CTF Web 刷题笔记|Bugku CTF 题解:备份是个好习惯

5 阅读1分钟

前言

网站开发者在更新代码的时候,经常会给重要文件做备份,常用的后缀有:

  • .bak(手动备份时最常用)
  • .swp(Vim 编辑器自动生成的交换文件)
  • .~(临时备份)
  • .txt(纯文本备份)

这些备份文件如果被遗忘在服务器上,就会成为泄露源码的入口。

一、题目

二、解题步骤:

  1. 根据题目“备份是个好习惯”指向了备份文件泄漏的考点。目标就是找到并下载这个备份文件。
  2. 输入/index.php.bak,下载了一个文件。
  3. 查看文件,分析代码
<?php
/* Created by PhpStorm.
 * User: Norse
 * Date: 2017/8/6
 * Time: 20:22
 */

include_once "flag.php"; // 引入包含flag的文件(隐藏不输出)
ini_set("display_errors", 0); // 关闭错误显示,防止暴露关键信息

$str = strstr($_SERVER['REQUEST_URI'], '?'); // 从URL中截取?及其后面的内容,比如访问/?abc=123就得到"?abc=123"
$str = substr($str,1); // 去掉开头的?,得到纯参数字符串,比如"abc=123"
$str = str_replace('key','',$str); // 把参数字符串里所有的"key"都替换成空
parse_str($str); // 把处理后的参数字符串解析成PHP变量,比如"key1=xxx"会生成变量$key1,值为xxx

echo md5($key1); // 输出$key1的MD5值(用于调试看结果)
echo md5($key2); // 输出$key2的MD5值(用于调试看结果)

if(md5($key1) == md5($key2) && $key1 !== $key2){ // 核心判断:MD5值弱比较相等,但两个变量本身强比较不相等
    echo $flag."取得flag"; // 满足条件就输出flag
}
?>

这段代码的核心是 str_replace('key','',$str) 的替换逻辑。

str_replace('key','',$str) 会把你传的参数里所有 key 字符串都删掉,所以我们要传一个参数名,删掉 key 后正好是 key1key2

比如:

  • kkey1=xxx → 替换掉 key 后变成 k1=xxx → 不行
  • keykey1=xxx → 替换掉 key → 变成 1=xxx →不行
  • kkeyey1=xxx → 替换掉 key 后变成 key1=xxx → 行

我们可以通过构造参数名,让它在替换后变成 key1key2,从而绕过替换规则,再用数组或0e字符串让MD5值相等,最终拿到flag。

  1. 构造Payload,需要让 key1key2 的MD5值相等但本身不等,直接用 0e 字符串 或者 数组绕过

方法1:0e字符串

<http://171.80.2.169:11186//?kkeyey1=QNKCDZO&kkeyey2=240610708>
  • QNKCDZO 的MD5是 0e830400451993494058024219903391
  • 240610708 的MD5是 0e462097431906509019562988736854
  • PHP弱比较 == 会把这两个 0e 开头的字符串都解析为 0,所以条件成立

方法2:数组绕过

<http://171.80.2.169:11186/>
  • PHP的 md5() 处理数组会返回 NULL
  • 所以 md5($key1) == md5($key2)NULL == NULL
  • 同时 $key1 !== $key2 → 数组 [1] 不等于数组 [2],满足所有条件