bugku 备份是个好习惯

bugku 备份是个好习惯

题目:备份是个好习惯

打开题目看到

d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e

没有思路

根据题目提示:备份

联想到目录扫描看看有没有备份文件(备份文件的后缀是.bak)

在linux使用

dirb “ http://171.80.2.169:18691/ “ -X .bak

指令扫描后缀是.bak的文件

执行结果
DIRB v2.22
By The Dark Raver

START_TIME: Thu Apr 9 19:17:59 2026
URL_BASE: http://171.80.2.169:18691/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
EXTENSIONS_LIST: (.bak) | (.bak) [NUM = 1]

GENERATED WORDS: 4612

—- Scanning URL: http://171.80.2.169:18691/ —-

http://171.80.2.169:18691/index.php.bak (CODE:200|SIZE:378)

看到存在 index.php.bak

访问

http://171.80.2.169:18691/index.php.bak

自动下载文件,打开看到

开始审计代码

include_once “flag.php”;

意思是加载flag.php 将flag.php嵌入到当前脚本执行

ini_set(“display_errors”, 0);

意思是设置display_errors的值是0(display_errors时控制是否输出报错信息的,值是0时,不会在页面上输出报错信息)

$str = strstr($_SERVER[‘REQUEST_URI’], ‘?’);

意思是定义变量 str 他的值是截取当前请求的路径?之后的值包括?

比如我请求http://171.80.2.169:18691/index.php?a=1&b=2

那现在变量str值就是?a=1&b=2

$str = substr($str,1);

意思是截取变量str字符串第一位之后的值当作变量str新的值

例如原始是$str=”?a=1&b=2”

更新以后就是$str=”a=1&b=2”

$str = str_replace(‘key’,’’,$str);

意思是把变量str里面的key替换为空

例如$str=abkeyc 会变成$str=abc

parse_str($str);

是把$str的值解析成变量

例如$str=”a=1&b=2”

现在就有两个新的变量是
$a=1 $b=2

echo md5($key1);

意思是输出md5计算过后的变量key1的值

echo md5($key2);

意思是输出md5计算过后的变量key2的值

if(md5($key1) == md5($key2) && $key1 !== $key2){

意思是如果变量key1的值md5计算以后等于变量key2的值经过md5计算,并且key1的值不等于key2的值,那么执行大括号里面的代码

echo $flag."取得flag";

意思是输出变量flag的值,并输出 取得flag (这行代码就是在大括号里面的代码)

虽然这里的变量flag没有在之前的代码里面声明过是多少

但是还记得代码第一行include_once “flag.php”;

引入了一个叫flag.php的代码,所以变量flag的值应该是在这个里面被定义的

这里猜测flag.php里面的内容是 (只是猜测,无实际作用)

整理一下思路

首先:要他输出flag就必须要服务器执行 echo $flag.”取得flag”;

要服务器执行 echo $flag.”取得flag”;就必须要(md5($key1) == md5($key2) && $key1 !== $key2)成立

要(md5($key1) == md5($key2) && $key1 !== $key2)成立就必须要变量key1的值md5计算以后等于变量key2的值经过md5计算,并且key1的值不等于key2的值

这里面有三个问题要解决

1:

变量key1和key2都是在前面没有提到过的

所以只能通过 parse_str($str);

是把$str的值解析成变量

也就是在$str里面定义key1和key2

我们就要构造 ?key1=xxxxxx&key2=xxxxxx 这样的值

成功解决第一个问题

2:

前面$str = str_replace(‘key’,’’,$str);

把变量str里面的key值替换空了(可以理解成删掉了)

这个时候 ?key1=xxxxxx&key2=xxxxxx

就变成了?1=xxxxxx&2=xxxxxx 了

但是我们需要的是变量key1和key2,而不是变量1和2

那我们思考一下,如果变量str值是12key1,这里面有一个key所以会变成121

可是当他的值是kkeyey(k + key + ey),这里面其实也只有一个连起来的key,因为k ey被key隔开了,所以不会被替换

那这个时候变量str的值就会变成key,这就得到了我们想要的key

这个是侯我们构造的值就应该是 ?kkeyey1=xxxxxx&kkeyey2=xxxxxx

3:

md5计算只要是值不一样那结果就完全不一样,哪怕只是改变一点原始被计算的值

(不过这句话不够严谨,因为被计算值完全不一样,但是计算结果一样的值也是存在的,而且理论上是很多的,可是很难被找出或计算出)

要是想真的找到这种值,现在没有很好的办法

所以我们不考虑

那么我们怎么办呢,这里注意到md5($key1) == md5($key2这段代码里面使用的是==比较两边的值

搜索信息可以知道==是弱类型比较,在被比较的值可以被转译的时候自动转译,例如

key1=0e123&key2=0e456 (e是科学计数法 3e4就是3乘以10的4次方)

那么他们用==比较的时候是一样的,因为0乘以10的123次方大小和0乘以10的456次方大小是一样的(都是0)

所以我们要找两个值,md5计算以后都是0e开头并且两个值本身不一样

这里常用的有QNKCDZO和240610708

那思路就清晰了

直接传入?kkeyey1=QNKCDZO&kkeyey2=240610708

就可以符合三个要求


http://171.80.2.169:18691/index.php连接后面加上?kkeyey1=QNKCDZO&kkeyey2=240610708

http://171.80.2.169:18691/index.php?kkeyey1=QNKCDZO&kkeyey2=240610708

即可看到

0e8304004519934940580242199033910e462097431906509019562988736854flag{eb116ff7d0f2f40def6e9d9c6309ab65}鍙栧緱flag

其中0e830400451993494058024219903391是QNKCDZO经过md5计算后的值

0e462097431906509019562988736854是240610708经过md5计算后的值

flag{eb116ff7d0f2f40def6e9d9c6309ab65} 就是flag

鍙栧緱flag 原本是文本 取得flag 这里因为编码问题显示乱码(无需在意)

取得flag

flag{eb116ff7d0f2f40def6e9d9c6309ab65}

补充知识:为什么flag.php里面有flag,不直接访问flag.php呢,而且index.php和flag.php可以访问到,但是他不显示内容是空白界面呢

因为文件后缀是php的时候,服务器的php解析器会自动尝试解析文件里面的内容

如果是php代码格式就直接运行,不显示;如果本身php代码格式就当作普通文本文件,直接显示给客户端

posted @ 2026-07-29 13:46  zidurile  阅读(15)  评论(0)    收藏  举报