SQLi
免责声明
本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关.
大纲
注入检测
MySQL
MSSQL
Oracle
H2 database
BigQuery
SQLite
描述
注入攻击的本质,是程序把用户输入的数据当做代码执行。这里有两个关键条件,第一是用户能够控制输入;第二是用户输入的数据被拼接到要执行的代码中从而被执行。sql 注入漏洞则是程序将用户输入数据拼接到了 sql 语句中,从而攻击者即可构造、改变 sql 语义从而进行攻击。
教程
payload
在线 SQLi 测试
http://demo.testfire.net/
https://juice-shop.herokuapp.com/#/search
https://sqlchop.chaitin.cn/demo/
相关工具
sqlmap
sqlmap 笔记
提权工具
SafeGroceryStore/MDUT - 数据库跨平台利用工具
Ryze-T/Sylas - 数据库综合利用工具
https://paper.seebug.org/1836/
SQL 注入常规利用思路
注入的分类
基于响应类型
报错
联合查询
堆叠注入
盲注
基于布尔
基于时间
基于数据类型
字符型
数字型
搜索型
基于语句类型
查询型
插入型
删除型
基于程度和顺序
一阶注入 : 指输入的注入语句对 WEB 直接产生了影响,出现了结果;
二阶注入 : 类似存储型 XSS,是指输入提交的语句,无法直接对 WEB 应用程序产生影响,通过其它的辅助间接的对 WEB 产生危害,这样的就被称为是二阶注入.
基于注入点的位置
通过用户输入的表单域的注入
通过 cookie 注入
通过服务器变量注入 : 例如基于头部信息的注入
注入检测
可以通过多种方式检测注入。其中最简单的方法是在各种参数后添加 ' 或 " 从而得到一个从 Web 服务器返回的数据库报错信息。
找注入点
GET - HTTP Request
在常见的 HTTP GET 请求(以及大多数请求类型)中,有一些常见的注入点。例如:网址参数(下面的请求的 id),Cookie,host 以及任何自定义 headers 信息。然而,HTTP 请求中的任何内容都可能容易受到 SQL 注入的攻击。
POST - Form Data
在具有 Content-Type 为 application/x-www-form-urlencoded 的标准 HTTP POST 请求中,注入将类似于 GET 请求中的 URL 参数。它们位 于HTTP 头信息下方,但仍可以用相同的方式进行利用。
POST - JSON
在具有 Content-Type 为 application/json 的标准 HTTP POST 请求中,注入通常是 JSON{"key":"value"} 对的值。该值也可以是数组或对象。虽然符号是不同的,但值可以像所有其他参数一样注入。(提示:尝试使用
',但要确保 JSON 使用双引号,否则可能会破坏请求格式。)POST - XML
在具有 Content-Type 为 application/xml 的标准 HTTP POST 请求中,注入通常在一个内部。虽然符号是不同的,但值可以像所有其他参数一样注入。(提示:尝试使用
')
检测注入
通过在应用程序中触发错误和布尔逻辑,可以最轻松地检测易受攻击的参数。提供格式错误的查询将触发错误,并且使用各种布尔逻辑语句发送有效查询将触发来自Web服务器的不同响应。
注:True 或 False 语句应通过 HTTP 状态码或 HTML 内容返回不同的响应。如果这些响应与查询的 True/False 性质一致,则表示存在注入。
万能密码
逻辑测试
1.php?id=1 or 1=1 -- true
1.php?id=1' or 1=1 -- true
1.php?id=1" or 1=1 -- true
1.php?id=1 and 1=2 -- false
1.php?id=1-false
1.php?id=1-true
算术
1.php?id=1/1 -- true
1.php?id=1/0 -- false
基于盲注
基于错误
判断数据库类型
注释符判断
/*是 MySQL 中的注释符,返回错误说明该注入点不是 MySQL,继续提交如下查询字符:-是 Oracle 和 MSSQL 支持的注释符,如果返回正常,则说明为这两种数据库类型之一。继续提交如下查询字符:;是子句查询标识符,Oracle 不支持多行查询,因此如果返回错误,则说明很可能是 Oracle 数据库。函数判断
and (select count()from MSysAccessObjects)>0返回正常说明是 access 数据库,and (select count()from sysobjects)>0返回正常说明是 mssql 数据库and length(user())>10返回正常说明是 Mysql Oracle 可以根据 from dual 虚拟库判断
MYSQL
靶场
https://github.com/Audi-1/sqli-labs
sqli-labs
相关文章
资源
监控工具
TheKingOfDuck/MySQLMonitor - MySQL 实时监控工具(代码审计/黑盒/白盒审计辅助工具)
cw1997/MySQL-Monitor - MySQL服务器执行SQL记录实时监控(WEB版本)
MySQL 基础
MySQL
注释
数据库名
表名
列名
根据列名查询所在的表
条件语句
延时函数
order by 后的注入
简单判断
order by 由于是排序语句,所以可以利用条件语句做判断,根据返回的排序结果不同判断条件的真假。一般带有 order 或者 order by 的变量很可能是这种注入,在知道一个字段的时候可以采用如下方式注入:
宽字节注入
国内最常使用的 GBK 编码,这种方式主要是绕过 addslashes 等对特殊字符进行转移的绕过。反斜杠 \ 的十六进制为 %5c,在你输入 %bf%27 时,函数遇到单引号自动转移加入 \,此时变为 %bf%5c%27,%bf%5c 在 GBK 中变为一个宽字符「縗」。%bf 那个位置可以是 %81-%fe 中间的任何字符。不止在 SQL 注入中,宽字符注入在很多地方都可以应用。
oob
如果不成功,可能是访问 oob 域名的流量被拦截了,也可能是由于没开启文件导入导出
文件导出
正则表达式攻击
在 MYSQL 5+ 中 information_schema 库中存储了所有的库名,表名以及字段名信息。
判断第一个表名的第一个字符是否是 a-z 中的字符,其中 blind_sqli 是假设已知的库名。
注:正则表达式中
^[a-z]表示字符串中开始字符是在 a-z 范围内
判断第一个字符是否是 a-n 中的字符
确定该字符为 n
表达式的更换如下
这时说明表名为 news ,要验证是否是该表名 正则表达式为 '^news$',但是没这必要 直接判断 table_name = 'news' 即可。
接下来猜解其它表了
regexp 匹配的时候会在所有的项都进行匹配。例如:security 数据库的表有多个,users,email 等
实验表名:在 limit 0,1 下,regexp 会匹配所有的项。我们在使用 regexp 时,要注意有可能有多个项,同时要一个个字符去爆破。类似于上述第一条和第二条。而 limit 0,1 对于 where table_schema='security' limit 0,1 来说 table_schema='security' 已经起到了限定作用了,limit 有没有已经不重要了。
bypass 技巧
常见的绕过技巧
函数替换
连接
benchmark 代替 sleep
字符串截取函数
字符串连接函数
字符转换/编码
函数与括号之间
执行语句之间
括号包裹
省略空格
注释配合换行符
绕过引号限制
绕过字符串黑名单
json 函数
MySQL 5.7.8 开始新增了很多操作 json 数据的函数
提权/GETSHELL
Mysql提权
MSSQL
基于ASP / ASPX的应用程序一般都是 MSSQL。
学习资源
靶场
搭建过程 : MSSQL搭建 , asp站点搭建
相关文章
相关案例
相关工具
Keramas/mssqli-duet - SQL injection script for MSSQL that extracts domain users from an Active Directory environment based on RID bruteforcing
MSSQL 基础
MSSQL
基本参数
查询密码HASH
正则表达式攻击
MSSQL 所用的正则表达式并不是标准正则表达式 ,该表达式使用 like 关键词
该查询语句中,select top 1 是一个组合,不要看错了。
如果要查询其它的表名,由于不能像 mysql 那样用 limit x,1,只能使用 table_name not in (select top x table_name from information_schema.tables) 意义是:表名没有在前 x 行里,其实查询的就是第 x+1 行。
例如查询第二行的表名:
表达式的顺序:
之所以表达式 news[a-z] 查询后返回正确是应为 % 代表 0-n 个字符,使用 "_" 则只能代表一个字符。故确认后续是否还有字符可用如下表达式
同理可以用相同的方法获取字段,值。这里就不再详细描述了。
bypass 技巧
select from 后的位置
空白符号
需要做 urlencode,sqlserver 中的表示空白字符比较多,靠黑名单去阻断一般不合适.
注释符号
Mssql 也可以使用注释符号
/**/.符号:号
select from 之间的位置
空白符号
注释符号
:号
and 之后的位置
空白符号
注释符号
:号%2b号
常见过滤函数
字符串截取函数
字符串转换函数
Mssql 支持多语句查询,因此可以使用;结束上面的查询语句,然后执行自己构造的语句.动态执行.
使用 exec 的方式:
使用 sp_executesql 的方式:
提权/GETSHELL
MSSQL提权
oracle
用于是否是判断 oracle 数据库的方法
相关案例
bypass 技巧
oracle 中文版中,中文括号 ( )可以代理英文且不报错
H2 database
相关文章
BigQuery
相关文章
Playground
https://console.cloud.google.com/bigquery
信息收集
SQLite
SQLite 是一个进程内的库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。它是一个零配置的数据库,这意味着与其他数据库不一样,你不需要在系统中配置。
SQLite 数据库的特点是它每一个数据库都是一个文件,当你查询表的完整信息时会得到创建表的语句。
相关文章
SQLite 基础
https://www.runoob.com/sqlite/sqlite-commands.html
注释
查看版本
查询表名和列名
布尔盲注
布尔盲注通过查询正确和错误返回的页面不同来判断数据内容。
SQLite不支持ascii,所以直接通过字符去查询,这里和mysql不同,这个区分大小写。也没有mid,left等函数。
时间盲注
SQLite没有sleep()函数,但可以用randomblob(N)函数,randomblob(N) 函数,其作用是返回一个 N 字节长的包含伪随机字节的 BLOG。N 是正整数。可以用它来制造延时。SQLite没有if,所以需要使用case……when来代替。
写 webshell
SQLite 的 ATTACH DATABASE 语句是用来选择一个特定的数据库,使用该命令后,所有的 SQLite 语句将在附加的数据库下执行。
如果附加数据库不存在,就会创建该数据库,如果数据库文件设置在web目录下,就可以写入webshell。
Postgresql
相关文章
Postgresql 基础
Postgresql
忽略
||
|| 可用于将数据附加到同一行的输出中
通过延时判断是否是 Postgresql 数据库的方法
SELECT
FROM
WHERE
HAVING
OFFSET
当注入点在 WHERE 时
可以配合 ||
bypass 技巧
注释
代替引号
query_to_xml
query_to_xml 可以将结果返回在一行里,不必担心限制或多行
DATABASE_TO_XML
使用 xml 帮助程序通过单个查询转储整个数据库
提权/GETSHELL
Postgresql提权