Live data from Hacker News

RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

qualys.com

291–300 of 347 posts

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#291
post #271

Earlier quoted context omitted.

Why can't you call strcmp? I think a general practice of "only call functions that are explicitly blessed as async-signal-safe" is a good idea, which means not calling strcmp as it hasn't been blessed, but surely it doesn't touch any global (or per-thread) state so how can it corrupt program state? Update: according to https://man7.org/linux/man-pages/man7/signal-safety.7.html strcmp() actually is async-signal-safe a…

> surely it doesn't touch any global (or per-thread) state Not necessarily. An implementation might choose to e.g. use some kind of cache similar to what the JVM does with interned strings, and then a function like strcmp() might behave badly if it happened to run while that cache was halfway through being rebuilt.

Contrived example, never seen in reality.

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#293
post #209

Earlier quoted context omitted.

We ran iperf on our multi-cloud and on prem network. > Also, if we're talking about SSH connections, why does throughput matter? scp, among other things, runs over ssh.

>scp, among other things, runs over ssh. Ironically scp/sftp caused me more bandwidth headaches than wireguard/openvpn. I frequently experienced cases where scp/sftp would get 10% or even less of the transfer speed compared to a plain http(s) connection. Maybe it was due to packet loss, buffer size, or qos/throttling, but I wasn't able to figure out a definitive solution.

In almost all cases, the reason is OpenSSH's silly limitation of buffer sizes [1].

It limits the amount of data that's "in the cable" (which needs to be more if the cable is long).

> The default SSH window size was 64 - 128 KB, which worked well for interactive sessions, but was severely limiting for bulk transfer in high bandwidth-delay product situations.

> OpenSSH later increased the default SSH window size to 2 MB in 2007.

2 MB is still incredibly little.

It means that on a 100 ms connection, you can not exceed 160 Mbit/s, even if your machines have 10 Gbit/s.

OpenSSH is one of the very few TCP programs that have garbage throughput on TCP. This is also what makes rsync slow.

The people from [1] patched that.

You can support that work here: https://github.com/rapier1/hpn-ssh

In my opinion, this should really be fixed in OpenSSH upstream. I do not understand why it doesn't just use normal automatic TCP window size scaling, like all other TCP programs.

All the big megacorps and almost every other tech company in existence uses SSH, yet nobody seems to care that it's artificially 100x slower than necessary.

[1]: http://www.allanjude.com/bsd/AsiaBSDCon2017_-_SSH_Performanc...

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#294
post #248

From the diff introducing the bug [1], the issue according to the analysis is that the function was refactored from this: void sigdie(const char *fmt,...) { #ifdef DO_LOG_SAFE_IN_SIGHAND va_list args; va_start(args, fmt); do_log(SYSLOG_LEVEL_FATAL, fmt, args); va_end(args); #endif _exit(1); } to this: void sshsigdie(const char *file, const char *func, int line, const char *fmt, ...) { va_list args; va_start(args, fmt…

One of these: 1. Using a proper programming language that doesn't allow you to setup arbitrary functions as signal handlers (since that's obviously unsafe on common libcs...) - e.g. you can't do that in safe Rust, or Java, etc. 2. Using a well-implemented libc that doesn't cause memory corruption when calling async-signal-unsafe functions but only deadlocks (this is very easy to achieve by treating code running in si…

This comes across as quite scathing critique of an open source tool that has provided an extremely high standard of security and reliability over decades, despite being built on technologies that don’t offer the guardrails outlined in points (1) and (2).

Point (3) seems like a personal attack on the developers/reviewer, who made human errors. Humans do in fact make mistakes, and the best build toolchain/test suite in the world won’t save you 100% of the time.

Point (4) seems to imply that OpenSSH is not well-engineered, simple, or written by good programmers. While all of that is fairly subjective, it is (I feel) needlessly unkind.

I’d invite you to recommend an alternative remote access technology with an equivalent track record of security and stability in this space — I’m not aware of any.

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#295

I stopped exposing SSH to the internet years ago. Now I connect over WireGuard, and then run SSH through that when I need to remotely admin something.

I guess you could also spin up a OpenBSD server running SSH and use that as a jump host.

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#296
post #242
post #232

Earlier quoted context omitted.

There are several crates available which implement the dangerous parts of signal handling safely for you.

There are, but safety of their implementation is not checked by the language. Rust doesn't have an effect system nor a similar facility to flag what code is not signal-handler-safe. A Rust implementation could just as likely call something incompatible. Rust has many useful guarantees, and is a significant improvement over C in most cases, but let's be precise about what Rust can and can't do.

The crates that I have looked at work by installing their own minimal signal handler which then puts a message into a channel, or otherwise delivers the message that the signal was fired to your code in a safe way.

Of course, you are still trusting that the implementation is sound.

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#297
post #35
post #28

Earlier quoted context omitted.

Theo de Raadt made an, I think, cogent observation about this bug and how to prevent similar ones: no signal handler should call any function that isn't a signal-safe syscall. The rationale is that, over time, it's too way easy for any transitive call (where it's not always clear that it can be reached in signal context) to pick up some call that isn't async signal safe.

Exactly, yes :-) Signal handlers have so many hazards it's vital to keep them as simple as possible.

You should read the sigsev handler at google, it’s great, doing all kinds of things. Of course it’s going to crash at some point anyway….

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#299

Earlier quoted context omitted.

Similarly, safest is normal English means not completely safe, but more safe than the other options. So safe > safest > safer > safe-ish > unsafe.

Wait, that seems backwards to me as a native English speaker. The superlative version feels more safe. Safest > Safe > (…)

It's a bit ambiguous and depends on context, which is why I said 'at least in CS', since for whatever the particular topic is 'safe' and 'unsafe' is likely to have a fairly strict meaning.

In general you're right. For safety it's just that 'safest' implies some sort of practicality: the best - most safe - from a set of options. But the safest option isn't necessarily strictly safe.

(Say your dog's stuck on a roof on a windy day, you decide the safest option is scaffolding (safer than a ladder or free climbing), but it's not safe, you just insist on rescuing your dog.)

Re: RegreSSHion: RCE in OpenSSH's server, on glibc-based Linux systems

#300
post #271

Earlier quoted context omitted.

> surely it doesn't touch any global (or per-thread) state Not necessarily. An implementation might choose to e.g. use some kind of cache similar to what the JVM does with interned strings, and then a function like strcmp() might behave badly if it happened to run while that cache was halfway through being rebuilt.

Contrived example, never seen in reality.

You could be surprised.

For example, recently I wanted to call `gettid()` in a signal handler. Which I guessed was just a simple wrapper around the syscall.

However, it seems this can cache the thread ID in thread local storage (can't remember exact details).

I switched to making a syscall instead.

Post reply on HN