Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggest using a stealth Onion service for even greater security. #48

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions _layouts/no.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html>

{% include head.html %}

<body>
<div class="page-content">
<div class="wrapper">
{{ content }}
</div>
</div>
</body>

</html>
32 changes: 24 additions & 8 deletions _posts/2015-01-04-secure-secure-shell.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Both provide [forward secrecy][forward-secrecy] which the NSA hates because they
The server and the client will end up with a shared secret number at the end without a passive eavesdropper learning anything about this number.
After we have a shared secret we have to derive a cryptographic key from this using a key derivation function.
In case of SSH, this is a hash function.
[Collision attacks][sloth] on this hash function have been proven to allow downgrade attacks.

DH works with a multiplicative group of integers modulo a prime.
Its security is based on the hardness of the [discrete logarithm problem][dlp].
Expand Down Expand Up @@ -149,8 +150,8 @@ If you don't want that, remove any `ssh-keygen` commands from the init script.

<pre><code id="server-keygen">cd /etc/ssh
rm ssh_host_*key*
ssh-keygen -t ed25519 -f ssh_host_ed25519_key < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key < /dev/null</code></pre>
ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" < /dev/null
ssh-keygen -t rsa -b 4096 -f ssh_host_rsa_key -N "" < /dev/null</code></pre>

### Client authentication

Expand Down Expand Up @@ -182,7 +183,7 @@ Recommended `/etc/ssh/ssh_config` snippet:

<pre><code id="client-auth-pubkey">Host *
PubkeyAuthentication yes
HostKeyAlgorithms [email protected],[email protected],ssh-[email protected],ssh-ed25519,ssh-rsa</code></pre>
HostKeyAlgorithms [email protected],[email protected],ssh-ed25519,ssh-rsa</code></pre>

Generate client keys using the following commands:

Expand Down Expand Up @@ -237,7 +238,7 @@ We have to consider the following:
* *Block size*:
Does not apply to stream ciphers.
At least 128 bits.
This eliminates 14 because CAST has a 64 bit block size.
This eliminates 13 and 14 because those have a 64 bit block size.
* *Cipher mode*:
The recommended approach here is to prefer [AE][ae] modes and optionally allow CTR for compatibility.
CTR with Encrypt-then-MAC is provably secure.
Expand Down Expand Up @@ -334,6 +335,13 @@ The NSA has a database of stolen keys - you do not want your key there.

## System hardening

OpenSSH has some undocumented, and rarely used features.
UseRoaming is one such feature with a known vulnerability.

Recommended `/etc/ssh/ssh_config` snippet:
<pre><code id="client-features">Host *
UseRoaming no</code></pre>

This post is not intended to be a comprehensive system security guide.
Very briefly:

Expand Down Expand Up @@ -362,7 +370,7 @@ It provides an additional layer of encryption and server authentication.
People looking at your traffic will not know your IP, so they will be unable to scan and target other services running on the same server and client.
Attackers can still attack these services but don't know if it has anything to do with the observed traffic until they actually break in.

Now this is only true if you don't disclose your SSH server's fingerprint in any other way.
Now this is only true if you don't disclose your SSH server's fingerprint in any other way. To mitigate this, consider [using a stealth Onion service](https://www.torproject.org/docs/tor-manual.html#HiddenServiceAuthorizeClient) so that attackers cannot even observe the presence of your hidden service.
You should only accept connections from the hidden service or from LAN, if required.

If you don't need LAN access, you can add the following line to `/etc/ssh/sshd_config`:
Expand All @@ -372,15 +380,22 @@ If you don't need LAN access, you can add the following line to `/etc/ssh/sshd_c
Add this to `/etc/tor/torrc`:

<pre><code id="hidden-service">HiddenServiceDir /var/lib/tor/hidden_service/ssh
HiddenServicePort 22 127.0.0.1:22</code></pre>
HiddenServicePort 22 127.0.0.1:22
# Uncomment this if you want the added security of Tor-level authentication.
#HiddenServiceAuthorizeClient stealth my_client
</code></pre>

You will find the hostname you have to use in `/var/lib/tor/hidden_service/ssh/hostname`.
You also have to configure the client to use Tor.
For this, socat will be needed.
You also have to configure the client to use Tor, and then proxy your SSH connection through the local Tor client.
If you chose to configure stealth client authorization, you must also further [configure your client's `torrc` file to access the stealth Onion service](https://github.com/micahflee/onionshare/wiki/Stealth-Onion-Services#how-to-receive-files-with-stealth-onion-services).
To proxify SSH, however, either `socat` or the more ubiquitous `nc` will be needed.
Add the following line to `/etc/ssh/ssh_config`:

<pre><code id="onion-proxy">Host *.onion
# When using socat:
ProxyCommand socat - SOCKS4A:localhost:%h:%p,socksport=9050
# When using nc:
#ProxyCommand nc -x localhost:9050 %h %p

Host *
...</code></pre>
Expand Down Expand Up @@ -468,3 +483,4 @@ I promise not to use `git push -f`.
[sssh-wiki]: https://github.com/stribika/stribika.github.io/wiki/Secure-Secure-Shell
[changelog]: https://github.com/stribika/stribika.github.io/commits/master/_posts/2015-01-04-secure-secure-shell.md
[bug779880]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=779880
[sloth]: https://www.mitls.org/downloads/transcript-collisions.pdf
46 changes: 46 additions & 0 deletions _posts/2015-08-07-why-cyber-deterrence-is-bullshit.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
layout: post
title: "Why cyber deterrence is bullshit"
tags: [bullshit, cybercybercyber, deterrence]
---

You may have heard of [this brilliant idea](https://uk.businessinsider.com/us-retaliation-against-china-for-opm-hacks-2015-8).
That's right, "hack back" as foreign policy.
It does not and will never work.

The reasons why this is utter bullshit should be all too obvious, but my Twitter account is locked and I have nothing better to do, so here goes:

1. *The word cyber.*
Whenever you hear it, question the speaker's competence.
1. *Easy access.*
To build nuclear weapons, you need: relatively rare fissionable materials, huge enrichment facilities, knowledge, and ICBMs.
To hack, you need: a computer, electricity, knowledge, and Internet access.
You may be able to deter a few rational entities capable of building nukes, but not every single child capable of hacking OPM.
There is nothing even close to perfect rationality on the Internet.
1. *Attribution.*
Radars and satellites can clearly show where the missiles are coming from.
No such device exists for detecting the origin of a breach.
Attribution is purely guesswork, based on things like the language of strings found in the malware, source IPs, etc.
It's like sending a postcard, then trying to figure out who read it.
Does that sound like perfect detection?
1. *Working defense.*
Missile defense systems are actually more dangerous that the nukes they are trying to defend against.
This is because they have a [very interesting property](https://en.wikipedia.org/wiki/Pre-emptive_nuclear_strike#Destabilizing_role_of_missile_defense):
They reduce the second strike capability of one side, making counterforce first strike the logical choice for the other.
The reason we are still all here, reading this post, is because covering large areas with such defenses is not feasible.
This is not the case for defending computers against intrusion.
Yes, attackers have a clear advantage over defenders, that is to say, hacking will always be possible.
But it is significantly more difficult, and the effect less devastating, if the opponent just doesn't have an OPM equivalent.
There goes your second strike.
1. *It is not a fucking weapon.*
The damage caused by even the worst breaches is nowhere near the damage caused by a thermonuclear explosion.
Even conventional weapons cause more damage, and are more scary.
This is also supported by the fact that no sane person would risk armed conflict over hacking incidents.
No one is afraid of getting pwned.

Today's attackers don't even need their advantage.
They get in because we let them.
We should focus on exploit mitigation (Grsecurity), isolation (Qubes), sandboxed multiprocess architectures (Chrome, qmail), encryption, and fixing shit.
Instead we are wasting time trying to make the attribution dice work, listening to fumbling idiots threaten the Chinese, and looking for a magic security device that solves everything if we just connect it to the network.

We know what to do and we know how to do it.
104 changes: 104 additions & 0 deletions _posts/2015-11-23-service-discovery-and-authentication.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
---
layout: post
title: "Service discovery and authentication"
tags: [java,security,zookeeper,tls]
---

[ZooKeeper][zk] is a popular choice for service discovery in distributed systems.
It is a hierarchical key-value store with very strong consistency guarantees.
What makes it a good choice for service discovery is its capability to create temporary tree nodes that disappear when the session that created it is disconnected.
Another important feature is sequential nodes - nodes that have a consistent counter appended to their name.
You can use these for implementing distributed locking for example.
This post is about the authentication problems that appear as a result of introducting service discovery into a distributed system.

# Service discovery

The exact details of implementing a [service discovery protocol][zksvc] using ZooKeeper is outside the scope of this document.
I want to describe it in enough details so that we can understand its security properties.
Each service that's running and ready to respond to requests opens a persistent connection to Zookeeper.
What usually happens is there is a root node, say /services, and it creates a temporary, sequential node:

<code>
/services/foo-service-1 = https://somehost.inthecloud.internal:6666
/services/foo-service-3 = https://otherhost.inthecloud.internal:12345
</code>

If you want to talk to this foo-service, you look in this root node and retrieve all the registered foo-service hostnames.
You pick one randomly, or using round-robin, or what have you, and talk to that.
If it fails, you try another.
If you shut down foo-service, or it crashes, the temporary node is removed and other services will no longer try to talk to it.

# Authenticating hostnames

In the example above, we are using HTTPS URLs, so you probably want some kind of internal CA to sign the certificates.
(You might want to use some different protocol, Kerberos maybe.)
You connect to the host and you can be sure it's really that host, no one is eavesdropping, all the good things.

There are two problems with this.
First, you are using Zookeeper because you don't want to care about what host is running which service.
You certainly don't want to sign a new certificate for each one, deploy the private key to that host, etc.
You can do this.
It is possible.
You can even automate it if you don't mind having an online CA, that is not only easier to abuse, but also limits your availability.

The second, and even more important problem is _authenticating the wrong thing_.
What if ZooKeeper lies to you?
What if a compromised service publishes a hostname for some other service?
You connect to that, verify that its certificate is correct, and proceed talking to the wrong service without noticing anything is wrong.
Now, ZooKeeper is capable of controlling who can write what node, so you can create a structure like this:

<code>
/services/foo-service/foo-service-1 = https://a.inthecloud.internal:6666
/services/foo-service/foo-service-3 = https://b.inthecloud.internal:12345
/services/bar-service/bar-service-0 = https://c.inthecloud.internal:6666
/services/baz-service/baz-service-2 = https://d.inthecloud.internal:4444
</code>

You have to set up the permissions so that no one can write /services, the user running foo-service can only write /services/foo-service, etc.
This still doesn't help if Zookeeper itself is compromised.

This way we must trust Zookeeper and the CA.

# Authenticating service names

There is a better way.
We don't care about the hostname, the same way we don't care about the IP address.
We don't sign certificates for IP addresses.
We can sign a certificate for the service name, as in, CN=foo-service.
Actually, we don't even have to sign it - the (self-signed) certificate can be included with the code of its clients.

The main disadvantage of this approach is having to write custom certificate validation code, which I have done in Java.
In Java it's actually pretty simple, the interfaces of interest are [X509KeyManager][keyman] and [X509TrustManager][trustman].
Some of the methods relating to CAs will be simple stubs.
There are "extended" versions of both, with more methods you don't need.
I will publish the code, but I did this at work, and have not had time to reimplement it in the public domain.

This way we don't have to trust Zookeeper, and we don't have to trust the CA either (we don't have one).
The only thing we do have to trust is that the certificates included in the code are correct, but if someone can change that, they can change the code too.

There is still the matter of deploying the private keys to the hosts, but now it can be the same one for each instance of the same service.
This could be on a NAS, or scp'd to the local machine before starting the service that needs it.
Obviously we also have to trust that the ACLs will protect the private key but this is no worse than the previous method.

# Authenticating the client

We must not forget to authenticate the client certificate as well.
This is usually not done for browsers, but for inter-service traffic it is essential.
You might want to use a different CN if the same service is sometimes the server and sometimes the client.
Or you can use the same certificate but I don't recommend it.
If they are different you can use the CA system for client authentication and use the embedded cert system for server authentication.
Either way, this means you have to embedd the certificate of the client in the server code.

There are all these certificates embedded everywhere.
It doesn't sound too maintainable, but what's really going on here is each service consists of 3 files:

- A server JAR that runs the server and doesn't contain any certs.
- A client JAR that's a library imported by the clients, and contains the cert for the service.
- A certificate, to be used for client authentication. (Or not, you could use a CA here.)

It's not that bad.

[keyman]: https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/X509KeyManager.html
[trustman]: https://docs.oracle.com/javase/8/docs/api/javax/net/ssl/X509TrustManager.html
[zk]: https://zookeeper.apache.org/
[zksvc]: http://blog.arungupta.me/zookeeper-microservice-registration-discovery/
2 changes: 1 addition & 1 deletion about.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ I am stribika.
I [write code](https://github.com/stribika) and I [tweet](https://twitter.com/stribika).
Also, [stackoverflow](https://stackoverflow.com/users/128514/stribika).

* PGP fingerprint: `9AB5 E3A6 0AE3 F091 0B86 056F CFB7 F248 7B01 6D87` and [public key](/assets/rsa-pubkey-7B016D87.txt)
* PGP fingerprint: `0406 629F F94F 92BF DEE5 FDA7 A11E 98D6 4B0F C61E` and [public key](/assets/rsa-pubkey-4B0FC61E.txt)
* OTR fingerprint: `4218BF59 537FED11 30D72874 423FECC4 75D849D8`
* BTC address: `18JbJ37A5VW5FKpbaXgfeAixSyVVac6fa4`

Expand Down
Binary file added assets/NSA-Emails-About-Snowden-s-Concerns.pdf
Binary file not shown.
Binary file added assets/no.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
51 changes: 51 additions & 0 deletions assets/rsa-pubkey-4B0FC61E.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
uEUm2KMgyAvYQH8Cfto=
=WbNe
-----END PGP PUBLIC KEY BLOCK-----
Loading