sqlmap
的作用:
- 判断可注入的参数
- 判断可以用那种SQL注入技术来注入
- 识别出哪种数据库
- 根据用户选择,读取哪些数据
其支持5种模式的注入方式:
- 基于布尔的盲注,即可以根据返回页面判断条件真假的注入。
- 基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
- 基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
- 联合查询注入,可以使用union的情况下的注入。
- 堆查询注入,可以同时执行多条语句的执行时的注入。
使用-h -hh
可看到更为详细的帮助。
测试的来源可以是一个简单的URL,Burp或WebScarab请求日志文件,文本文档中的完整http请求或者Google的搜索,匹配出结果页面,也可以自己定义一个正则来判断那个地址去测试。
测试GET参数,POST参数,HTTP Cookie参数,HTTP User-Agent头和HTTP Referer头来确认是否有SQL注入,它也可以指定用逗号分隔的列表的具体参数来测试。
sqlmap
输出共有七个等级,默认为1
,使用-v
参数更改:
|
|
我们以-hh
显示的参数来介绍常见参数:
参数介绍
target/目标
目标URL
-u
|
|
Burp或者WebScarab代理中获取日志
-l
可以直接吧Burp proxy或者WebScarab proxy中的日志直接倒出来交给sqlmap来一个一个检测是否有注入。
文本中获取多个目标扫描
-m
文件中每行存储一个目标
|
|
文件中加载HTTP请求
-r
sqlmap可以从一个文本文件中获取HTTP请求,这样就可以跳过设置一些其他参数(比如cookie,POST数据,等等)
|
|
处理google搜索结果
-g
sqlmap可以测试注入Google的搜索结果中的GET参数
|
|
根据配置文件处理
-c
根据ini
文件中的内容进行配置
Request/请求
http方法
--method
更改http请求方法类型,如put,connect
等
http数据
--data
此参数是把数据以POST方式提交,sqlmap会像检测GET参数一样检测POST的参数。
|
|
参数拆分字符
--param-del
当GET或POST的数据需要用其他字符分割测试参数的时候需要用到此参数。
|
|
HTTP cookie头
--cookie,--load-cookies,--drop-set-cookie
这个参数在以下两个方面很有用:
- web应用需要登陆的时候。
- 你想要在这些头参数中测试SQL注入时。
可以通过抓包把cooki
e获取到,复制出来,然后加到–cookie参数里。
在HTTP请求中,遇到Set-Cookie
的话,sqlmap
会自动获取并且在以后的请求中加入,并且会尝试SQL注入
。
如果你不想接受Set-Cookie
可以使用--drop-set-cookie
参数来拒接。
当你使用--cooki
e参数时,当返回一个Set-Cookie头
的时候,sqlmap会询问你用哪个cookie
来继续接下来的请求。当--level
的参数设定为2或者2以上的时候,sqlmap会尝试注入Cookie参数。
HTTP User-Agent头
--user-agent,--random-agent
默认情况下sqlmap的HTTP请求头中User-Agent值是:sqlmap/1.0-dev-xxxxxxx (http://sqlmap.org)
可以使用--user-anget
参数来修改,同时也可以使用--random-agnet
参数来随机的从./txt/user-agents.txt
中获取。
当--level
参数设定为3或者3以上的时候,会尝试对User-Angent
进行注入。
HTTP Referer头
--referer
sqlmap可以在请求中伪造HTTP中的referer
,当–level参数设定为3或者3以上的时候会尝试对referer
注入。
有些WAF会限制链接的跳转源,这时修改此字段就非常有必要。
额外的HTTP头
--headers
可以通过此参数来增加额外的http头
HTTP请求延迟
--delay
可以设定两个HTTP(S)请求间的延迟,设定为0.5的时候是半秒,默认是没有延迟的。
设定超时时间
--timeout
可以设定一个HTTP(S)请求超过多久判定为超时,10.5表示10.5秒,默认是30秒。
利用正则过滤目标网址
--scope
|
|
避免过多的错误请求被屏蔽
--safe-url,--safe-freq
有的web应用程序会在你多次访问错误的请求时屏蔽掉你以后的所有请求,这样在sqlmap进行探测或者注入的时候可能造成错误请求而触发这个策略,导致以后无法进行。
1、–safe-url:提供一个安全不错误的连接,每隔一段时间都会去访问一下。
2、–safe-freq:提供一个安全不错误的连接,每次测试请求之后都会再访问一边安全连接。
每次请求时候执行自定义的python代码
--eval
在有些时候,需要根据某个参数的变化,而修改另个一参数,才能形成正常的请求,这时可以用--eval
参数在每次请求时根据所写python代码做完修改后请求。
|
|
上面的请求就是每次请求时根据id参数值,做一次md5后作为hash参数的值。
Injection/注入
测试参数
-p
sqlmap
默认测试所有的GET
和POST
参数,当--level
的值大于等于2的时候也会测试HTTP Cookie头的值,当大于等于3的时候也会测试User-Agent和HTTP Referer头的值。但是你可以手动用-p参数设置想要测试的参数。例如: -p "id,user-anget"
当你使用--level
的值很大但是有个别参数不想测试的时候可以使用–skip参数。
例如:--skip="user-angent.referer"
在有些时候web服务器使用了URL重写,导致无法直接使用sqlmap测试参数,可以在想测试的参数后面加*
|
|
指定数据库
--dbms
默认情况系sqlmap会自动的探测web应用后端的数据库是什么,sqlmap支持的数据库有:
|
|
指定数据库服务器系统
--os
默认情况下sqlmap会自动的探测数据库服务器系统,支持的系统有:Linux、Windows
。
指定无效的大数字
--invalid-bignum
当你想指定一个报错的数值时,可以使用这个参数,例如默认情况系id=13,sqlmap
会变成id=-13来报错,你可以指定比如id=9999999来报错。
指定无效的逻辑
--invalid-logical
可以指定id=13把原来的id=-13的报错改成id=13 AND 18=19。
注入payload
--prefix,--suffix
在有些环境中,需要在注入的payload的前面或者后面加一些字符,来保证payload的正常执行。
例如:
例如,代码中是这样调用数据库的:
|
|
这时你就需要--prefix
和--suffix
参数了:
这样执行的SQL语句变成:
|
|
修改注入的数据
--tamper
sqlmap除了使用CHAR()
函数来防止出现单引号之外没有对注入的数据修改,你可以使用–tamper参数对数据做修改来绕过WAF等设备。
下面是一个tamper脚本的格式:
|
|
常用的tamper都在/tamper
目录下:
|
|
Detection/探测
探测等级
--level
共有五个等级,默认为1,sqlmap使用的payload可以在xml/payloads.xml
中看到,你也可以根据相应的格式添加自己的payload
。
这个参数不仅影响使用哪些payload
同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie
在level为2的时候就会测试,HTTP User-Agent/Referer
头在level
为3的时候就会测试。
总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值。
风险等级
--risk
共有四个风险等级,默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。
在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险。
测试的语句同样可以在xml/payloads.xml
中找到,你也可以自行添加payload。
页面比较
--string,--not-string,--regexp,--code
默认情况下sqlmap通过判断返回页面的不同来判断真假,但有时候这会产生误差,因为有的页面在每次刷新的时候都会返回不同的代码,比如页面当中包含一个动态的广告或者其他内容,这会导致sqlmap的误判。此时用户可以提供一个字符串或者一段正则匹配,在原始页面与真条件下的页面都存在的字符串,而错误页面中不存在(使用–string参数添加字符串,–regexp添加正则),同时用户可以提供一段字符串在原始页面与真条件下的页面都不存在的字符串,而错误页面中存在的字符串(–not-string添加)。用户也可以提供真与假条件返回的HTTP状态码不一样来注入,例如,响应200的时候为真,响应401的时候为假,可以添加参数–code=200。
--text-only,--titles
有些时候用户知道真条件下的返回页面与假条件下返回页面是不同位置在哪里可以使用–text-only(HTTP响应体中不同)–titles(HTML的title标签中不同)。
注入技术
测试是否是注入
--technique
这个参数可以指定sqlmap使用的探测技术,默认情况下会测试所有的方式。所有支持的注入方式如下:
|
|
设定延迟注入的时间
--time-sec
当使用继续时间的盲注时,时刻使用--time-sec
参数设定延时时间,默认是5秒。
设定UNION查询字段数
--union-cols
默认情况下sqlmap测试UNION查询注入会测试1-10个字段数,当--level
为5的时候他会增加测试到50个字段数。设定--union-cols
的值应该是一段整数,如:12-16,是测试12-16个字段数。
设定UNION查询使用的字符
--union-char
默认情况下sqlmap针对UNION查询的注入会使用NULL字符,但是有些情况下会造成页面返回失败,而一个随机整数是成功的,这是你可以用--union-char
只定UNION查询的字符。
二阶SQL注入
--second-order
有些时候注入点输入的数据看返回结果的时候并不是当前的页面,而是另外的一个页面,这时候就需要你指定到哪个页面获取响应判断真假。–second-order后面跟一个判断页面的URL地址。
枚举数据
标志
-b,--banner
大多数的数据库系统都有一个函数可以返回数据库的版本号,通常这个函数是version()
或者变量@@version
这主要取决与是什么数据库。
用户
-current-user
在大多数据库中可以获取到管理数据的用户。
当前数据库
--current-db
返还当前连接的数据库。
列数据库管理用户
--users
当前用户有权限读取包含所有用户的表的权限时,就可以列出所有管理用户。
列出并破解数据库用户的hash
--passwords
当前用户有权限读取包含用户密码的表的权限时,sqlmap
会现列举出用户,然后列出hash,并尝试破解。
|
|
列出数据库管理员权限
--privileges
当前用户有权限读取包含所有用户的表的权限时,很可能列举出每个用户的权限,sqlmap将会告诉你哪个是数据库的超级管理员。也可以用-U参数指定你想看哪个用户的权限。
列举数据库表
--tables,--exclude-sysdbs,-D
当前用户有权限读取包含所有数据库表信息的表中的时候,即可列出一个特定数据的所有表。
如果你不提供-D参数来列指定的一个数据的时候,sqlmap会列出数据库所有库的所有表。
–exclude-sysdbs参数是指包含了所有的系统数据库。
需要注意的是在Oracle中你需要提供的是TABLESPACE_NAME而不是数据库名称。
列举数据库表中的字段
--columns,-C,-T,-D
当前用户有权限读取包含所有数据库表信息的表中的时候,即可列出指定数据库表中的字段,同时也会列出字段的数据类型。
如果没有使用-D参数指定数据库时,默认会使用当前数据库。
|
|
列举数据库系统的架构
--schema,--exclude-sysdbs
用户可以用此参数获取数据库的架构,包含所有的数据库,表和字段,以及各自的类型。
加上--exclude-sysdbs
参数,将不会获取数据库自带的系统库内容。
例如:
|
|
获取表中数据个数
--count
有时候用户只想获取表中的数据个数而不是具体的内容,那么就可以使用这个参数。
|
|
获取整个表的数据
--dump,-C,-T,-D,--start,--stop,--first,--last
如果当前管理员有权限读取数据库其中的一个表的话,那么就能获取真个表的所有内容。
使用-D,-T参数指定想要获取哪个库的哪个表,不适用-D参数时,默认使用当前库。
|
|
可以获取指定库中的所有表的内容,只用-dump
跟-D
参数(不使用-T与-C参数)。
也可以用-dump
跟-C
获取指定的字段内容。
sqlmap为每个表生成了一个CSV文件。
如果你只想获取一段数据,可以使用–start和–stop参数,例如,你只想获取第一段数据可hi使用–stop 1,如果想获取第二段与第三段数据,使用参数 –start 1 –stop 3。
也可以用–first与–last参数,获取第几个字符到第几个字符的内容,如果你想获取字段中地三个字符到第五个字符的内容,使用–first 3 –last 5,只在盲注的时候使用,因为其他方式可以准确的获取注入内容,不需要一个字符一个字符的猜解。
运行自定义的SQL语句
--sql-query,--sql-shell
sqlmap会自动检测确定使用哪种SQL注入技术,如何插入检索语句。
如果是SELECT查询语句,sqlap将会输出结果。如果是通过SQL注入执行其他语句,需要测试是否支持多语句执行SQL语句。
|
|
暴力破解
暴力破解表名
--common-tables
当使用–tables无法获取到数据库的表时,可以使用此参数。
原因一般是:
|
|
暴力破解列名
--common-columns
与暴力破解表名一样,暴力跑的列名在txt/common-columns.txt中。
系统文件操作
从数据库服务器中读取文件
--file-read
当数据库为MySQL
,PostgreSQL
或Microsoft SQL Server
,并且当前用户有权限使用特定的函数。读取的文件可以是文本也可以是二进制文件。
|
|
把文件上传到数据库服务器中
--file-write,--file-dest
当数据库为MySQL
,PostgreSQL
或Microsoft SQL Server
,并且当前用户有权限使用特定的函数。上传的文件可以是文本也可以是二进制文件。
|
|
运行任意操作系统命令
--os-cmd,--os-shell
当数据库为MySQL
,PostgreSQL
或Microsoft SQL Server
,并且当前用户有权限使用特定的函数。
在MySQL
、PostgreSQL
,sqlmap
上传一个二进制库,包含用户自定义的函数,sys_exec()
和sys_eval()`。
那么他创建的这两个函数可以执行系统命令。在Microsoft SQL Server
,sqlmap
将会使用xp_cmdshell
存储过程,如果被禁(在Microsoft SQL Server 2005及以上版本默认禁制),sqlmap
会重新启用它,如果不存在,会自动创建。
|
|
对Windows注册表操作
当数据库为MySQL
,PostgreSQL
或Microsoft SQL Server
,并且当前web应用支持堆查询。 当然,当前连接数据库的用户也需要有权限操作注册表。
读取注册表值
--reg-read
写入注册表值
--reg-add
删除注册表值
--reg-del
常规参数
从sqlite中读取session
-s
sqlmap对每一个目标都会在output路径下自动生成一个SQLite文件,如果用户想指定读取的文件路径,就可以用这个参数。
保存HTTP(S)日志
-t
这个参数需要跟一个文本文件,sqlmap会把HTTP(S)请求与响应的日志保存到那里。
非交互模式
--batch
用此参数,不需要用户输入,将会使用sqlmap提示的默认值一直运行下去。
强制使用字符编码
--charset
不使用sqlmap自动识别的(如HTTP头中的Content-Type)字符编码,强制指定字符编码如:
|
|
爬行网站URL
--crawl
sqlmap可以收集潜在的可能存在漏洞的连接,后面跟的参数是爬行的深度。
|
|
规定输出到CSV中的分隔符
--csv-del
当dump保存为CSV格式时(--dump-format=CSV
),需要一个分隔符默认是逗号,用户也可以改为别的 如:
|
|
其他参数
使用HTTP参数污染
-hpp
HTTP参数污染可能会绕过WAF/IPS/IDS
保护机制,这个对ASP/IIS
与ASP.NET/IIS
平台很有效
测试WAF/IPS/IDS保护
--identify-waf
sqlmap可以尝试找出WAF/IPS/IDS
保护,方便用户做出绕过方式。目前大约支持30种产品的识别。
|
|
自带tamper分析
单引号替换 apostrophemask.py
使用utf-8 编码
字符'
(U+FF07
)替换单引号'
(U+0027
)
|
|
适用数据库:ALL
单引号替换 apostrophenullencode.py
将单引号替换为%00%27
在引号前插入了空字符U+0000
|
|
适用数据库:ALL
添加空字符 appendnullbyte.py
|
|
适用数据库:Access
base64编码 base64encode.py
这个看模块名也知道是base64
编码
|
|
适用数据库:ALL
比较符替换 between.py
将大于符号和等号用between
语句替换,用于过滤了大于符号和等号的情况
|
|
适用数据库:ALL
空格替换 bluecoat.py
用%09 U+0009
水平制表符代替空格,并且将等号替换为 like
,用于过滤了空格和等号的情况
|
|
适用数据库:MySQL 5.1
, SGOS
两次urlencode chardoubleencode.py
|
|
适用数据库:ALL
一次url编码 charencode.py
|
|
unicode转义 charunicodeencode.py
使用unicode
转义所有字符,除了已经urlencode
的字符
|
|
适用数据库:ALL,但是需要 asp
和 asp.net
环境
unicode转义 charunicodeescape.py
常用语绕过WAF
中JSON
数据
|
|
逗号替换 commalesslimit.py
将的逗号用offset
代替,用于过滤了逗号并且是两个参数的情况
|
|
适用数据库:MySQL
mid函数逗号替换 commalessmid.py
将mid
函数中的start,end
换成from to
|
|
适用数据库:MySQL
括号前注释 commentbeforeparentheses.py
在单词后括号前加行内注释以绕过WAF
|
|
适用数据库:ALL
concat替换 concat2concatws.py
用于过滤了concat
函数的情况,将其转换为concat_ws
函数
|
|
适用数据库:MySQL
等号替换成like equaltolike.py
|
|
引号转义逃逸 escapequotes.py
'
单引号变成\\'
,"
双引号变成\\"
大于号替换 greatest.py
|
|
在关键词前加内联注释 halfversionedmorekeywords.py
|
|
适用数据库:MySQL < 5.1 ,之后的内联注释必须为/*!content*/
html实体转义 htmlencode.py
|
|
ifnull函数替换 ifnull2casewhenisnull.py
将 ifnull()
函数转为 if(isnull())
函数,用于过滤了 ifnull
函数的情况
ifnull函数替换 ifnull2ifisnull.py
将 ifnull()
函数转为 if(isnull())
函数,用于过滤了 ifnull
函数的情况
|
|
适用数据库:MySql5.0,5.5
内置表过滤绕过 informationschemacomment.py
有些WAF过滤了information_schema
字段,在其后面加行内注释
|
|
使用least替换比较符 least.py
|
|
大写转小写 lowercase.py
|
|
完整语句注释绕过 modsecurityversioned.py
使用内联注释注释完整语句,绕过ModSecurity WAF/IDS
|
|
完整语句注释绕过 modsecurityzeroversioned.py
同上,补了4个0
|
|
关键字周围加空格 multiplespaces.py
|
|
叠写关键字 nonrecursivereplacement.py
用于绕过替换策略,例如服务器做如下操作replace("SELECT", "")
,可用此方式绕过:
|
|
overlongutf8.py
|
|
用百分号加到所有字符前面 percentage.py
|
|
加号替换为concat plus2concat.py
|
|
加号替换为fn concat plus2fnconcat.py
|
|
随机大小写 randomcase.py
|
|
随机加注释 randomcomments.py
|
|
加入任意字符串 securesphere.py
|
|
添加sp_password字段 sp_password.py
在payload
语句后添加sp_password
,用于迷惑数据库日志
适用数据库:MSSQL
空格替换 space2comment.py
|
|
空格替换 space2dash.py
空格替换成被注释的字符串并换行
|
|
适用数据库:MSSQL
、 SQLite
空格替换 space2hash.py
同上,注释从--
改为#
|
|
空格替换 space2morecomment.py
将空格用 /**_**/
替代
|
|
空格替换 space2morehash.py
跟之前的差不多,用#
+随机字串
+\n
代替空格
|
|
空格替换 space2mssqlblank.py
随即用空白ASCII替换空格
|
|
空格替换 space2plus.py
空格替换为+
|
|
适用数据库:ALL
空格替换 space2randomblank.py
空格替换为随机空白符
|
|
适用数据库:ALL
逻辑操作符替换 symboliclogical.py
and
和or
替换成&& ||
|
|
union替换 unionalltounion.py
|
|
宽字符注入 unmagicquotes.py
'
替换为%df%27
|
|
大写 uppercase.py
|
|
HTTP头部注入 varnish.py
添加一个 HTTP头 X-originating-IP
来绕过 WAF
|
|
关键字内联注释 versionedmorekeywords.py
|
|
HTTP头部注入 xforwardedfor.py
添加一个伪造的 HTTP 头X-Forwarded-For
来绕过 WAF
本文总结于以下参考文献: