XSS中的JS转义和HTML转义

admin 2021年4月2日20:38:29评论52 views字数 2277阅读7分35秒阅读模式

今天在给客户做渗透测试时,遇到了一处XSS。虽然很简单,但有点小意思。引发了我对js转义和html转义在XSS中的思考,故做个小笔记记录一下。两个例子都会以仿写现实场景的代码的说明问题。

0x01 一点知识贮备

1.1 关于转义

**;格式的字符串是html的转义字符,是JS的转义符,转义的目的就是告诉解析器该符号为字符,而不是代码,防止代码出现歧义。

1.2 浏览器解析原则

  1. 若果存在html转义字符串,HTML解析引擎会先把转义字符解析为字符串
  2. HTML解析引擎按照从上到下,从外向里解析html标签
  3. 遇到html标签浏览器会让html解析引擎解析,遇到标签,浏览器会让JS解析引擎对标签内容进行解析。

1.3 html源码和浏览器解析结果

在浏览器中我们按住快捷键ctrl+u,看到的是服务器接受我们的请求后返回的html源码。按F12进入开发者工具面板,开发者工具分析出的DOM结构,就是浏览器的解析结果。

ps:html源代码DOM结构和浏览器解析后的DOM结构是有区别的!

0x02 XSS与JS转义

2.1 测试代码和问题描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


"Content-Type" content="text/html; charset=utf-8">
一个XSS


>
var input_str = "";
if(input_str.length>0){
document.write("Your input:"+input_str);
}

""
method="post">
"text" name="str" />
"submit" value="提交">



当我们提交,前端没有出现我们期待的弹窗,而是输出了以下字符串。

1
"; if(input_str.length>0){ document.write("Your input:"+input_str); }

而当我们提交,则可以正常弹框。如何解释这两种情况,我们来思考一下?

2.2 原理分析

当我们输入第一个payload提交后,得到的html源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
html>
head>
meta http-equiv="Content-Type" content="text/html; charset=utf-8">
title>一个XSStitle>
head>
body>
script type="text/javascript">
var input_str = "script>alert(1);script>";
if(input_str.length>0){
document.write("Your input:"+input_str);
}
script>
form action="" method="post">
input type="text" name="str" />
input type="submit" value="提交">
form>
body>
html>

当我们的HTML解析器解析到标签时,它会快速去查找离它最近的闭合标签。这时它查找到是8行中的,而不是12行的。这时标签内的var input_str = "被交给js引擎去解析。而8行和12行的之间的代码被当成字符串输出到前端页面。而由于6行标签没有配对成功,故不会被浏览器解析为一个合法标签。 所以最终的解析结果是第8行的被解析为字符串,被解析为html标签。

当我们输入第二个payload提交后,得到的html源码如下,与上面代码类似,只是差异只在第8行(多了一个/)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
html>
head>
meta http-equiv="Content-Type" content="text/html; charset=utf-8">
title>XSS与JS编码title>
head>
body>
script type="text/javascript">
var input_str = "script>alert(1);/script>";
if(input_str.length>0){
document.write("Your input:"+input_str);
}
script>
form action="" method="post">
input type="text" name="str" />
input type="submit" value="提交">
form>
body>
html>

还是同样的解析原则,html解析引擎解析到7行的时,它会快速去查找离它最近的闭合标签。这是在到第8行时发现标签,而不是,
故继续往下,直到找寻到12行的标签,才完成了配对。这时8行和11行的代码交给了js引起去解析。由于双引号包围,所以js解析器会把它当字符串处理。 所以最终的解析结果是第8行中的都是字符串而不是标签。

值得注意的是第8行当中的字符的引入使得标签在html解析引擎解析时未在第8行被闭合,同时又因为为js语法中的转义字符,故在js解析引擎解析时,又能正常解析input_str变量的值为字符串,所以最总成功弹窗,很巧妙!

这些解析结果都是可以使用浏览器自带的F12开发者工具开验证。

0x03 XSS与html转义

3.1 测试代码与问题描述

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22


"Content-Type" content="text/html; charset=utf-8">
XSS与html编码



if(isset($_POST['submit'])){
echo "]."'>str1";
echo "
"
;

echo "str2:".$_POST['str2'];
}
?>
""
method="post">

str1:"text" name="str1" />


str2:"text" name="str2" />


"submit" name="submit" value="提交">



我们将javascript:alert(1);html转义得到如下字符串,并填写到str1输入框

1
javascript:alert(1);

我们将html转义后得到如下字符,并填写到str2输入框

1
<script>alert(1);</script>

提交后发现点击str1链接可以弹框,说明前者被当代码来执行了,而后者被当字符串输出了。我们来看这时为何?

3.2 原理分析

提交payload之后,服务器返回的html代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
html>
head>
meta http-equiv="Content-Type" content="text/html; charset=utf-8">
title>XSS与编码title>
head>
body>
a href='javascript:alert(1);'>str1a>br/>str2:<script>alert(1);</script> form action="" method="post">
str1:input type="text" name="str1" />
br/>
str2:input type="text" name="str2" />
br/>
input type="submit" name="submit" value="提交">
form>
body>
html>

而浏览器html解析器解析后的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
html>
head>
meta http-equiv="Content-Type" content="text/html; charset=utf-8">
title>XSS与编码title>
head>
body>
a href='javascript:alert(1);'>str2:<script>alert(1);</script>form action="" method="post">
str1:input type="text" name="str1" />
br/>
str2:input type="text" name="str2" />
br/>
input type="submit" name="submit" value="提交">
form>
body>
html>

通过解析结果,我们可以很容易看到。payload其实都被当成了字符输出了。只是在点击str1连接时,前者被解码之后的字符被当代码执行了。而后者被浏览器html解析器解码后为<script>alert(1);</script>,而不是,所以js代码自然无法执行。所以str2应该为,才可以触发XSS。

0x04 总结

通过对js转义和html转义在XSS中的应用,让我对浏览器解析html代码的解析过程有了更深的了解。可以借鉴其中的原理来构造更简洁,精巧的XSS的payload,也可以尝试用来绕waf。

参考文章

XSS绕过学习

文章来源于gv7.me:XSS中的JS转义和HTML转义

相关推荐: 148处XSS你如何提交给开发修复?

客户:你上周发的渗透测试报告中说存在有148处XSS。今天开发需要修复,但你的渗透测试报告只列举了三处。开发需要提供所有存在漏洞的地址,才能修复完整。 我:其实可以在系统数据提交的入口,对get和post数据包中参数进行过滤就好了。那样就修改一处就可以了。 客…

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2021年4月2日20:38:29
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   XSS中的JS转义和HTML转义https://cn-sec.com/archives/318063.html

发表评论

匿名网友 填写信息