No. 0543 min read
huh. What is this string, exactly?
A timestamp, a cron line, an exit code, an invisible Unicode character.
No. 0012 min read
I wrote 291 lines of C to get SSH through a corporate proxy in 2000. Linux distributions kept shipping it. Modern analysis has some things to tell me.
I wrote corkscrew[1]Ref. 1corkscrew en.wikipedia.org in an afternoon. A quarter century later I'm still discussing it, although I would have preferred to be discussing something other than its stack buffer overflow.
In 2000 I was behind a corporate HTTP proxy that let port 443 out and nothing else. I wanted SSH access to my own machine at home. The proxy spoke HTTP CONNECT[2]Ref. 2HTTP CONNECT rfc-editor.org, SSH spoke a raw TCP stream, and OpenSSH[3]Ref. 3OpenSSH openssh.com had this option nobody seemed to use, ProxyCommand. I wrote the thing to sit between them.
291 lines of C. Debian[4]Ref. 4Debian debian.org, Ubuntu, Red Hat, CentOS, FreeBSD and Cygwin have packaged it. Linux Magazine and 2600 reviewed it. It has a Wikipedia article. An afternoon's work has an encyclopedia entry now. I certainly didn't expect that.
I recently had the source put through GCC[5]Ref. 5GCC gcc.gnu.org static analysis, AddressSanitizer[6]Ref. 6AddressSanitizer clang.llvm.org, UndefinedBehaviorSanitizer, and a loopback mock proxy sending deliberately hostile responses. I wanted to know what 26-year-old C looks like under modern tooling, and, well... it looks like 26-year-old C. Fuck.
The big finding is a stack buffer overflow reachable from the proxy. The response handler does a read() into a 4096-byte buffer, doesn't add a terminator, and hands it to sscanf() with unbounded %s. Send 4096 non-whitespace bytes and you get a write one byte past the buffer. No code execution was demonstrated. A hostile proxy can still corrupt the client's stack, and I do not particularly enjoy typing that about my software.
The framing bug bothers me more, because I can't blame a typo. The code treats the first read() as the whole proxy response, and on a 200 it throws all of it away. If headers and the first bytes of the SSH greeting arrive in the same segment, the greeting goes with them. And with fragmented headers it tries to parse HTTP/1. and exits.
It worked for 25 years because proxies almost always send headers in their own packet. I wrote that assumption into the thing, and now I get to look at it again.
The rest I'd leave alone. But those damned buffers need terminators.
No. 0543 min read
A timestamp, a cron line, an exit code, an invisible Unicode character.
No. 0531 min read
A shell that can undo the last thing you did.
No. 0441 min read
Corkscrew fits in 291 lines, folks.
No. 0431 min read
Corkscrew reported success without establishing a tunnel.