做渗透测试,你得先懂Web应用是怎么工作的。很多人一上来就想学SQL注入、XSS,但连HTTP请求都看不懂,那肯定学不好。这一部分,让我们从实战的角度,深入理解Web应用的技术基础。这是做渗透测试的“语法基础”,不理解这些,后面的漏洞理解起来会很困难。
很多人会用Burp Suite抓包,但看不懂包里的内容。他们知道要改参数,但不知道为什么要这样改,也不知道改哪里。
理解HTTP协议,是做渗透测试的基础。就像学编程要先学语法一样,做Web渗透测试,必须先理解HTTP协议。
一个完整的HTTP请求,包含这几个部分:
|请求行 请求头 空行 请求体(可选)
让我用一个真实的例子给你看:
|POST /api/login.php HTTP/1.1 Host: example.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Content-Type: application/x-www-form-urlencoded Content-Length: 38 Cookie: sessionid=abc123 Connection: keep-alive username=admin&password=123456
请求行:POST /api/login.php HTTP/1.1,其中POST是请求方法,/api/login.php是请求路径,HTTP/1.1是协议版本。
请求头:从Host到Connection都是请求头。Host标识目标主机,告诉服务器要访问哪个域名。User-Agent包含客户端信息,告诉服务器你用的什么浏览器。Content-Type指定请求体的类型,这里是application/x-www-form-urlencoded,表示表单数据。Content-Length表示请求体的长度,这里是38字节。Cookie包含会话信息,用于维持登录状态。
空行:请求头和请求体之间必须有一个空行
请求体:username=admin&password=123456,这是实际传输的数据
HTTP响应的结构类似:
|状态行 响应头 空行 响应体
真实例子:
|HTTP/1.1 200 OK Server: nginx/1.18.0 Date: Mon, 01 Jan 2024 12:00:00 GMT Content-Type: application/json Content-Length: 156 Set-Cookie: sessionid=xyz789; Path=/; HttpOnly Connection: keep-alive {"status":"success","message":"Login successful","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."}
状态行:HTTP/1.1 200 OK,其中200是状态码,表示请求成功,OK是状态描述。
响应头:Server头包含服务器信息,这个很重要,做信息收集时会用到,比如这里显示nginx/1.18.0,说明用的是nginx服务器,版本是1.18.0。Set-Cookie用于设置Cookie,注意这里的HttpOnly属性,后面会详细讲。Content-Type指定响应体的类型,这里是application/json,表示返回的是JSON数据。
响应体:实际的响应内容,这里是JSON格式的数据,包含登录成功的状态和token。

做渗透测试,你得知道这些HTTP方法:
状态码是HTTP响应的重要部分,做渗透测试时,状态码能告诉你很多信息。
状态码能帮你快速定位问题。403说明路径存在,但没权限,可以尝试绕过,比如尝试其他路径或者修改权限。405说明路径存在,但方法不对,可以尝试其他方法,比如GET不行就试试POST。500说明代码执行了,但出错了,可能有注入漏洞,因为参数处理出错。429说明有速率限制,可以尝试绕过,比如换IP或者降低请求频率。
HTTPS就是在HTTP基础上加了TLS加密。很多人觉得用了HTTPS就安全了,其实不是。HTTPS只能保证传输过程的加密,不能保证服务器端的安全、客户端的安全、应用逻辑的安全。即使传输过程加密了,如果服务器端有漏洞,或者应用逻辑有问题,还是会被攻击。
做渗透测试时,经常需要抓HTTPS的包。方法很简单,安装Burp Suite的CA证书到浏览器,或者用mitmproxy等工具。这样就能看到HTTPS的明文内容了。
在测试中发现,很多系统的HTTPS配置存在问题。使用弱加密算法、证书配置错误、支持不安全的协议版本(如SSL 2.0),这些都是常见的问题。这些配置缺陷可能导致中间人攻击,或者被利用已知漏洞。
这些都可以通过工具检测,比如sslscan、testssl.sh,可以快速发现TLS配置问题。
Cookie是Web应用中最常用的会话管理机制。做渗透测试,你必须深入理解Cookie。
Cookie的结构:
|name=value; attribute1=value1; attribute2=value2
常见的Cookie属性:
HttpOnly的作用是防止JavaScript访问Cookie,安全意义是防XSS攻击窃取Cookie。如果Cookie设置了HttpOnly,JavaScript无法通过document.cookie读取,这样即使有XSS漏洞,攻击者也无法窃取Cookie。测试方法是尝试用JavaScript读取Cookie,如果设置了HttpOnly,document.cookie读不到。
Secure的作用是只在HTTPS下传输Cookie,安全意义是防止中间人攻击窃取Cookie。如果Cookie设置了Secure,在HTTP下不会传输,只有在HTTPS下才会传输。测试方法是在HTTP下看Cookie是否传输,如果设置了Secure,HTTP下应该不传输。
SameSite的作用是防止CSRF攻击。值有三种,Strict最严格,跨站请求不发送Cookie,完全防止CSRF。Lax部分允许,GET请求可以跨站,POST请求不行,这是平衡安全和用户体验的折中方案。None允许跨站,但需要Secure,这是最宽松的设置。测试方法是构造CSRF攻击,看Cookie是否发送,如果设置了SameSite=Strict,跨站请求应该不发送Cookie。
Path的作用是指定Cookie的有效路径,安全意义是限制Cookie的作用范围。比如Path设置为/admin,那么这个Cookie只在/admin路径下有效。测试方法是在不同路径下测试Cookie是否有效,比如在/admin下有效,在/user下可能无效。
Domain的作用是指定Cookie的有效域名,安全意义是限制Cookie的作用范围。比如Domain设置为.example.com,那么这个Cookie在所有example.com的子域名下都有效。测试方法是在子域名下测试Cookie是否有效,比如在admin.example.com和user.example.com下是否都能用。
实战案例:Cookie安全问题
|Set-Cookie: sessionid=abc123; Path=/
上面的系统问题有几个。没有HttpOnly,可能被XSS窃取,如果网站有XSS漏洞,攻击者可以通过JavaScript读取Cookie。
没有Secure,在HTTP下也传输,如果网站同时支持HTTP和HTTPS,在HTTP下Cookie也会传输,容易被中间人攻击窃取。没有SameSite,可能被CSRF利用,攻击者可以构造跨站请求,利用用户的Cookie进行操作。
攻击者可以通过XSS窃取Cookie,然后用这个Cookie登录了系统。这说明Cookie的安全配置很重要,如果配置不当,即使有XSS漏洞,也可能被利用。
Session是服务器端的会话管理机制。客户端通过Session ID(通常存在Cookie里)来标识会话。
Session的工作流程:
Session的安全问题:
Session ID可预测,问题是如果Session ID是可预测的,比如基于时间戳生成,攻击者可以预测其他用户的Session ID,从而冒充其他用户。测试方法是注册多个账号,分析Session ID的规律,看看是否有可预测的模式。
Session固定攻击,问题是如果系统在登录后不重新生成Session ID,攻击者可以先获取Session ID,然后诱导用户登录,这样攻击者就能用这个Session ID访问用户的账号。测试方法是获取未登录的Session ID,登录后看Session ID是否变化,如果不变,就存在Session固定漏洞。
Session超时问题,问题是Session超时时间太长,或者登出后Session不失效,这样即使用户登出了,Session ID还能用,攻击者如果获取了Session ID,还能继续使用。测试方法是登录后登出,看Session ID是否还能用,如果还能用,就存在问题。
案例:Session固定攻击
一个简单的案例就是攻击者可以在未登录状态下,访问网站,获取Session ID:sessionid=abc123。然后诱导用户(或自己)用这个Session ID登录。
登录后,Session ID还是abc123,没有重新生成。这样攻击者就可以用这个Session ID直接访问用户的账号,因为Session ID没有变化,攻击者获取的Session ID在用户登录后仍然有效,可以冒充用户访问账号。
HTTP Header包含很多信息,做渗透测试时,这些信息很有用。
常见的请求头:
常见的响应头:
案例:通过Header绕过防护
假设一个系统根据User-Agent判断是否是爬虫,如果是爬虫就限制访问。如果系统只检查User-Agent,攻击者可以修改User-Agent为正常的浏览器,成功绕过限制。
另一个场景是系统根据Referer做CSRF防护,验证请求来源。如果系统只是简单检查Referer是否存在,攻击者可以删除Referer头,或者修改Referer为合法域名,可能就能绕过CSRF防护。这说明验证不严格,CSRF防护可能存在问题。
URL中有些字符有特殊含义,比如?表示查询参数开始,&表示参数分隔符,=表示键值分隔符,#表示锚点,空格也需要编码。如果参数值中包含这些字符,就需要编码,否则会被解析成URL的语法,而不是参数值。
1. URL编码(Percent Encoding)
URL编码是最常见的编码方式,格式:%XX(XX是十六进制)
|空格 → %20 + → %2B & → %26 = → %3D
在测试时,很多人经常用URL编码绕过WAF。WAF可能检测union select,但编码后union%20select可能检测不到,因为WAF可能只检测原始字符串,不检测编码后的。或者双重编码:union%2520select(%20编码成%2520),如果WAF只解码一次,可能检测不到,但服务器解码两次,就能正常执行。
2. Unicode编码
Unicode编码用于非ASCII字符:
|中 → \u4e2d 文 → \u6587
实战应用:
某些系统可能对Unicode字符处理不当,可以用来绕过。比如文件名:test.txt → test\u002etxt(.的Unicode编码),如果系统对Unicode处理不当,可能可以绕过文件扩展名限制。SQL注入中:' → \u0027,如果系统对Unicode处理不当,可能可以绕过SQL注入过滤。
3. HTML实体编码
HTML实体编码用于HTML上下文:
|< → < > → > & → & " → " ' → '
实战应用:
在XSS测试中,如果输出在HTML上下文,可能需要用HTML实体编码。比如<script>alert(1)</script> → <script>alert(1)</script>,这样HTML解析器就不会把它当作标签。但如果系统解码不当,可能可以绕过,比如系统对HTML实体解码了,但过滤不严格,可能可以绕过。
4. Base64编码
Base64不是URL编码,但经常用在参数传递中:
|admin → YWRtaW4= password → cGFzc3dvcmQ=
实战应用:
很多系统用Base64编码参数,可能是为了隐藏参数内容,让参数看起来不那么明显。或者避免特殊字符问题,Base64编码后都是ASCII字符,不会有特殊字符。但Base64编码不是加密,可以轻松解码。在测试中,可以解码Base64参数,查看里面的内容,有时候能发现敏感信息或者可以修改的参数。
5. 双重编码/多重编码
有时候,系统会对参数进行多次编码,或者解码多次。这可能导致编码不一致,可以用来绕过:
|原始:union select 一次编码:union%20select 二次编码:union%2520select(%编码成%25)
实战应用:
假设一个WAF拦截了union select,直接输入会被拦截。尝试URL编码一次union%20select,仍然被拦截。但编码两次union%2520select成功绕过。原因是WAF只解码一次,检测不到SQL注入,但服务器解码两次,得到原始的union select,成功执行。这说明编码不一致可能导致绕过,WAF和服务器对编码的处理不同,就可能被利用。
参数可以传递在多个位置,做渗透测试时,要测试所有位置:
1. URL参数(Query String)
|GET /api/user.php?id=1&name=admin
2. POST Body
|POST /api/user.php Content-Type: application/x-www-form-urlencoded id=1&name=admin
3. JSON Body
|POST /api/user.php Content-Type: application/json {"id":1,"name":"admin"}
4. Cookie
|Cookie: user_id=1; user_name=admin
5. Header
|X-User-Id: 1 X-User-Name: admin
6. URL路径
|GET /api/user/1/profile
实战技巧:
在测试时,应该测试所有可能的位置。常见的比如URL参数、POST Body,这些是最常见的参数传递位置。不常见的比如Header、Cookie、路径,这些位置也可能传递参数。有时候,系统在不同位置对参数的处理不同,可能某个位置有漏洞,另一个位置没有,所以要多测试几个位置,才能发现漏洞。
让我给你一个完整的编码绕过案例:
场景:测试一个搜索功能,参数是keyword
步骤1:正常测试
|GET /search?keyword=test
响应正常。
步骤2:尝试SQL注入
|GET /search?keyword=test' OR 1=1--
响应:被WAF拦截。
步骤3:尝试URL编码
|GET /search?keyword=test%27%20OR%201%3D1%2D%2D
响应:还是被拦截。
步骤4:尝试双重编码
|GET /search?keyword=test%2527%2520OR%25201%253D1%252D%252D
响应:成功绕过WAF,返回了所有结果。
分析:
WAF只解码一次,所以%27被解码成',被检测到SQL注入。双重编码后,WAF解码一次得到%27,检测不到SQL注入,因为WAF认为这是编码后的字符,不是SQL注入。但服务器解码两次,得到',成功注入。这说明编码不一致可能导致绕过,WAF和服务器对编码的处理不同,就可能绕过。

让我们用一个完整的案例,把这一节课的内容串起来。
目标:分析一个登录功能的HTTP请求和响应
步骤1:抓取请求
用Burp Suite抓取登录请求:
|POST /api/login HTTP/1.1 Host: target.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Accept: application/json Content-Type: application/json Origin: https://target.com Referer: https://target.com/login Cookie: csrftoken=abc123def456
HTTP协议是基础,不理解HTTP,做不好渗透测试。HTTP协议是Web应用的基础,所有的Web应用都基于HTTP协议,如果不理解HTTP协议,就无法理解Web应用的工作原理,也就无法做好渗透测试。 请求和响应结构,每个部分都可能有问题。请求行、请求头、请求体,响应状态行、响应头、响应体,每个部分都可能存在安全问题,都需要仔细分析。
Cookie和Session是会话管理的核心,也是安全问题的重灾区。Cookie和Session的安全配置很重要,如果配置不当,可能导致XSS、CSRF等攻击。Session ID的生成和验证也很重要,如果Session ID可预测,或者存在Session固定漏洞,都可能导致安全问题。 Header信息可能泄露信息,也可能用来绕过防护。响应头可能泄露服务器信息、后端技术信息,可以用来查找已知漏洞。请求头可能用来绕过防护,比如修改User-Agent、Referer等。
编码方式很重要,理解各种编码,才能绕过WAF和过滤。URL编码、Unicode编码、HTML实体编码、Base64编码等,理解这些编码方式,才能在测试中绕过WAF和过滤,发现漏洞。
下一节课,我们会学习渗透测试方法论。这是做渗透测试的"总指导",告诉你应该怎么系统性地进行测试。
记住:技术基础不扎实,后面的漏洞理解起来会很困难。如果你对这一节课的内容还有疑问,建议多实践,可以尝试用Burp Suite多抓几个包,多分析几个请求和响应。
实践建议: 安装Burp Suite,配置好代理,访问几个网站,抓取登录、注册等功能的请求,分析请求和响应的每个部分,尝试修改参数,看响应有什么变化,理解各种编码方式,尝试用编码绕过一些简单的过滤。
步骤2:分析请求
请求方法是POST(适合传输敏感信息),Content-Type是application/json(JSON格式),Cookie包含CSRF token,请求体是JSON格式的用户名和密码。
步骤3:分析响应
|HTTP/1.1 200 OK Server: nginx/1.18.0 Date: Mon, 01 Jan 2024 12:00:00 GMT Content-Type: application/json Content-Length: 245 Set-Cookie: sessionid=xyz789abc123; Path=/; HttpOnly; Secure; SameSite=Strict Set-Cookie: csrftoken=newtoken123; Path=/; Secure; SameSite=Strict X-Powered-By: PHP/7.4.3 Connection: keep-alive {"status":"success","message":"Login successful","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwiaWF0IjoxNjA5NDU2MDAwfQ.xxx"}
步骤4:安全分析
Server头泄露了服务器类型和版本(nginx/1.18.0),X-Powered-By头泄露了后端语言和版本(PHP/7.4.3),Cookie安全属性有HttpOnly(防XSS)、Secure(只在HTTPS传输)、SameSite=Strict(防CSRF),响应体包含JWT token,可以用来后续认证。
步骤5:测试点
基于这个分析,可以测试的点有几个。SQL注入,在username和password字段尝试注入,看看是否有SQL注入漏洞。JSON注入,尝试在JSON中注入特殊字符,看看系统对JSON的处理是否安全。CSRF,测试CSRF token的验证,看看CSRF防护是否严格。Session管理,测试Session ID的生成和验证,看看Session是否安全。信息泄露,Server和X-Powered-By头泄露了信息,可以用来查找已知漏洞。