All DNScat2 Sessions Are Now Encrypted by Default!

Hello everybody!

Now when you start a dnscat2 client, a key exchange with the server is performed by default and it uses a derived session key to encrypt all traffic. This prevents passive surveillance and IDS from seeing your traffic. But then it’s technically possible to launch a man-in-the-middle attack against dnscat2, but it’s unlikely.

By default, all connections are encrypted, and the server will refuse to allow cleartext connections. If you start the server with–security=open (or run set security=open), then the client decides the security level – including cleartext.

If you pass the server a –secret string then the server will require clients to authenticate using the same –secret value. That can be turned off by using –security=open or –security=encrypted (or the equivalent set commands).

Short authentication string inspired by ZRTP and Silent Circle is displayed on both the client and the server by default.  The user has to manually match the short authentication strings on the client and the server and if it does then the connection is legit but if not you could be a victim of a man-in-the-middle attack

There are 256 different possible words, so six words gives 48 bits of protection. While a 48-bit key can eventually be bruteforced, in this case it has to be done in real time, which is exceedingly unlikely.

Alternatively, a pre-shared secret can be used. When you start the server, you pass in a –secret value, such as –secret=pineapple. Clients with the same secret will create an authenticator string based on the password and the cryptographic keys, and send it to the server, encrypted, after the key exchange. Clients that use the wrong key will be rejected.

However this is not completely stealthy. A 512-bit value has to be sent via DNS, and a 512-bit response has to come back so it’s quite obvious.

After that, every packet has an unencrypted 40-bit (5-byte) header and an unencrypted 16-bit (2-byte) nonce. Three bytes that in the header that are constant, and the nonce is incremental. Any system that knows to look for dnscat2 will be able to find that. Then again no data leak would be there.

Additional overheads include Encrypted packets have 64 bits (8 bytes) signature on each packet. Since DNS packets have between 200 and 250 bytes of payload space, that means we lose ~4% of our potential bandwidth.

Additionally, there’s a key exchange packet and potentially an authentication packet taking two extra roundtrips over a fairly slow protocol.

The encryption/decryption/signing/validation are super fast, and it uses a stream cipher so the length of the messages don’t change. Nothing more than that really changes

If you want to turn off the encryption then you’ll have to manually hack the server or use a version of dnscat2 server <=0.03. But you’ll have to manually turn off encryption in the client; otherwise, the connection fails.

To disable encryption in the client- you can compile without encryption by using make nocrypto. You can also disable encryption at runtime with dnscat2 –no-encryption. On Visual Studio, you’ll have to define “NO_ENCRYPTION”. Note that the server, by default, won’t allow either of those to connect unless you start it with –security=open.

Some of the challenges faced in the process were – having to expose more information in the packets because DNS doesn’t have the connections/sessions concept; not being able to use Curve25519 for the key exchange, because there is no Ruby implementation; Finding a C implementation of ECC that doesn’t require libcrypto or libssl; Finding a working SHA3 implementation in Ruby ; and Dealing with DNS’s gratuitous re-transmissions and accidental drops was difficult and required hacker code.

Check out the full technical details: https://github.com/iagox86/dnscat2/blob/master/doc/protocol.md#encryption–signing


Source: Akati

Comments are closed.