The thing about port knocking is that if you're on a host where you don't have the ability to port-knock, then you're not able to connect.
This can turn into a footgun: you're away from your usual device, something happens and you desperately need to connect, but now you can't because all the devices in your vicinity don't have the ability to perform $SECURITY_FEATURE_X so that you can connect, and you're screaming at yourself for adding so much security at the expense of convenience.
This could happen as easily as restricting logins to SSH keys only, and not being able to use your SSH key on whatever host you have available at the time, wishing you'd have enabled password authentication.
> The thing about port knocking is that if you're on a host where you don't have the ability to port-knock, then you're not able to connect.
If that's important, one should be able to set up port knocking such that you're able to do the knocks even by changing the port in a sequence by hand on e.g. a web browser address bar.
Naive knocking isn't good as a primary security mechanism, but it lowers your attack surface and adds defense in depth.
It means that people who can't intercept traffic can't talk to the ssh server-- and that's most attackers at the beginning phases of an attack. And even someone who can intercept traffic needs to wait for actual administrative activity.
Defense in depth has value I agree, but I think it can also be counterproductive in some cases. Every layer can also be buggy and have vulnerabilities, which can often leak (e.g. into code execution) and compromise the whole system (bypassing layers). What happened in this case seems to be a case of maintained hijacking and introducing vulnerabilities. Adding an additional dependency (of say a port-knocking library) doesn't look great in that regard, if the dependency can be hijacked to add remote code execution capabilities. And that library is likely a lot less scrutinized than OpenSSH!
Also underrated I think is security by simplicity. OpenSSH should be extremely simple and easy to understand, such that every proposal and change could be easily scrutinized. Cryptographic constructions themselves are almost mathematically proven invulnerable, then a small codebase can go most of the way to mathematically provable security (bonus points for formal verification).
But for this kind of system there's usually some kind of human vulnerability (e.g. system updates for your distro) in the loop such that the community needs to remain watchful. (It's fun to consider an application that's proven correct and doesn't need updating every again, but usually that's not practical)
> Adding an additional dependency (of say a port-knocking library) doesn't look great in that regard, if the dependency can be hijacked to add remote code execution capabilities.
Port knocking infrastructure can be minimal, knowing nothing but addresses knocking. It can also be completely outside the protected service on a gateway.
> OpenSSH should be extremely simple and easy to understand, such that every proposal and change could be easily scrutinized.
But OpenSSH intrinsically is going to have a much larger attack surface.
> then a small codebase can go most of the way to mathematically provable security (bonus points for formal verification).
It's worth noting this would not have helped against this attack:
* It was against another dependency, not openssh
* The actual vulnerability didn't occur in the code you'd inspect as part of verification processes today. (I don't think anyone is formally verifying build process).
Good points, I would say that defense in depth is useful when the layers of defense need to all be broken (more or less) independently for a successful attack (this fails only if you add layers that expose vulnerabities compromising your system). E.g. usually a sandbox satisfies this criterion.
Also, whenever some layers may allow compromising everything, the supply chains of the layers should be minimal or correlated (same supplier), to avoid increasing such supply chain risks.
Don't have to do anything too complicated. Here's the knocker code in a short Bash script, produced by GPT4:
~ % gpt4 'write a very short bash script that takes the number stored in ~/.ssh/knock_seq, increments it by 1 and saves it to the file. It then takes the new number and concatenates it with the value stored in the file ~/.ssh/secret. It pipes the resulting string to sha1sum, spitting out binary. It then takes both the resulting sha1sum and the number used and pipes their concatenation to "nc -u $host $(cat ~/.ssh/knocking_port)". be brief'
The knockee PoC should also be straightforward, can use socat + udp-listen + fork with a script that checks that input matches `sha1sum(secret||num)||num` and `num>previously_seen_num`, and if so, adds an iptables rule.
This should prevent against replays. Throw in some rate limits somewhere maybe to not get DDoSed, especially if you let socat `fork`.
Yeah you could but wouldn’t it defeat the purpose of being basically a secret knock before you can give the password? The password should be the ssh password.
This would be just to allow you to connect to the server. If there was a vulnerable sshd on port 22, an adversary would have to know the port knocking sequence to connect to sshd and run the exploit.
This looks related to some other problem:
- There is Alice's server which provide service X
- There are clients like Bob who needs this service.
- There is Mallory who thinks clients doesn't need such service. Mallory have significant resources (more than Alice or Bob).
- Mallory thinks it's ok to block access to Alice' server IF it's known that it's Alice's server and not some random site. Mallory sometimes also thinks it's ok to block if protocol is unknown.
This problem solved by XRay in all of it's versions. It could be possible (if overkill) to use mostly same methods to authenticate correct user and provide eir access.
I've actually been behind a firewall that blocked outgoing connections except on several well-known ports. Had to run my SSH server over the port usually used for HTTPS just to get it unblocked.
Port knocking involves sending a packet to certain ports on a host. It's overkill but typing http://host:port/ in your browser will, as part of trying to make a TCP connection, send a packet to that port.
Thanks, I didn't realize port knocking could be done manually like this as a way to "unlock" an eventual regular ssh attempt outside the browser. This makes sense now and is super clever!
That's just the usual way of attempting to connect to an HTTP server running on a different port. Sometimes you see websites hosted on port 8080 or something like that.
Absolutely, everything in security is a tradeoff. I guess the real point is that there should be layers, and even though you should never rely on security through obscurity, you should still probably have a bit of obscurity in the mix.
I wouldn't really consider port knocking to be that effective of a way to block connections. It is really only obscure, but port knocking software is very accessible. So if you know a port needs to be knocked, it's not hard for an attacker to get to it.
The main benefit of port knocking is that it allows you to present your ports as normally closed. If you have a system and you are worried about it getting port scanned for whatever reason, it makes sense to have a scheme where the ports are closed unless it receives a knock. So if someone gets access they shouldn't for whatever reason and pulls a portscan off, the information they get about your system is somewhat limited.
In this scheme, it would be much better to have an access point you authenticate with and then that handles the port knocking for the other devices. So it is a kind of obscure method that is really only useful in a specific use case.
As far as SSH keys go, I would argue that SSH support is so ubiquitous, and SSH access is so powerful that it is a reasonable security tradeoff. I also don't think that SSH ports should be exposed to the internet, unless it is a specific use case where that is the whole point, like GitHub. I'm very down on connecting directly through SSH without network access. The xz situation has validated this opinion.
I personally don't know any application where you really need supreme admin access to every device, from any device, from anywhere in the world, while at the same time it has extreme security requirements. That's a pretty big task. At that point, constructing a dedicated, hardened access point that faces the internet and grants access to other devices is probably the way to go.
> I'm very down on connecting directly through SSH without network access. The xz situation has validated this opinion.
Did it? At the point an attacker has remote code execution, couldn't they just as easily pivot into an outgoing connection to some command and control server? I don't see how some intermediary access point would have alleviated this problem. If the call is coming from inside the house, the gig is already up.
> At the point an attacker has remote code execution
The attacker doesn't have remote code execution in the xz case unless they can speak to your port 22. Port knocking prevents them from doing so, provided they don't know how to knock.
Assuming they have injected code into the sshd executable, couldn't that code just do the exploit without a connection? What I'm saying is that the structure of this payload is the way it is because sshd is accessible. Had it not been accessible, the payload just wouldn't have required an external connection.
I mean, this is the twisting logic. xy hack put's a backdoor in sshd. You need to access sshd port to go through the back door and get RCE. Hacker could have put something even more nefarious that could phone home somewhere. We would like to think that would have been a little easier to spot, but who knows.
To me, that is what makes this hack so noteworthy. Hacker got access, and then kept playing the long game. Very spooky. And yes, someone capable of this probably has a plan for gaining network access if they had a target in mind. Even with best security practice, this rabbit hole goes pretty deep.
I was too, but the past few years their government server blocks have been pen-testing servers without authorization.
It is apparently a free service they offer people even when told to get stuffed.
=)
My spastic ban-hammer active-response list i.e. the entire block gets temporarily black-holed with a single violation:
AU
BG
BR
BZ
CN
ES
EE
FR
GB
HR
IL
IN
ID
IR
IQ
JP
KG
KR
KP
KW
LV
MM
MX
NI
NL
PA
PE
PK
PL
RO
RU
RS
SE
SG
TW
TH
TR
YE
VN
UA
ZA
ZZ
In general, it is a standard shore-wall firewall rule in perl, and the standard ssh protocol wrapper mod.
These are very well documented tricks, and when combined with a standard port 22 and interleaved knock ports tripwire 5 day ban rules... are quite effective against scanners too.
I am currently on the clock, so can't write up a detailed tutorial right now.
At least TOTP is just a long, random, server-assigned password, where you you don't type the whole thing into during login attempts.
You can write down the full TOTP secret, and make new 'TOTP keys' whenever you want. Suggested apps: Firefox Extension named "TOTP", and Android App named "Secur". You don't need the heavier apps that want you to create accounts with their company.
Using a TOTP key only provides a little more protection than any other complex password, since you're not typing in the whole thing during a login attempt.
My solution to this has been creating a public bastion server and use Wireguard. Wireguard listens on a random UDP port (port knocking is more difficult here.) This client is set up to have a dynamic endpoint so I don't need to worry about whitelisting. The key and port information are stored in a password manager like Vaultwarden with the appropriate documentation to connect. Firewall rules are set to reject on all other ports and it doesn't respond to ICMP packets either. A lot of that is security through obscurity but I found this to be a good balance of security and practicality.
I've seen this discussed a fair bit, and always the recommendation is to use wire guard and expose ssh only to the "local network" e.g. https://bugs.gentoo.org/928134#c38
First, I don't see how this works where there's a single server (e.g. colocation).
Second, doesn't that just make Wireguard the new hack target? How does this actually mitigate the risk?
This can turn into a footgun: you're away from your usual device, something happens and you desperately need to connect, but now you can't because all the devices in your vicinity don't have the ability to perform $SECURITY_FEATURE_X so that you can connect, and you're screaming at yourself for adding so much security at the expense of convenience.
This could happen as easily as restricting logins to SSH keys only, and not being able to use your SSH key on whatever host you have available at the time, wishing you'd have enabled password authentication.