Tuesday, August 29, 2017

HACKING TV BROADCAST



Using PHP’s data:// stream and File Inclusion to execute code

This is a reasonably old remote code execution trick that I was actually unaware of until recently, illness when I stumbled across it by accident. I have been heavily researching various ways to go from a file inclusion bug to a remote code execution bug, and this one really got me interested.
As we previously mentioned in the I expect:// a shell post, medical you can use certain PHP streams to execute code via a file inclusion vulnerability. This one does not require any PHP extensions to be installed, unlike the expect:// trick, and relies solely on allow_url_include to be enabled, which sadly is becoming a rarity these days.
How this works is simple. PHP has a data:// stream, which can decode and accept data. If you insert some PHP code into this stream and include() it, the code will be executed. Rather simple, and rather effective too. I will cover php://input in a follow up post, and then post my findings on abusing FindFirstFile.
Essentially, instead of including /etc/passwd or a remote file, you simply include the following. data://text/plain;base64,PAYLOAD_GOES_HERE
Where the payload is base64 encoded PHP code to be executed. I choose to base64 encode the payload to avoid some problems I ran into with whitespace and longer payloads.
Now, obviously this would be no fun without a simple proof of concept tool to demonstrate the vulnerability. The following tool is under serious redevelopment at the moment, so it only spawns a bind shell at the moment. Next version will offer several payloads (I am working on a generic payload library for this kind of thing).

Data:// shell to bindshell :)
You can download the current version of the tool here: PHP data include exploit
I will update that code later, might do a video once there is something worth watching.

http://insecurety.net/?p=742

3 THOUGHTS ON “USING PHP’S DATA:// STREAM AND FILE INCLUSION TO EXECUTE CODE

  1. HI,
    Verry nice new one, thank you, i follow all of your article’s with an big plaisure.
    I just try this new one & fortunetaly got errror’s wehn run the PY script..( i am on MAC LION )
    I chmod +x the “py” script, put in on an dir & run…
    *****************************************
    new-host:data xxxx$ ./p.py
    Traceback (most recent call last):
    File “./p.py”, line 9, in
    import requests
    ImportError: No module named requests
    ****************************************
    Thanks in advance for your reply about,
    Regards,
    David
    • You need to install pythons “requests” module.
      If you have “pip” or “Easy_install” just run “pip install requests” or “easy_install requests”

INTERCEPT NSA

Using mprotect(.., .., PROT_NONE) on Linux

After deciding to revisit some old code of mine (ok, very old), I realized that there was something different about how Linux was allocating pages of data I wanted to hide.   At first, I was glad that I couldn't see the data using yarascan, but then I realized that I was unable to access the memory regions at all in linux_volshell to verify that they were, in fact, obfuscated. So I decided to take a look at using a smaller, stripped down program. Below is one such example, comments are included to explain what is happening:
int main( int argc, char *argv[]){ // pid: the process ID of this process // so we can print it out int pid; pid = getpid(); //size: an integer to hold the current page size int size; size = getpagesize(); //[1] create two pointers in order to allocate //memory regions char *buffer; char *buffer2; //unprotected buffer: //allocate memory using mmap() buffer2 = (caddr_t) mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0,0); //[2] put some characters in the allocated memory //we're setting these characters one at a time in order //to avoid our strings being detected from the binary itself buffer2[0] = 'n'; buffer2[1] = 'o'; buffer2[2] = 't'; buffer2[3] = ' '; buffer2[4] = 'h'; buffer2[5] = 'e'; buffer2[6] = 'r'; buffer2[7] = 'e'; //protected buffer: //allocate memory with mmap() like before buffer = (caddr_t) mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0,0); //[2] put some characters in the allocated memory //we're setting these characters one at a time in order //to avoid our strings being detected from the binary itself buffer[0] = 'f'; buffer[1] = 'i'; buffer[2] = 'n'; buffer[3] = 'd'; buffer[4] = ' '; buffer[5] = 'm'; buffer[6] = 'e'; //[3] protect the page with PROT_NONE: mprotect(buffer, size, PROT_NONE); //[4] print PID and buffer addresses: printf("PID %d\n", pid); printf("buffer at %p\n", buffer); printf("buffer2 at %p\n", buffer2); //spin until killed so that we know it's in memory: while(1); return 0; }
Now we'll just compile the above program and run it. In short, the above program [1] creates two buffers, [2] places characters in these buffers, [3] then calls mprotect() on one of them with PROT_NONE; [4] the program then prints out its process ID and the virtual addresses of the aforementioned buffers:
$ ./victim PID 29620 buffer at 0x7f2bec9a1000 buffer2 at 0x7f2bec9a2000
Let's set up a config file so that we don't have to type as much:
$ cat linux.config [DEFAULT] LOCATION=file:///Path/to/Virtual%20Machine/Linux%20Mint%20Cinnamon/Mint%2064-bit-d583834d.vmem PROFILE=LinuxLinuxMintCinnamonx64x64 PID="29620"
If we try to search for the strings we placed in the buffers we get:
$ python vol.py --conf-file=linux.config linux_yarascan -Y "not here" Volatility Foundation Volatility Framework 2.4 Task: victim pid 29620 rule r1 addr 0x7f2bec9a2000 0x7f2bec9a2000 6e 6f 74 20 68 65 72 65 00 00 00 00 00 00 00 00 not.here........ 0x7f2bec9a2010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a2020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ [snip] $ python vol.py --conf-file=linux.config linux_yarascan -Y "find me" Volatility Foundation Volatility Framework 2.4

Well that was disappointing, we couldn't find the "find me" string. What you would expect, is to be able to access the memory contents using Volatility. Let's use the linux_volshell plugin to explore the victim process' memory and see if we can access the memory addresses (given to us from the program at run time) directly. First we'll examine the contents at 0x7f2bec9a2000:
$ python vol.py --conf-file=linux.config linux_volshell Volatility Foundation Volatility Framework 2.4 >>> Current context: process victim, pid=29620 DTB=0x3cfb1000 >>> db(0x7f2bec9a2000) 0x7f2bec9a2000 6e 6f 74 20 68 65 72 65 00 00 00 00 00 00 00 00 not.here........ 0x7f2bec9a2010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a2020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a2030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a2040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a2050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a2060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a2070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
As we see, we have the contents that we'd expect. Now to try to access the other memory location:
>>> db(0x7f2bec9a1000) Memory unreadable at 7f2bec9a1000
We see that we've been rejected. After a bit of investigation, we see that the point of failure is in the entry_present() function in the amd64.py address space. In order to find the value of the entry that failed, we'll print it out. First we'll add a print statement to entry_present():
def entry_present(self, entry): if entry: if (entry & 1): return True arch = self.profile.metadata.get('os', 'Unknown').lower() # The page is in transition and not a prototype. # Thus, we will treat it as present. if arch == "windows" and ((entry & (1 << 11)) and not (entry & (1 << 10))): return True # we want a valid entry that hasn't been found valid: print hex(entry) return False

Now let's see what the entry is: 
$ python vol.py --conf-file=linux.config linux_yarascan -Y "find me" Volatility Foundation Volatility Framework 2.4 0x2681d160
So let's look a little closer at the page table entry:
>>> print "{0:b}".format(0x2681d160) 100110100000011101000101100000
The way we read this is from right to left.  The entry_present() function checks the 0th bit to see if the entry is present. In this case the bit is not set (0); therefore this function returns False.

At this point, I decided to take a look at the Linux source code to see how mprotect() is actually implemented. As it turns out, the _PAGE_PRESENT bit is cleared when mprotect(...PROT_NONE) is called on a page and the _PAGE_PROTNONE bit is set [3]. Looking at how _PAGE_PROTNONE is defined [4][5][6] we'll see that it's actually equivalent to the global bit (8th bit) [1][2]. So let's look at our page table entry again, we'll notice that the 8th bit is indeed 1:
>>> print "{0:b}".format(0x2681d160) 100110100000011101000101100000


So let's patch the entry_present() function with our findings:
def entry_present(self, entry): if entry: if (entry & 1): return True arch = self.profile.metadata.get('os', 'Unknown').lower() # The page is in transition and not a prototype. # Thus, we will treat it as present. if arch == "windows" and ((entry & (1 << 11)) and not (entry & (1 << 10))): return True # Linux pages that have had mprotect(...PROT_NONE) called on them # have the present bit cleared and global bit set if arch == "linux" and ((entry & (1 << 8))): return True return False


Let's see if we get anything back: 
$ python vol.py --conf-file=linux.config linux_yarascan -Y "find me" Volatility Foundation Volatility Framework 2.4 Task: victim pid 29620 rule r1 addr 0x7f2bec9a1000 0x7f2bec9a1000 66 69 6e 64 20 6d 65 00 00 00 00 00 00 00 00 00 find.me......... 0x7f2bec9a1010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0x7f2bec9a1020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ [snip]

Success! So now we're able to see the "forbidden" string that we couldn't access before.  This goes to show that sometimes you have to dig a little into "why" something is not working as expected. In this case, we lucked out and had source code to examine, but sometimes things are not as easy as all that. Both intel.py and amd64.py have been patched in order to accommodate memory sections that have had mprotect() called on them with PROT_NONE.

https://volatility-labs.blogspot.pt/2015/05/using-mprotect-protnone-on-linux.html
When we are involved in an incident handling and we are in charge of analyzing a traffic capture in a pcap format related to an attack, one of the things we usually need to do is get the files which were downloaded. The reason is that we need to have a copy of the malware or the exploit to analyze it by reversing engineer or similar... 

We usually detect the original sources where these files were downloaded from just analyzing the pcap file, but they disappear in a short period of time from they were originally hosted. Because of that, we will need to extract them directly from the pcap file.

In this post, I will show you three different ways to achieve this goal using the the pcap hosted in Barracuda related to the www.php.net compromise which can be downloaded here:
http://barracudalabs.com/downloads/5f810408ddbbd6d349b4be4766f41a37.pcap

Wireshark

As you know, Wireshark is the most popular network protocol analyzer. It is capable of extracting all the files which were downloaded and captured.

If you load the pcap file in you Wireshark and use the command below...
http contains "in DOS mode"

... you can check that some executables were downloaded.

We are able to download all files which were downloaded like executables, pictures, javascripts, etc... by clicking File --> Export Objects --> HTTP and clicking on "Save all".


In the picture below shows you the files which are been recovered.

We use the command below to filter only the executables.

If we upload these files to Virustotal, we check that all of them have been categorized as malicious.

NetworkMinner

NetworkMiner is another Network Forensic Analysis Tool (NFAT) for Windows. Also, it can be installed on Linux using Mono. This tool is a great alternative to Wireshark if you just want to extract the files which were downloaded, look at the sessions, discover the DNS queries or get details about the mails detected from a pcap file.

Just loaded the traffic capture file, Network Minner downloads all files from it. Because of that, if you are using an Antivirus, It is possible it warns you if some file is detected as malicious.


You can find the folder where files have been recovered by right-clicking on a file and selecting "Open Folder". In the Picture below you can see this folder.


If we get the SHA256 checksum of the PE files, we can see that the results are exactly the same than using Wireshark. We have got the sames files.

Foremost

Foremost is a well known file carving tool. It was developed by the United States Air Force Office of Special Investigations and The Centre for Information Systems Security Studies and Research and now, it has been opened to the general public.

This tool has been designed to work on image files, such as those generated by dd, Safeback, Encase, etc, or directly on a drive...

Although I usually use Wireshark or NetworkMinner I have read some blogs where they describe how to use Foremost to extract files from a pcap file. For this, I have decided to use it in our example.

Just downloaded we extract all files from the pcap file, we execute the command in the picture below to extract all the files.


We can check that a "/output/exe" folder has been created containing six files.


But the checksum is different than we got with Wireshark or NetworkMinner. It seems like Foremost hasn't work well with the pcap file... For this reason I don't usually use it with a pcap file...


I've uploaded these files to my Cuckoo Sandbox and it seems to be corrupted because the files couldn't run properly...

The VirusTotal links below redirect you to the reports of the corrupted executables:






Cielo e terra (duet with Dante Thomas)