RuoYi学习-跨站脚本攻击(XSS)
本文最后更新于 2024-04-01,欢迎来到我的Blog! https://www.zpeng.site/
RuoYi学习-跨站脚本攻击(XSS)
1.介绍
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容。
2.类型
XSS的类型:
存储型 XSS(Stored XSS):攻击者将恶意代码存储到目标网站的数据库中,当其他用户浏览相关页面时,恶意代码会从服务器上返回并在用户的浏览器中执行。
反射型 XSS(Reflected XSS):攻击者通过构造带有恶意代码的URL,并诱导用户点击该链接,服务器接收到请求后,将恶意代码反射回用户的浏览器并执行。
DOM 型 XSS(DOM-based XSS):攻击者利用网页的 DOM(文档对象模型)结构漏洞,修改了网页的内容,使得恶意代码被执行。
2.1存储型 XSS(Stored XSS)
存储型 XSS 的原理是攻击者将恶意脚本注入到目标网站的数据库中,然后当其他用户访问该网站时,恶意脚本会从数据库中取出并在用户浏览器中执行,从而导致安全漏洞。
以下是一个示例说明存储型 XSS攻击的过程:
攻击者登录一个论坛网站,并找到一个可以留下评论或发帖的地方。
攻击者在评论或帖子中注入一段包含恶意脚本的代码,例如
<script>alert('存储型XSS攻击');</script>
。用户A访问这个论坛网站,并打开攻击者发布的帖子或评论。
网站从数据库中获取帖子或评论的内容,并在用户A的浏览器中显示。
用户A的浏览器解析并执行了恶意脚本,弹出一个警告框,显示"存储型XSS攻击"的信息。
攻击者可以利用该漏洞进行更进一步的攻击,例如窃取用户敏感信息、钓鱼攻击等。
存储型 XSS攻击的危害性较大,因为恶意脚本会被长期存储在目标网站的数据库中,影响所有访问该网站的用户。为了防止存储型 XSS攻击,开发者应该对用户输入进行有效的过滤和转义,以确保恶意脚本无法被存储并执行。同时,使用内容安全策略(Content Security Policy)和输出编码等技术也能增强网站的安全性。
2.2反射型 XSS(Reflected XSS)
反射型 XSS 利用了应用程序对用户输入的不恰当处理或输出过程中的漏洞。攻击者通过构造恶意的请求,将恶意脚本注入到应用程序返回的响应中。一旦用户访问了携带恶意脚本的链接,浏览器会执行该脚本,从而导致攻击者能够窃取用户的敏感信息、修改页面内容或进行其他恶意操作。
下面是反射型 XSS 的工作原理:
攻击者构造特制的恶意请求,并将恶意脚本作为参数或路径的一部分发送给目标网站。
目标网站接收到恶意请求后,服务器端未经充分验证或过滤就将用户提供的数据(包含恶意脚本)嵌入到响应中。
服务器将带有恶意脚本的响应发送给用户的浏览器。
用户在浏览器中打开响应时,恶意脚本被执行,攻击成功。
举例说明:
假设有一个在线留言板应用程序,用户可以在留言板上发布自己的留言。该应用程序存在一个漏洞,即没有对用户输入进行充分过滤和验证。
攻击者利用这个漏洞进行反射型 XSS 攻击的步骤如下:
攻击者构造一个恶意链接,包含了一个恶意脚本参数。例如:
http://example.com/message?content=<script>alert('XSS')</script>
攻击者将这个恶意链接发送给目标用户。
用户点击了这个链接,浏览器向服务器发送请求。
服务器接收到请求后,将恶意脚本参数
<script>alert('XSS')</script>
直接嵌入到响应中。响应被发送回用户的浏览器,浏览器解析响应时执行了恶意脚本。
弹出一个警报框,显示 "XSS",表示攻击成功。
通过这种方式,攻击者可以注入任意恶意脚本并在用户浏览器上执行,进而窃取用户敏感信息、篡改页面内容或进行其他恶意操作。为了防止反射型 XSS 攻击,开发人员需要对用户输入进行充分的验证和过滤,并对输出的数据进行适当的编码,以确保用户提供的数据不会被解释为可执行的脚本。
2.3DOM 型 XSS(DOM-based XSS)
DOM 是一种表示 HTML 文档结构的对象模型,它可以通过 JavaScript 来操作和修改。DOM-based XSS 攻击利用了前端页面中存在的漏洞,使得攻击者能够在 DOM 中插入恶意代码,并以合法用户的身份将其执行。
以下是 DOM-based XSS 的基本原理:
攻击者找到一个可被用户访问的页面,该页面包含有漏洞的 JavaScript 代码或由用户输入直接生成的 DOM 结构。
攻击者通过某种方式,例如发送特制的 URL 或通过篡改页面内容的方式,将恶意代码注入到页面中。
用户在浏览器中访问被注入恶意代码的页面时,浏览器解析并执行了这些代码,从而触发了攻击。
恶意代码在用户的浏览器中修改了页面的 DOM 树结构,通过操作 DOM 元素和属性,攻击者可以实现各种攻击行为,如盗取用户信息、篡改页面内容等。
下面是一个简单的例子来说明 DOM-based XSS 的原理:
<!DOCTYPE html>
<html>
<head>
<title>DOM-based XSS Example</title>
</head>
<body>
<input type="text" id="userInput">
<button onclick="displayInput()">Submit</button>
<div id="output"></div>
<script>
function displayInput() {
var userInput = document.getElementById('userInput').value;
document.getElementById('output').innerHTML = userInput;
}
</script>
</body>
</html>
在上述示例中,用户在输入框中输入内容,然后单击按钮,输入的内容将被显示在网页上的 <div>
元素中。
然而,如果攻击者通过恶意链接或其他方式将以下内容作为输入值传递给上述页面:
"><script>alert('XSS Attack!');</script><span id="xss">
这将导致 DOM 型 XSS 攻击。当用户单击按钮时,由于未对输入进行正确的验证和过滤,恶意脚本将被注入到页面的 <div>
元素中:
<div id="output">
"><script>alert('XSS Attack!');</script><span id="xss"></div>
结果是,恶意脚本 alert('XSS Attack!');
将在受害者的浏览器中执行,弹出一个警告框。
3.若依
3.1配置yml
# 防止XSS攻击
xss:
# 过滤开关
enabled: true
# 排除链接(多个用逗号分隔)
excludes: /system/notice
# 匹配链接
urlPatterns: /system/*,/monitor/*,/tool/*
3.2配置java
src/main/java/com/ruoyi/framework/config/FilterConfig.java
是个过滤器
package com.ruoyi.framework.config;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.DispatcherType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.ruoyi.common.filter.RepeatableFilter;
import com.ruoyi.common.filter.XssFilter;
import com.ruoyi.common.utils.StringUtils;
/**
* Filter配置
*
* @author ruoyi
*/
@Configuration
public class FilterConfig
{
@Value("${xss.excludes}")
private String excludes;
@Value("${xss.urlPatterns}")
private String urlPatterns;
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
@ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
public FilterRegistrationBean xssFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setDispatcherTypes(DispatcherType.REQUEST);
registration.setFilter(new XssFilter());
registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
registration.setName("xssFilter");
registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
Map<String, String> initParameters = new HashMap<String, String>();
initParameters.put("excludes", excludes);
registration.setInitParameters(initParameters);
return registration;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
@Bean
public FilterRegistrationBean someFilterRegistration()
{
FilterRegistrationBean registration = new FilterRegistrationBean();
registration.setFilter(new RepeatableFilter());
registration.addUrlPatterns("/*");
registration.setName("repeatableFilter");
registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
return registration;
}
}
src/main/java/com/ruoyi/common/filter/XssFilter.java
package com.ruoyi.common.filter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.enums.HttpMethod;
/**
* 防止XSS攻击的过滤器
*
* @author ruoyi
*/
public class XssFilter implements Filter
{
/**
* 排除链接
*/
public List<String> excludes = new ArrayList<>();
@Override
public void init(FilterConfig filterConfig) throws ServletException
{
String tempExcludes = filterConfig.getInitParameter("excludes");
if (StringUtils.isNotEmpty(tempExcludes))
{
String[] url = tempExcludes.split(",");
for (int i = 0; url != null && i < url.length; i++)
{
excludes.add(url[i]);
}
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException
{
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (handleExcludeURL(req, resp))
{
chain.doFilter(request, response);
return;
}
XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
chain.doFilter(xssRequest, response);
}
private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
{
String url = request.getServletPath();
String method = request.getMethod();
// GET DELETE 不过滤
if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
{
return true;
}
return StringUtils.matches(url, excludes);
}
@Override
public void destroy()
{
}
}
3.3效果
输入<script>alert('存储型XSS攻击');</script>
存入alert('存储型XSS攻击');
- 感谢你赐予我前进的力量