Archive

Archive for the ‘Security’ Category

SSH Proxy: Server and Client Side of Using an SSH User Without Shell as Proxy Server

April 30, 2016 Leave a comment

Accessing services on an internal network over a proxy reachable from the Internet.

Imagine you want one of your machines to become a proxy for external users to be able to access local resources or the internet as if they were on that machine. You could run a dedicated proxy server for that, but if the machine provides SSH and you want an easy solution, you can use SSH as well – without risking any shell-related issues (like this user also having access to the local file system).

Why would you want stuff like that in the first place? That’s what proxy servers (and most frequently VPNs) are made for: to access country-, company-, or university-internal resources from outside of that network just as you would from the inside.

Server side

The server side is rather easy. Let’s assume we call that user “sshproxy”. The important thing is to not give your proxy user a shell, which we do here during creation of the user:

sudo useradd -m -d /home/sshproxy -s /bin/false sshproxy # create user and home directory, disable shell

The user’s password is disabled by default (you can check that there’s a ! in /etc/shadow for the sshproxy user). If you don’t want to use passwords but private-public keys (which I would recommend): in /home/sshproxy create the .ssh/ folder and the .ssh/authorized_keys file and ensure they’re readable for the sshproxy user. There you need to add the ssh public keys of people that should be allowed to use the ssh proxy. The cool thing about it is that different real life users can make use of the same sshproxy user: you just need to add to manage the keys of real life users for the sshproxy user. Further, you likely don’t want the sshproxy user to be able to change the authorized keys, therefore make the file read only for that user (e.g. root owned + writeable by owner only). If you have an AllowUsers section in your /etc/ssh/sshd_config, you need to add the sshproxy user there and restart ssh. That’s it on the server side.

User side

If you’re one of the users that need to generate their ssh keypair, you can have a look at:

https://help.ubuntu.com/community/SSH/OpenSSH/Keys#Generating_RSA_Keys
(very easy to understand)

https://stribika.github.io/2015/01/04/secure-secure-shell.html
(details that are good to know if you want to have more secure keys = not so easy to crack)

If you use RSA then use at least 2048 bit key length (4096 can’t hurt…), e.g. with ssh-keygen with the “-b 4096” parameter. If you’re on a Windows machine: you can do the same using e.g. Putty. Don’t forget to use a good password to protect your private key file (usually the “id_rsa” file) and never disclose it – servers only need your public key (usually “id_rsa.pub”).

Using the proxy via Linux shell

Everything’s built in, just use the following command.

ssh -D 8080 -N sshproxy@YOUR-IP-OR-URL -p YOUR-PORT

This command opens the local port 8080 (on the client machine) for proxy tasks. YOUR-PORT-URL and YOUR-PORT correspond to the SSH server running on the server machine. If everything worked fine you won’t get any response in the shell – just leave the terminal open. Make sure your private key file is in ~/.ssh/id_rsa or provide it explicitly with “-i”. If you can’t access the server try removing the “-N”. Then you should see that the server logs you in and out immediately (this means everything works fine from the SSH, proxy and tunnel side – if you add -N again, you should be fine therefore). You can check your local opened ports with nmap (“nmap localhost”). If port 8080 is not in the list before login and opened after login your tunnel works.

Using the proxy via Putty

  • address: YOUR-IP-OR-URL (where SSH server is running)
  • port: YOUR-PORT (where SSH server is running)
  • user: sshproxy
  • Enable the check box “Don’t start a shell or command at all” in “Connection-SSH”
  • Specify your private key in “Auth”
  • Tunnels: add a “dynamic tunnel” on “local port 8080”, leave destination open (should state “D8080” in Putty after you apply)

Sending data to your local port

As you now have a tunnel on port 8080 on your local machine open, you need to send request to this port, instead of your standard gateway. E.g. for your browser you can achieve that configuring the browser to use a proxy (e.g. Firefox: FoxyProxy AddOn: set address “localhost” and port “8080”).

Btw: you can do other cool things with that proxy as well, such as reverse port tunnelling, circumventing firewalls etc. But you should ensure that this is allowed in the company/country you’re in before you get yourself into troubles.

Git security: enabe fsckobjects in ~/.gitconfig:

February 3, 2016 Leave a comment

In order to prevent possible tampering with code in git repositories you work with (e.g. malicious manipulation of objects during clone, fetch, push…), check if these lines exist in your ~/.gitconfig and add them, if they don’t:

[transfer]
fsckobjects = true
[fetch]
fsckobjects = true
[receive]
fsckObjects = true

These enable git checking transferred objects for their integrity using their computed hashes.

Original idea from here: https://groups.google.com/forum/#!topic/binary-transparency/f-BI4o8HZW0
(and the corresponding bug on Debian here: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=813157)

Cracking RC4 messages that use weak RC4 reinitialization for each message part

April 12, 2015 Leave a comment

This post deals with a short excerpt of a security and hacking related exercise at the University of Applied Sciences Upper Austria, Campus Hagenberg: we obtain the plaintext from an intercepted RC4 encoded message, from which we know that it uses an easy to crack re-initialization of the RC4 cipher for each message part.

The problem

Imagine we have intercepted a secret message split into 11 message parts, each (but the last) consisting of 40 1-byte characters:

0xd9, 0xef, 0x7b, 0x6e, 0xca, 0xb5, 0x12, 0xa0, 0x4f, 0x4b, 0x56, 0xb4, 0x94, 0xdf, 0x27, 0xed, 0xf8, 0xcc, 0x64, 0x94, 0xeb, 0x5a, 0x77, 0xea, 0x9b, 0x76, 0xdf, 0xe9, 0x18, 0x02, 0xc6, 0x36, 0x19, 0x1f, 0xc8, 0xf2, 0x5a, 0xa8, 0xda, 0xe7,
0xb7, 0xd3, 0x5f, 0x4e, 0x89, 0x9f, 0x01, 0xa9, 0x0e, 0x4c, 0x5c, 0xb6, 0xc0, 0xdc, 0x2e, 0xfa, 0xbd, 0xbf, 0x63, 0xb4, 0xa4, 0x42, 0x77, 0xb3, 0x98, 0x62, 0xd5, 0xf0, 0x5d, 0x07, 0xdc, 0x62, 0x17, 0x4d, 0xca, 0xe6, 0x5a, 0xa8, 0xdd, 0xec,
0xf9, 0xd3, 0x5c, 0x47, 0x85, 0x86, 0x05, 0xab, 0x5d, 0x4c, 0x5b, 0xf0, 0xc7, 0xc2, 0x22, 0xf8, 0xb4, 0xe6, 0x17, 0xb8, 0xa4, 0x5f, 0x66, 0xb3, 0x80, 0x79, 0xd9, 0xec, 0x18, 0x1d, 0xc0, 0x35, 0x51, 0x4b, 0xca, 0xab, 0x19, 0xaf, 0xc2, 0xe6,
0xe4, 0xc5, 0x0f, 0x5f, 0x82, 0x93, 0x40, 0xb7, 0x47, 0x58, 0x5b, 0xa4, 0x94, 0xdb, 0x2e, 0xfa, 0xb9, 0xf2, 0x52, 0xa8, 0xae, 0x43, 0x61, 0xb3, 0xbc, 0x7e, 0xc2, 0xf3, 0x18, 0x18, 0xd6, 0x62, 0x1c, 0x50, 0xc1, 0xe2, 0x1c, 0xae, 0xce, 0xe8,
0xe3, 0xc9, 0x40, 0x45, 0x99, 0xd6, 0x32, 0x96, 0x6f, 0x1f, 0x56, 0xbe, 0xd7, 0xd9, 0x36, 0xf8, 0xac, 0xf6, 0x58, 0xb2, 0xeb, 0x46, 0x7d, 0xe1, 0x80, 0x64, 0x96, 0xec, 0x59, 0x0c, 0x8f, 0x24, 0x10, 0x4c, 0xd1, 0xee, 0x08, 0xe7, 0x8d, 0xa9,
0xc3, 0xef, 0x6b, 0x64, 0xca, 0xb3, 0x0e, 0xa6, 0x5c, 0x46, 0x43, 0xa4, 0x94, 0xc9, 0x26, 0xfc, 0xbb, 0xf0, 0x5e, 0xb2, 0xeb, 0x41, 0x60, 0xfa, 0x9d, 0x76, 0xc2, 0xfe, 0x18, 0x1e, 0xca, 0x3b, 0x02, 0x1f, 0xd2, 0xe2, 0x0e, 0xaf, 0x8d, 0xce,
0xc7, 0xe7, 0x0f, 0x41, 0x9f, 0x85, 0x14, 0xe5, 0x4c, 0x5a, 0x13, 0xb2, 0xd1, 0x8b, 0x3c, 0xfd, 0xaa, 0xfa, 0x17, 0xbe, 0xae, 0x52, 0x73, 0xe6, 0x98, 0x72, 0x96, 0xef, 0x50, 0x10, 0xd6, 0x62, 0x19, 0x5e, 0xd3, 0xee, 0x5a, 0xa5, 0xc8, 0xec,
0xf9, 0x80, 0x4a, 0x53, 0x9a, 0x99, 0x12, 0xb1, 0x4b, 0x5b, 0x13, 0xa5, 0xda, 0xdb, 0x3d, 0xe7, 0xac, 0xfa, 0x54, 0xa8, 0xae, 0x55, 0x32, 0xc4, 0x82, 0x7b, 0xda, 0xbb, 0x4b, 0x10, 0xc1, 0x26, 0x51, 0x4b, 0xcd, 0xee, 0x17, 0xe7, 0xf9, 0xc5,
0xc4, 0x80, 0x5f, 0x59, 0x85, 0x82, 0x05, 0xa6, 0x5a, 0x5a, 0x57, 0xf0, 0xd6, 0xde, 0x3b, 0xa8, 0xbb, 0xfe, 0x59, 0xfc, 0xb2, 0x5e, 0x67, 0xb3, 0x9f, 0x65, 0xc3, 0xe8, 0x4c, 0x55, 0xfb, 0x0e, 0x22, 0x1f, 0xf5, 0xea, 0x09, 0xb4, 0xda, 0xe6,
0xe5, 0xc4, 0x0f, 0x4d, 0x85, 0x84, 0x40, 0xa1, 0x4f, 0x49, 0x5a, 0xb4, 0xd0, 0xde, 0x21, 0xe6, 0xb6, 0xfa, 0x43, 0xfc, 0xa0, 0x54, 0x6b, 0xb3, 0x82, 0x64, 0x96, 0xc2, 0x48, 0x33, 0xcd, 0x26, 0x25, 0x73, 0xce, 0xe8, 0x2e, 0x8a, 0xc8, 0xcb,
0xff, 0xf6, 0x5a, 0x0b, 0xca, 0xb2, 0x01, 0xb3, 0x47, 0x5b

We know all these message parts have been encrypted using RC4 with a known to be easy to crack reinitialization of the RC4 stream for each message part. We also know the message plaintext only contains letters and whitespaces. The task is: obtain the plaintext. How to do so?

The solution

We know all 11 message parts have been encrypted using the same key stream (as the RC4 cipher has been re-initialized for each message using the same secret key). To avoid confusion here: as stream cipher, RC4 gets initialized from a secret key (e.g. the user’s password) and generates a continuous key stream from it. Each time a RC4 cipher is initialized this way, the generated key stream is exactly the same. Therefore, the RC4 reinitialization for each package causes the key stream to be exactly the same for all messages. RC4 does an XOR on the key stream and the plaintext to obtain the ciphertext. Hence, an XOR with the key stream used for all 11 message ciphertexts causes these to become correct plaintext. We further know that valid plaintext only allows certain characters. Therefore it’s possible to try through all 255 possibilities per keystream character: XOR each one with all corresponding characters of all ciphertexts and keep only those, where all resulting plaintext characters are actually allowed ones. By doing so we generate a list of valid keystreams in an effective way (which by doing an XOR on the ciphertext all result in valid plaintext). Trying through these keys (XOR with plaintext) until we see a message that “makes sense” is now very easy – and could even be done by hand (not posting the actual solution here).

# Cracking RC4 messages that use weak RC4 reinitialization for each message part
#
# Rainhard Findling
# University of Applied Sciences Upper Austria, Campus Hagenberg
# 2015/03
# 
# all ciphertext message parts
c1 = [0xd9, 0xef, 0x7b, 0x6e, 0xca, 0xb5, 0x12, 0xa0, 0x4f, 0x4b, 0x56, 0xb4, 0x94, 0xdf, 0x27, 0xed, 0xf8, 0xcc, 0x64, 0x94, 0xeb, 0x5a, 0x77, 0xea, 0x9b, 0x76, 0xdf, 0xe9, 0x18, 0x02, 0xc6, 0x36, 0x19, 0x1f, 0xc8, 0xf2, 0x5a, 0xa8, 0xda, 0xe7]

c2 = [0xb7, 0xd3, 0x5f, 0x4e, 0x89, 0x9f, 0x01, 0xa9, 0x0e, 0x4c, 0x5c, 0xb6, 0xc0, 0xdc, 0x2e, 0xfa, 0xbd, 0xbf, 0x63, 0xb4, 0xa4, 0x42, 0x77, 0xb3, 0x98, 0x62, 0xd5, 0xf0, 0x5d, 0x07, 0xdc, 0x62, 0x17, 0x4d, 0xca, 0xe6, 0x5a, 0xa8, 0xdd, 0xec]

c3 = [0xf9, 0xd3, 0x5c, 0x47, 0x85, 0x86, 0x05, 0xab, 0x5d, 0x4c, 0x5b, 0xf0, 0xc7, 0xc2, 0x22, 0xf8, 0xb4, 0xe6, 0x17, 0xb8, 0xa4, 0x5f, 0x66, 0xb3, 0x80, 0x79, 0xd9, 0xec, 0x18, 0x1d, 0xc0, 0x35, 0x51, 0x4b, 0xca, 0xab, 0x19, 0xaf, 0xc2, 0xe6]

c4 = [0xe4, 0xc5, 0x0f, 0x5f, 0x82, 0x93, 0x40, 0xb7, 0x47, 0x58, 0x5b, 0xa4, 0x94, 0xdb, 0x2e, 0xfa, 0xb9, 0xf2, 0x52, 0xa8, 0xae, 0x43, 0x61, 0xb3, 0xbc, 0x7e, 0xc2, 0xf3, 0x18, 0x18, 0xd6, 0x62, 0x1c, 0x50, 0xc1, 0xe2, 0x1c, 0xae, 0xce, 0xe8]

c5 = [0xe3, 0xc9, 0x40, 0x45, 0x99, 0xd6, 0x32, 0x96, 0x6f, 0x1f, 0x56, 0xbe, 0xd7, 0xd9, 0x36, 0xf8, 0xac, 0xf6, 0x58, 0xb2, 0xeb, 0x46, 0x7d, 0xe1, 0x80, 0x64, 0x96, 0xec, 0x59, 0x0c, 0x8f, 0x24, 0x10, 0x4c, 0xd1, 0xee, 0x08, 0xe7, 0x8d, 0xa9]

c6 = [0xc3, 0xef, 0x6b, 0x64, 0xca, 0xb3, 0x0e, 0xa6, 0x5c, 0x46, 0x43, 0xa4, 0x94, 0xc9, 0x26, 0xfc, 0xbb, 0xf0, 0x5e, 0xb2, 0xeb, 0x41, 0x60, 0xfa, 0x9d, 0x76, 0xc2, 0xfe, 0x18, 0x1e, 0xca, 0x3b, 0x02, 0x1f, 0xd2, 0xe2, 0x0e, 0xaf, 0x8d, 0xce]

c7 = [0xc7, 0xe7, 0x0f, 0x41, 0x9f, 0x85, 0x14, 0xe5, 0x4c, 0x5a, 0x13, 0xb2, 0xd1, 0x8b, 0x3c, 0xfd, 0xaa, 0xfa, 0x17, 0xbe, 0xae, 0x52, 0x73, 0xe6, 0x98, 0x72, 0x96, 0xef, 0x50, 0x10, 0xd6, 0x62, 0x19, 0x5e, 0xd3, 0xee, 0x5a, 0xa5, 0xc8, 0xec]

c8 = [0xf9, 0x80, 0x4a, 0x53, 0x9a, 0x99, 0x12, 0xb1, 0x4b, 0x5b, 0x13, 0xa5, 0xda, 0xdb, 0x3d, 0xe7, 0xac, 0xfa, 0x54, 0xa8, 0xae, 0x55, 0x32, 0xc4, 0x82, 0x7b, 0xda, 0xbb, 0x4b, 0x10, 0xc1, 0x26, 0x51, 0x4b, 0xcd, 0xee, 0x17, 0xe7, 0xf9, 0xc5]

c9 = [0xc4, 0x80, 0x5f, 0x59, 0x85, 0x82, 0x05, 0xa6, 0x5a, 0x5a, 0x57, 0xf0, 0xd6, 0xde, 0x3b, 0xa8, 0xbb, 0xfe, 0x59, 0xfc, 0xb2, 0x5e, 0x67, 0xb3, 0x9f, 0x65, 0xc3, 0xe8, 0x4c, 0x55, 0xfb, 0x0e, 0x22, 0x1f, 0xf5, 0xea, 0x09, 0xb4, 0xda, 0xe6]

c10 = [0xe5, 0xc4, 0x0f, 0x4d, 0x85, 0x84, 0x40, 0xa1, 0x4f, 0x49, 0x5a, 0xb4, 0xd0, 0xde, 0x21, 0xe6, 0xb6, 0xfa, 0x43, 0xfc, 0xa0, 0x54, 0x6b, 0xb3, 0x82, 0x64, 0x96, 0xc2, 0x48, 0x33, 0xcd, 0x26, 0x25, 0x73, 0xce, 0xe8, 0x2e, 0x8a, 0xc8, 0xcb]

c11 = [0xff, 0xf6, 0x5a, 0x0b, 0xca, 0xb2, 0x01, 0xb3, 0x47, 0x5b]

# concatenate all ciphertext parts (except last) 
ciphertext = [c1, c2, c3, c4, c5, c6, c7, c8, c9, c10]

# our brute forcing method
def try_keys(c):
    # each key is one byte, so 255 possibilities here
    k_ok = []
    for k in range(255):
        plaintext = [x^k for x in c] 
        # all chars of one position have to translate to chars allowed in plaintext: 41-5a, 61-7a
        ok = [p_chr == 0x20 or p_chr >= 0x41 and p_chr <= 0x5a or p_chr >= 0x61 and p_chr <= 0x7a for p_chr in plaintext]
        if(all(ok)):
            k_ok += [k]
    return k_ok

# brute force all keystream positions
xor = []
for i in range(40):
    c = [x[i] for x in ciphertext]
    xor += [try_keys(c)]

# see amount of possibilities left per keystream char position
print filter(lambda x:x[1] > 1, [(i, len(xor[i])) for i in range(len(xor))])

# use "first" key
key = [x[0] for x in xor]
# adapt specific keystream positions per hand so that all plaintext is correct (could be automated)
key[3] = xor[3][7]
key[14] = xor[14][1]
key[21] = xor[21][1]
key[24] = xor[24][3]
key[25] = xor[25][5]
key[34] = xor[34][14]

# decode (now include last message part)
plaintext = []
for c in (ciphertext + [c11]):
    t = []
    for i in range(len(c)):
        t += [chr(c[i]^key[i])]
    plaintext += t

print ''.join(plaintext)

Note: the more plaintext messages encoded by the same, re-initialized RC4 cipher we have, the less possible keystreams will remain, and the faster we obtain the plaintext. Btw: this is pretty much the problem WiFi WEP had – this is the core problem of why it can be cracked so easily, and why it is considered very insecure by now.

Around the Firewall: ssh proxy and ssh port forwarding

March 17, 2013 1 comment

If you happen to a) be behind a firewall which does not allow you to reach a certain destination on the web, or b) be outside in the web and cannot access a certain destination inside a network, the openssh implementation may help you: from the machine you’re sitting at (“local machine”) you just need ssh access to e.g. a Linux machine with an ssh-server running in the “target network” (“remote machine”, for a) outside the firewall in the “web”, for b) inside the target network behind the firewall).

a) ssh proxy (built in SOCKS proxy)

When logging in to the remote machine, use the -D option:

ssh -p 22 user_name@remote_machine_url -D 8080
  • -p 22 specifies the port the ssh server listens on at the remote machine.
  • -D 8080 specifies that requests sent to port 8080 at your locale machine are tunnelled to the remote machine, and then routed to where ever they should go. This way you can sent packets transparently to their targets over the remote machine.

For usage with a web browser, you then need to configure the browser so that it uses a proxy instead of your default gateway (e.g. for Firefox, you can use the FoxyProxy plugin). Configure it so that the browser uses a SOCKS proxy and routes packets to your local machine on port 8080.

b) ssh port forwarding

When logging in to the remote machine, use the the -L and/or the -R  option:

ssh -p 22 user_name@remote_machine_url -L 10001:192.168.0.101:10002 -R 10003:192.168.0.102:10004
  • -p 22 specifies the port the ssh server listens on at the remote machine.
  • -L 10001:192.168.0.101:10002 specifies that requests sent to port 10001 at your locale machine are tunnelled to the machine at 192.168.0.101 in the remote machine’s network on port 10002. This way you can sent packages from your machine to a machine in the remote machine’s network without needing direct access to it.
  • -P 10003:192.168.0.102:10004 specifies that requests sent to port 10003 at the remote machine are forwarded to the machine on 192.168.0.102 in your locale machine’s network on port 10004. This way somebody else from the remote machine’s network — which does not have any access to your locale machine’s network from outside — still can access a machine in your network.

On Windows you can do the same using Putty. You need to enable the check box “Don’t start a shell or command at all” in “Connection-SSH”. At “Tunnels”: add a “dynamic tunnel” on “local port X” where X is the port you are going to send data to locally (leave destination open – should state something like “D8080” after adding then).