Tuesday, September 17, 2013

CryptHook: Secure TCP/UDP Connection Wrapper

Introduction

CryptHook is a modular implementation for securing existing applications with symmetrical block cipher encryption. It works by hooking the base system calls for network communication send/sendto and recv/recvfrom. CryptHook will work with existing applications that rely on these system calls.

Download the Code

$ git clone https://github.com/chokepoint/CryptHook.git
or
$ wget https://github.com/chokepoint/CryptHook/archive/master.zip

Hooking the Calls

Hooking system calls is relatively simple, and is often used to deploy userland rootkits such as Jynx/Jynx2. For this, we're really only interested in hooking four system calls, as previously mentioned. With these hooks, we are able to intercept any data before it is sent across the network (for encryption), and also any data before it touches the client/server application (for decryption).

static ssize_t (*old_recv)(int sockfd, void *buf, size_t len, int flags);
static ssize_t (*old_send)(int sockfd, void *buf, size_t len, int flags);
static ssize_t (*old_recvfrom)(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
static ssize_t (*old_sendto)(int sockfd, void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

ssize_t recv(int sockfd, void *buf, size_t len, int flags) {
....
}

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen) { 
....
}

ssize_t send(int sockfd, const void *buf, size_t len, int flags) {
....
}

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen) {
....
}

Encrypting / Decrypting Data *Updated*

As part of this proof of concept, I've focused primarily on Advanced Encryption Standard (AES). CryptHook is now only set up with AES 256 in GMC mode, but it would be relatively simple to implement additional algorithms that are already a part of the OpenSSL library.

#define BLOCK_CIPHER EVP_aes_256_cbc()  // EVP_aes_256_cbc() and EVP_bf_cbc() have been tested
#define BLOCK_SIZE 16    // Blowfish = 8 AES = 16
#define KEY_SIZE 32     // Blowfish is variable, lets go w/ 256 bits

The key is passed to the library using an environment variable. The plain text is then used to derive a key using PBKDF2 with multiple iterations. If you're going to use this in a live environment, I highly encourage you to change the salt and number of iterations. If no key is passed to the library, it defaults back to PASSPHRASE defined below.

#define PASSPHRASE "Hello NSA"

Example Usage

As discussed earlier, this can be use with many different client/server applications. As a demonstration, lets add a layer of encryption to SSHd.

Server side:
$ LD_PRELOAD=./crypthook.so UC_KEY=OHarroNSA sshd -p 5000
Client Side:
$ LD_PRELOAD=./crypthook.so UC_KEY=OHarroNSA ssh localhost -p 5000

Wireshark Capture

As you can see, the packets show up as malformed, because Wireshark doesn't know how to interpret them, and the data is obviously encrypted.

Going Beyond

It'd be relatively simple to add an SSL header to each packet so that the packets look even more innocuous to anyone casually observing the transaction. SSL headers for application data are five bytes. Adding a fake SSL handshake immediately upon connection would also be a nice touch.

[SSL Record Type][SSL Version][Data Length]
[1 Byte]         [2 Bytes]    [2 Bytes]

Friday, September 13, 2013

Linux Kernel Structure Definition Lookup Script

Introduction

If you've ever written anything kernel side for Linux, I'm sure you've bashed your head on the keyboard as many times as I have looking through lackluster documentation and scouring source files to find structure definitions. Here's a little script that will show you the source file and line number of the given structure definition.

First of all, this script relies on a fantastic website that allows you to easily search through the Linux source files http://lxr.linux.no. I simply wrote a script to parse the output to show structure definition locations. Change the URL in the script depending on your current kernel version number.

Example

$ ./structure.py crypto_tfm
[-] Searching for all structure definitions of: crypto_tfm
[+] drivers/staging/rtl8192e/rtl8192e/rtl_crypto.h, line 186
[+] drivers/staging/rtl8192u/ieee80211/rtl_crypto.h, line 189
[+] include/linux/crypto.h, line 413

The Source

#!/usr/bin/python
# Linux Kernel Structure Search

import sys
from BeautifulSoup import BeautifulSoup
import requests

def main(argv):
 struct_search = "http://lxr.linux.no/linux+v3.11/+code=" + argv[0]
 in_struct = 0
 
 print "[-] Searching for all structure definitions of: " + argv[0]
 
 req = requests.get(struct_search)
 soup = BeautifulSoup(req.text)

 spanTag = soup.findAll('span')
 for tag in spanTag:
  try: 
   myclass = tag['class']
   if myclass == 'identtype':
    if tag.string == "Structure":
     in_struct = 1
    elif in_struct:
     break
  
   if myclass == "resultline" and in_struct:
    aTag = tag.find('a')
    print "[+] " + aTag.text
  except: 
   ohnoez=1

 if not in_struct:
  print "[-] No Structures Found"
  
if __name__ == "__main__":
 main(sys.argv[1:])

Tuesday, September 10, 2013

sslnuke -- SSL without verification isn't secure!

A video demonstration of the tool described in this post can be seen at ascii.io.

We have all heard over and over that SSL without verification is not secure. If an SSL connection is not verified with a cached certificate, it can easily be hijacked by any attacker. So in 2013, one would think we had totally done away with this problem. Browsers cache certificates and very loudly warn the user when a site has offered up a self-verified certificate and should not be trusted, browser vendors have pretty much solved this problem. However, HTTPS is not the only protocol that uses SSL. Unfortunately, many clients for these other protocols do not verify by default and even if they did, there is no guarantee of secure certificate transfer. After all, how many people are willing to pay $50 for an SSL certificate for their FTPS server?

A common protocol that uses SSL but is rarely verified is IRC. Many IRC clients verify by default, but most users will turn this off because IRC servers administrators tend not to purchase legitimate SSL certificates. Some popular clients even leave SSL verification off by default (IRSSI, for example). We already know that this is unwise, any attacker between a user and the IRC server can offer an invalid certificate and decrypt all of the user's traffic (including possibly sensitive messages). Most users don't even consider this fact when connecting to an SSL "secured" IRC server.

The purpose of sslnuke is to write a tool geared towards decrypting and intercepting "secured" IRC traffic. There are plenty of existing tools that intercept SSL traffic already, but most of these are geared towards HTTP traffic. sslnuke targets IRC directly in order to demonstrate how easy it is to intercept "secured" communications. sslnuke usage is simple.

Usage

First, add a user account for sslnuke to run as and add iptables rules to redirect traffic to it:

    # useradd -s /bin/bash -m sslnuke
    # grep sslnuke /etc/passwd
    sslnuke:x:1000:1000::/home/sslnuke:/bin/bash
    # iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner 1000 -m tcp \
      --dport 6697 --tcp-flags FIN,SYN,RST,ACK SYN -j REDIRECT --to-ports 4444

Finally, login as sslnuke, build, and run sslnuke:

    # su -l sslnuke
    # cd sslnuke
    # make
    # ./sslnuke

Run an IRC client and login to your favorite IRC network using SSL, IRC messages will be printed to stdout on sslnuke.

    [*] Received connection from: 192.168.0.5:58007
    [*] Opening connection to: 1.1.1.1:6697
    [*] Connection Using SSL!
    [*] irc.com -> AUTH (1.1.1.1): *** Looking up your hostname...
    [*] irc.com -> AUTH (1.1.1.1): *** Found your hostname
    [*] irc.com -> victim (1.1.1.1): *** You are connected to irc.com with TLSv1.2-AES256-GCM-SHA384-256bits
    [*] 192.168.0.5 -> nickserv (192.168.0.5): id hello
    [*] NickServ!services@irc.com -> victim (1.1.1.1): Password accepted - you are now recognized.

sslnuke will automatically detect a client using SSL and determine whether or not to use SSL. The code could also be easily modified to show web site passwords or FTP data, anything using SSL. To attack users on a network, sslnuke can be used in conjunction with an ARP poisoning tool, such as the one found at Blackhat Library or it can be deployed on a gateway.

Mitigation

Now on to the important part, how do we verify SSL connections? The first step is to transfer the SSL certificate over an alternative medium, the best way would be to have the administrator directly give you the certificate. However, if this is not possible, openssl can download the certificate from the server:

    # openssl s_client -showcerts -connect irc.com:6697 </dev/null

Save the certificate into "~/.irssi/ssl/irc.com.crt". It is best to run the command from a computer on a different network than yours to prevent this from being intercepted. Next, to configure IRSSI to use the certificate, save a network:

    /network add irc
    /server add -ssl_cafile ~/.irssi/ssl/irc.com.crt -network irc -port 6697 irc.com

If IRSSI ever gets an invalid certificate, it will warn you and disconnect immediately. However, for the truly paranoid, a Tor hidden service or VPN should be used. To configure automatic Tor hidden service redirection on Linux one can run the following commands:

    # echo "VirtualAddrNetwork 10.192.0.0/10" >> /etc/tor/torrc
    # echo "AutomapHostsOnResolve 1" >> /etc/tor/torrc
    # echo "TransPort 9040" >> /etc/tor/torrc
    # echo "DNSPort 5353" >> /etc/tor/torrc
    # killall -HUP tor
    # iptables -t nat -A OUTPUT -p tcp -d 10.192.0.0/10 -j REDIRECT --to-ports 9040
    # iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports 5353
    # ncat xxxxxxxxxxxxxxx.onion 6667
    :irc.com NOTICE AUTH :*** Looking up your hostname...
    :irc.com NOTICE AUTH :*** Couldn't resolve your hostname; using your IP address instead
    ^C

Ultimately, IRC clients should use an SSH-style key verification. On first connect, present the certificate fingerprint to the user and force the user to confirm it and then cache the certificate. If it changes the next time, do not allow the connection.

Source

The source code can be downloaded on Github.

Saturday, September 7, 2013

PiBowl: Rasperry Pi Secure (SIPS/SRTP) Asterisk Autoconfig Script

Introduction

This is directly related to my last post Create your own Fishbowl: an NSA Approved Telecommunication Network. That tutorial is dedicated to setting up both OpenVPN and Asterisk in order to provide secure end to end VoIP communications. This is part of a new project to make it as easily deployable as possible.

PiBowl Server

PiBowl server is the first part of the puzzle. Its specifically designed to be a one stop shop for installing and configuring Asterisk on a Raspberry Pi. For the demonstration, I am assuming that the user has a fresh installation of Raspbian on their SD Card. The installation script has also been tested on Debian Wheezy, and works just the same.

Getting the Script

PiBowl is hosted on github. You can either clone the repository, or if you don't feel like installing additional packages, access it directly using the following wget request.

$ wget https://github.com/chokepoint/PiBowl/archive/master.zip
$ unzip master.zip

Now that you have the script, you really only need to edit two variables defined in pibowl.sh.

  • AST_IP
  • ALLOW_CONTACT
AST_IP is the IP address of the interface that you want TLS to bind to. This prevents external users from probing or accessing Asterisk. The only traffic coming in or out should be through the VPN. ALLOW_CONTACT is the range of IPs that are able to make or receive calls. This is redundant, but ensures that we don't have any unencrypted or unwanted calls taking place.

Running the Script

You need to run PiBowl as sudo in order for the install to complete.

$ sudo ./pibowl.sh
If you're compiling on a Rapsberry Pi, go ahead and make a pot of coffee, bake a pizza, mow the lawn, take a shower, and then come back to see if it's done with the build yet. Interaction is minimal and requires your input while creating the Certificate Authority password used for certificate signing, and when it comes time to build client keys. You can build as many client keys / SIP users as you want during the configuration. Each user will be assigned a semi random password, as well as a sequential dialing extension. Extensions can be changed by tweaking the EXTEN variable in pibowl.sh. If you need to add users later, simply refer back to the original article for how to do it manually.

Going Beyond

Plans are to build similar configs for a client based Raspberry Pi as well. If you'd like to help with the client side, feel free to send pull requests to the github, and I'll merge them in as appropriate. This will hopefully show people that the concept is relatively simple and easy to deploy. As this becomes more user friendly, I hope that it can be used to connect friends and families in a secure manner.

Friday, September 6, 2013

Creating your own key-binds in Openbox

Introduction

I love being able to control any and every aspect of my computer by utilizing key-binds and macros to do certain tasks. This post is going to go over how to create key-binds in the Openbox desktop environment. Again as my last post I'll be running Crunch Bang as my distribution of choice which comes preconfigured with Openbox. Also because I don't like to steer too far away from the CLI; I will be calling the configs from the per this post.

The Configuration

As I discussed in my last tutorial, you can locate the config file by using the find command.

$ find ~/ -iname rc.xml
In this case we're going to edit the rc.xml file. Before we can edit that file we need to know which keys we're going to use as shortcuts along with the task that we want that key sequence to execute. So we're going to use a built in tool called 'xev' to find out what keys are called. For the sake of this post I'm going to use left shift and f1 to make a key-bind. So open a terminal and type xev and press enter, then push left shift and you should see an output like this:


KeyPress event, serial 46, synthetic NO, window 0x4000001,
    root 0x370, subw 0x0, time 326988347, (-740,188), root:(572,1005),
    state 0x11, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
    XLookupString gives 0 bytes:
    XFilterEvent returns: False

Now lets push f1 and see what happens:

KeyPress event, serial 46, synthetic NO, window 0x4000001,
    root 0x370, subw 0x0, time 327135703, (-576,193), root:(736,1010),
    state 0x10, keycode 67 (keysym 0xffbe, F1), same_screen YES,
    XLookupString gives 0 bytes:
    XmbLookupString gives 0 bytes:
    XFilterEvent returns: False

What information does this give us? First we have the X11 key name, and we also have the keycode which if we change to hex can be used in place of the X11 key name. So back to the rc.xml file. For simplicity reasons we'll just use the X11 key names, Shift_L and F1 respectively. In the xml file, we need to find the area where keybinds are defined. You should see comments that talks about keybinds like:


<!-- Keybindings for desktop switching -->
Now we need to create our own. You can create your keybinds anywhere in the keybind portion of the config file. Use the following format as an example:
<keybind key="">
     <action name="">
          <command>command goes here</command>
     </action>
</keybind>
Remember in this example we're using Shift_L and F1 for the keybind key, openbox has used modifiers for certain keys such as Shift which is an uppercase S and that's what we'll insert instead of Shift_L:
<keybind key="S-F1">
For the action name we want it to execute a command:
<action name="Execute">
And for the command we'll have it open Iceweasel:
<command>iceweasel</command>
Our keybind alltogether should look like this
<keybind key="S-F1">
     <action name="Execute">
          <command>iceweasel</command>
     </action>
</keybind>

Reload Openbox Configs

Now that the keybinds have been changed, whenever we use shift + f1 iceweasel opens up. These keybinds can be configured to do anything you want with endless combinations of keybinds and actions. Once you're happy with your current configuration, we need to have openbox reload the config files. In order to accomplish this, type the following into your terminal:
$ openbox --reconfigure

Monday, September 2, 2013

Building a multiplatform shellcode header

This post is a quick overview of one method used to quickly create machine code capable of branching to up to four different platforms:

  • 32-bit Linux
  • 64-bit Linux
  • 32-bit Windows
  • 64-bit Windows

The multi-platform process is a multi-step process that can be broken into small pieces of code - first to detect the processor architecture, then to determine operating system.

Determining Architecture

When I made my last post, I was reminded of an awesomely shorter technique I found while googling for architecture detection developed by the guys over at ragestorm.net. Because theirs is shorter (which in my opinion makes it cooler since we aren't focusing on strictly alphanumeric code), I'll use their getCPU in stead of my own for this little demonstration. Admittedly, I changed a 'jz' to a 'jnz' and re-ordered the code a little bit. Instead of bits_32 we're going to have a determine_32_os label:

arch_detect:
  xorl %eax, %eax
  rex
  nop
  jnz determine_32_os

This is a 6-byte header that works on both windows and linux for determining the CPU architecture, so lets get started with determining the operating system.

Determining operating system using segment registers

EDIT:

Apparently something was seriously wrong with my testing environment. Whether it was due to virtualization or this or that, we suspect that the controversy came from running windows 8.1 in a VM on an amd system with the VM providing an intel interface. In any case, here's the work-around that doesn't rely on the parity bit: segment registers.

All of the segment registers aren't always used by the operating system's runtime environment. In the case of windows, the %ds segment register is nearly always set, whereas in linux, it is nearly always zero. To that end, we can use the following snippet of code to determine operating system by testing for a zero value in the %ds segment register (zero means linux), but this is only valid for 64 bit. In a 32 bit world, %fs is 0 on linux while it has a value on windows:
determine_64_os:
  mov %ds, %eax
  test %eax, %eax
  jnz win64_code
  jmp lin64_code

determine_32_os:
  mov %fs, %eax
  test %eax, %eax
  jz lin32_code 

Final code:

The final version of this header comes out to a 20 bytes that could definitely be made shorter:
arch_detect:
  xorl %eax, %eax
  rex
  nop
  jnz determine_32_os

determine_64_os:
  mov %ds, %eax
  test %eax, %eax
  jnz win64_code
  jmp lin64_code

determine_32_os:
  mov %fs, %eax
  test %eax, %eax
  jz lin32_code 

win32_code:
  nop

lin64_code: 
  nop

win64_code:
  nop

lin32_code:
  nop

And it disassembles to:

0000000000000001 :
   1: 31 c0                 xor    %eax,%eax
   3: 40 90                 rex xchg %eax,%eax
   5: 75 08                 jne    f 

0000000000000007 :
   7: 8c d8                 mov    %ds,%eax
   9: 85 c0                 test   %eax,%eax
   b: 75 0a                 jne    17 
   d: eb 07                 jmp    16 

000000000000000f :
   f: 8c e0                 mov    %fs,%eax
  11: 85 c0                 test   %eax,%eax
  13: 74 03                 je     18 

0000000000000015 :
  15: 90                    nop

0000000000000016 :
  16: 90                    nop

0000000000000017 :
  17: 90                    nop

0000000000000018 :
  18: 90                    nop

Further reading: