-
Notifications
You must be signed in to change notification settings - Fork 31
XSS 漏洞
XSS(跨站脚本攻击)是一种常见的Web安全漏洞,攻击者可以通过注入恶意脚本代码,实现对用户的攻击。在Java Web开发中,以下业务代码可能存在XSS漏洞:
- 表单提交和查询结果的显示:在表单提交和查询结果的显示中,用户输入的数据没有经过过滤,直接显示在页面上,攻击者可以通过注入恶意脚本代码实现攻击。解决办法是对用户输入的数据进行HTML编码,可以使用Java自带的工具类或者第三方库来实现。
- URL参数的传递:如果使用URL传递参数,攻击者可以通过注入恶意脚本代码实现攻击。解决办法是对URL参数进行编码,可以使用Java自带的工具类或者第三方库来实现。
- 富文本编辑器:富文本编辑器中用户输入的内容可能包含HTML标签和脚本代码,攻击者可以通过注入恶意脚本代码实现攻击。解决办法是使用富文本编辑器自带的过滤器或者使用第三方库对用户输入的内容进行过滤。
- JavaScript代码的编写:在编写JavaScript代码时,要注意防止XSS攻击,不要直接使用用户输入的数据作为JavaScript代码的参数,可以对用户输入的数据进行编码。
XSS漏洞的原因是业务代码没有对用户输入的数据进行过滤和编码,攻击者可以通过注入恶意脚本代码实现攻击。为了防止XSS漏洞,需要在业务代码中对用户输入的数据进行过滤和编码。 XSS攻击可以达到不同的目的,但大致上有以下几种:
- 窃取用户信息:攻击者可以通过注入恶意脚本代码获取用户的敏感信息,例如用户名、密码、Cookie等。
- 欺骗用户:攻击者可以通过注入恶意脚本代码修改页面内容,伪装成合法的页面或者提供虚假的信息,从而欺骗用户。
- 利用用户权限进行恶意操作:攻击者可以通过注入恶意脚本代码获取用户的权限,例如通过获取管理员的权限进行恶意操作。
- 传播病毒:攻击者可以通过注入恶意脚本代码,在用户访问网页时传播病毒。
考察:如何通过修改请求参数为恶意的HTML来达到XSS攻击的效果。
我们在输入框内任意输入字符发现会给后端发送一个请求:/ElectricRat/xss/getMarkData?content=1
请求 /ElectricRat/xss/getMarkData?content=1,发现我们输入的 content 的参数会被渲染到页面中去。
这个使用我们使用常见payload:<script>javascript:alert(1)</script>
即可攻击成功。
考察:如何通过XSS攻击获取登录状态下的Cookie
遇到一个后台登录的输入框,这里我们输入admin/123456
参考payload:<img src =q onerror=prompt(document.cookie)>
即可打印cookie,HTTPOnly无法通过这种方式获取。
考察:理解存储XSS的表现形式
参考payload:<iframe/src="data:text/html,<svg onload=alert(1)>">
考察:理解DOM型xss表现形式
参考payload:<iframe/src="data:text/html,<svg onload=alert(1)>">
考察:利用页面锚点定位特性完成XSS攻击
在URL的后边增加#
并填写内容,访问后发现页面上显示了我们输入的内容。
payload:<iframe/src="data:text/html,<svg onload=alert(1)>">
考察:利用各种输入框盲打XSS,管理员访问后台获取数据时XSS会成功执行。
PS:这里可以尝试获取Cookie
参考payload:<iframe/src="data:text/html,<svg onload=alert(1)>">
点击提交后,我们通过admin/123456
登录后台查看数据。
当我们登录成功后,发现我们输入的XSS被成功执行了。
考察:编码绕过方式
此关使用了replace
和遍历过滤的方式将输入的HTML标签全部移除,突破口在decodeURIComponent
,通过URL编码的方式来绕过replace
函数过滤。
参考payload:<a href="jAvAsCrIpT:alert(1)">X</a>
将该payload进行URL编码:%3c%61%20%68%72%65%66%3d%22%6a%41%76%41%73%43%72%49%70%54%26%63%6f%6c%6f%6e%3b%61%6c%65%72%74%26%6c%70%61%72%3b%31%26%72%70%61%72%3b%22%3e%58%3c%2f%61%3e
点击提交后发现多了一个a标签,点击后执行了我们的JS代码。
考察:如何绕过replace过滤
这里通过replace
函数将&
、<
、>
、"
转换成了实体编码,但唯独单引号没有给转移。
参考payload:123'onmouseover='prompt(1)'
提交后鼠标放到输入框范围内,成功触发代码执行。
考察:如何绕过replace过滤,将XSS输出到页面上。
我们输入的任何文本都直接拼接到href属性之内了。
参考payload:javascript:alert(1)
点击提交后,点击链接触发代码执行。
考察:当输出的内容被拼接到JS语句中去,如何将我们自己的代码插入并执行。
无论我们输入什么都会拼接一个<addition>
,通过观察发现每提交一次都会增加一个脚本标签。我们填写的内容被拼接到num
变量内。
参考payload:';alert(1);a='
,闭合掉语句后可以任意执行我们想要的代码。
XSS攻击最终是在游览器客户端展示,其本身与HTML和JS息息相关。根据后端渲染、前后端分离、前端渲染的三种情况,也有不同的XSS展示效果。
一种是前后端分离,在请求接口后返回的响应包设置了ContentType
为text/html
那么极有可能会产生漏洞。在实战中一般是 Jsonp 回调接口处会出现这种情况:
http://xxx.xxxx.xxx/?callback=jQuery11130014313909482240961_1561597612526&lastpagetime=1559829276&_=1561602219158
这里的 callback
是可控的。一旦我们设置了返回数据包内容类型为text/html
那么将会导致XSS反射型漏洞的产生。
response.setContentType("text/html;charset=utf-8");
还有一种是后端渲染的情况。使用 JSP 或者其他模板语言引擎。例如:Thymeleaf、Velocity、FreeMarker。 一般的JSP输出变量到HTML的写法可以这么写:
<% String msg = request.getParameter('msg'); %>
<%=msg%>
其他的模板语言有不同的写法,但只要是没有经过过滤直接输出到HTML页面中去的,游览器解析后就会造成XSS攻击。
最后一种是前端渲染。有很多业务都可以使用前端完成,如今有很多前端的开发框架例如:React、Vue、Angular。尽管十分推荐使用类似innerText
的方式显示数据,但会存在某些业务上无法避免的使用类似innerHTML
的方法显示数据,一旦没有做好足够严格的数据校验,那么将会产生XSS漏洞。
function generateNote(mes){
return `<div class="callout callout-info">
<h5><i class="fas fa-info"></i> Note:</h5>${mes}</div>`;
}
function submitText(){
$("#notice")[0].innerHTML = generateNote("我不在乎你输入的是什么,就算是:" + $("#own-text")[0].value)
}
我开发时没有选择使用框架,直接使用了原生JS ES6语法拼接字符串,并且大量使用innerHTML
属性。
如果想要减少XSS攻击的产生,我们可以使用StringEscapeUtils
工具对用户输入的内容进行转义。
代码来源:com/pika/electricrat/xss/dto/XssServlet.java
public void getMarkData(HttpServletRequest request, HttpServletResponse response) throws IOException {
String content = request.getParameter("content");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("我不在乎你输入的是什么,就算是:" + StringEscapeUtils.escapeHtml(content));
}