Null byte injection in PHP
The null character is a control character with the value zero. It is presented in many character sets such as ASCII (American Standard Code of for Information Interchange), Unicode (Universal Character Set) and EBCDIC (Extended Binary Codded Decimal Interchange Code), as well as in programming languages like C, PHP, Python and Java. Every language and character set has a different way to implement the null character. For example: In Unicode, it is represented by u0000 or z. Some languages have represented it by �00 or x00.
It is also possible to pass the null character in the URL, which creates a vulnerability known as Null Byte Injection and can lead to security exploits. In the URL it is represented by %00. In this article, we will discuss a scenario in which Null Byte Injection can lead to a critical security thread in the Web application. Let's understand the basic concepts of the null byte before going in depth.
Learn Secure Coding
In order to fully understand the PHP null byte vulnerability, we will analyse how C handles strings. Unfortunately, C is a type of language which does not support a string as a distinct primitive data type. So, to create a string in C we have to use an array. In other words, to create a string in PHP we can simply write:
[c]
$Tmp= 'hehe';
[/c]
But for the same in C, we would use the following code:
[c]
Char Tmp [4];
Tmp [0] = 'h';
Tmp [1] = 'e';
Tmp [2] = 'h';
Tmp [3] = 'e';
Tmp [4] = '\0';
[/c]
Alternatively, we can use other functions in C like STRCPY to populate the array, but the concept is same. As C handles strings as a character array, it needs a way to define the last character of the string. This is done using a null byte. A null byte is donated by � in C. So when the program runs, it starts reading the string from the first character until the null byte is reached. This creates a problem. As we know, PHP is also implemented in C. This can become an issue, because some functions in PHP might handle an input string as they are handled by C.
Now, we will use a scenario in PHP language and try to exploit the vulnerability through the null byte injection.
Scenario 1:
We have created an application which allows the user to upload the image file into the application and to enter the file name for the image as desired. This application also has some server side validations, like only GIF files could be uploaded, etc. The PHP code of the file is given in the screenshot below. You can also download the sample code by clicking the URL. The sample code URL is given in the end of the article.
The description of each line is given in following:
- In the first line, we are creating the variable 'allowed' with the array value 'GIF'.
- We are getting user input parameter 'name' from the POST request and passing it through another PHP function 'EXPLODE', which is basically used to split the user entered data. It will return each value in the array.
- In this line, we are using another PHP function 'END', which is returning the last element of the array, which is the file extension, and then the extension is assigned in the variable 'fileExtension'.
- We are also using the 'getimagesize' function to check and ensure that the file uploaded by the user is a GIF file. This function will return a true or false value according to the user input. If the user input file is not a GIF file, it will return a false value, and this value will stored in the variable 'imagedetails'.
- We used an 'IF' condition, which checks that the user input file should be a GIF file and it also checks the user entered file name extension is a GIF. If both the conditions are true, then the file will be uploaded in the upload directory with the user entered name, otherwise it will print the error message. NOTE: Make sure that the file upload directory has the proper permissions.
- If the above condition is true, then it will take the user input file name through the 'POST' request and upload the file in the upload directory with the user input name.
We have also created an HTML file named "file.html". The HTML file code is given below:
This is a simple HTML file in which we are taking input from a 'POST' request.
Let's put the sample code in the document root of the server and run the code. After running the code, we can see that only image files with the extension of GIF are uploaded through the section. If the user entered file name has an extension other than GIF, then the file does not get uploaded on the server.
Now, our target is to upload the PHP command shell into the server. As we can see in the source code, there is no code level vulnerability in the PHP code, but it is possible to bypass this code through the null byte injection. Let's do this. The steps are following.
Note: We are using Kali Linux as a client machine.
Step 1
Download any image file with the extension GIF from the Internet and copy it into a folder. We also need a simple PHP backdoor for exploiting the null byte vulnerability. Kali Linux has a large amount of exploits. Let's copy the PHP backdoor into the same directory in which we have the GIF image.
In our case, hehe.gif is an image file we have downloaded from the Internet, and simle-backdoor.php is the PHP backdoor we have copied from the webshells directory. The path of the web shell is given in the above screen shot.
Step 2
Now, we have to install a package name Gifsicle. This package is not installed in Kali Linux by default. This tool is used to manipulate the GIF file. We can install it by using the following command.
Step 3
After installing the Gifsicle package, run the following command in the terminal.
gifsicle --comment "`tr 'n' ' ' < simple-backdoor.php`" < hehe.gif >action_back_out.php
This command will merge the PHP code into the GIF file and create a new file hehe_backdoor.php. This command is used to add PHP code into the GIF file as a comment. Let's check where the PHP code is inserted in the GIF image. We can check it by running the following command.
We can see the PHP code in the red box. We can also see the whole PHP code is written in the following section.
<!—Code Code Code Code<!--
This is a comment section. So if we see the image, we can't say that it contains a PHP code in the file.
Step 4
Let's try to upload this file into the server.
It can be seen in the above screenshot that we have chosen hehe_backdoor.gif through the browse option and given it the name profile.gif. After clicking on Upload, we can see the file has been successfully uploaded into the server. We can view the uploaded images by browsing the upload folder.
As we can see in the above screen shot, the normal image is viewable in the browser. The PHP interpreter does not execute the PHP code which is embedded into the image because it has the GIF extension.
Step 5
Let's try again. Setup the Burp Suite Proxy with the browser and turn the Burp Intercept on, and then upload the same file again. By clicking on upload, we can see Burp captures the browser request. The request can be seen in the following screenshot.
The marked section is explained briefly in the below section.
- This is the file name which we entered in the previous step. The file name is hehe.gif.
- This section gives the information about the image. We can see the image file name is hehe_backdoor.gif. We can also see content type of the image.
- This is interesting, we can see that the image file has the PHP code we had inserted in previous steps.
Step 6
Now we have to change the file name hehe.gif to hehe.phpA.gif. After changing the file name, click on hex. Now we can see all the Hex code. Scroll down the tab and find the name, which we have changed in the previous steps.
Once we identify the name, we can see the corresponding hex code. We have changed hehe.gif to hehe.phpA.gif in raw data. We can see the same thing in the hex code. Now, add the null character in the position of A. We already know that the value of A in hex ASCII is 41. Now, replace the 41 to 00 to add the null character. 00 denotes a null character in hex ASCII.
It can be seen in the above screenshot that we have replaced A with a null byte. So when PHP interpreter works with the file, as it is going to use the C library, it will terminate the string once it finds a null byte in the file name. So, that file will be saved as hehe.php.
Step 7
After forwarding the request to the server, we get the following results.
The server replies back 200 responses along with a message in the body that the image is "Successfully Uploaded". Finally, our backdoor is successfully uploaded on the server. Let's try to access the backdoor. We already know that all the files the user uploads will go to the 'uploads' directory. We had given the file name hehe.phpA.gif previously, but now we will access it with the file name hehe.php.
We can see the GIF file image code in the browser. We can also see our backdoor we added in the previous steps has also been executed, because the extension has changed from GIF to PHP.
Let's extract the password file through the PHP backdoor.
We have successfully extracted the password file from the server.
Conclusion
We have seen that null byte injection could be an extremely dangerous problem in PHP. It is often used as a technique to exploit arbitrary, local and remote file inclusion vulnerabilities, etc.
In order to fix the vulnerability of null byte injection, all user supplied input should be sanitized. This can be done by using the following snippit, which will strip null bytes out of the input:
[php]
$input = str_replace(chr(0), '', $input);
[/php]
Learn Secure Coding