XSS与字符编码及浏览器解析原理

XSS与字符编码基本介绍:

提起XSS 想到的就是插入字符字符编码与各种解析了!现在介绍一下在xss中最经常用到的编码
html实体编码(10进制与16进制):

如把尖括号编码[ < ] -----> html十进制: < html十六进制:&#x3 c;

javascript的八进制跟十六进制:

如把尖括号编码[ < ] -----> js八进制: \74 js十六进制: \x3c

jsunicode编码:

如把尖括号编码[ < ] ----->jsunicode: \u003c

url编码 base64编码:

如把尖括号编码[ < ] -----> url: %3C base64: PA==

html实体编码

html实体编码本身存在的意义是防止与HTML本身语义标记的冲突。但是在XSS中却成为了的一大利器,但是也不能盲目的使用!
html中正常情况只识别:html10进制,html16进制
应该如何在xss过程中灵活的使用各种编码呢?

比如现在你的输出点在这:

<img src="[代码]">

在这里过滤了script < > / \ http: 以及各种危险字符 比如创建一个html节点什么的!

有的站只允许你引用一个img文件夹里的图片 但是图片是你可以控的 可以通过抓包来修改的!

我们如果想加载外部js 或者一个xss平台的钩子我们应该怎么写呢?

那么我们可以在这里 闭合双引号 写事件: onerror=[html language="实体编码"][/html][/html]

比如现在弹个窗:

<img src="x" onerror="&#9 7;&#10 8;&#10 1;&#11 4;&#11 6;&#4 0;&#4 9;&#4 1;">

这里在编码中加了空格因为编码会被解析为下面的:
原code:

<img src="x" onerror="alert(1)">

图片.png

这里用的是html十进制编码 也可以使用十六进制的html实体编码

浏览器解析原理(参照https://blog.csdn.net/u010726042/article/details/76259398

解析过程:
浏览器在解析HTML文档时无论按照什么顺序,主要有三个过程:HTML解析、JS解析和URL解析,每个解析器负责HTML文档中各自对应部分的解析工作。下面以一篇HTML文档解析来简单的讨论下解析器如何协同工作的。

首先浏览器接收到一个HTML文档时,会触发HTML解析器对HTML文档进行词法解析(解析器-词法分析器 Parser-Lexer combination
解析可以分为两个子过程——语法分析及词法分析词法分析就是将输入分解为符号,符号是语言的词汇表——基本有效单元的集合。对于人类语言来说,它相当于我们字典中出现的所有单词。语法分析指对语言应用语法规则。解析器一般将工作分配给两个组件——词法分析器(有时也叫分词器)负责将输入分解为合法的符号,解析器则根据语言的语法规则分析文档结构,从而构建解析树,词法分析器知道怎么跳过空白和换行之类的无关字符。),

这一过程完成HTML解码并创建DOM树,接下来JavaScript解析器会介入对内联脚本进行解析,这一过程完成JS的解码工作,如果浏览器遇到需要URL的上下文环境,这时URL解析器也会介入完成URL的解码工作,URL解析器的解码顺序会根据URL所在位置不同,可能在JavaScript解析器之前或之后解析。每个解析过程中也有许多细节,下面再做具体讨论。

基本概念:

HTML字符实体:

在呈现HTML页面时,针对某些特殊字符如“<”或”>”直接使用,浏览器会误以为它们标签的开始或结束,若想正确的在HTML页面呈现特殊字符就需要用到其对应的字符实体。

字符实体是一个预先定义好的转义序列,它定义了一些无法在文本内容中输入的字符或符号。字符实体以&开头+预先定义的实体名称,以分号结束,如“<”的实体名称为< 或以&开头+#符号以及字符的十进制数字,如”<”的实体编号为<,字符都是有实体编号的但有些字符没有实体名称。

JavaScript编码:最常用的如“\uXXXX”这种写法为Unicode转义序列,表示一个字符,其中xxxx表示一个16进制数字,如”<” Unicode编码为“\u003c”。

URL编码:%加字符的ASCII编码对于的2位16进制数字,如”/”对应的URL编码为%2f。

下面结合具体示例来讨论下浏览器的解析原理过程和XSS复合编码的一些内容:

<a href="javascript:alert(1)">test</a>

针对上述a标签我们分析一下该环境中浏览器的解析顺序,首先HTML解析器开始工作,并对href中的字符做HTML解码,接下来URL解析器对href值进行解码,正常情况下URL值为一个正常的URL链接,如:“https://www.yirendai.com“,那么URL解析器工作完成后是不需要其他解码的,但是该环境中URL资源类型为JavaScript,因此该环境中最后一步JavaScript解析器还会进行解码操作,最后解析的脚本被执行。
整个解析顺序为3个环节:HTML解码àURL解码àJS解码
我们对href值做一些编码的转换,对照刚才分析的解析过程,思考一下脚本是否会正常执行?
Test1:URL 编码 "javascript:alert(1)”

URL编码“javascript:alert(1)”=“%6A%61%76%61%73%63%72%69%70%74:%61%6C%65%72%74%28%31%29”
编码后:

<a href="%6A%61%76%61%73%63%72%69%70%74:%61%6C%65%72%74%28%31%29">test1</a>

test2:HTML字符实体编码 "javascript" 、URL 编码 "alert(2)"

HTML编码"javascript"="javascript"

URL编码"alert(2)"=” %61%6C%65%72%74%28%32%29”

<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;:%61%6C%65%72%74%28%32%29">test2</a>

Test3:对<a href="javascript:alert(3)">test3</a>做JS编码àURL编码àHTML编码共3层。

JS编码:<a href="javascript:\u0061\u006c\u0065\u0072\u0074(3)">test3</a>

URL编码:<a href="javascript:%5c%75%30%30%36%31%5c%75%30%30%36%63%5c%75%30%30%36%35%5c%75%30%30%37%32%5c%75%30%30%37%34(3)">test3</a>

HTML编码:<a href="&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#51;&#49;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#54;&#51;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#54;&#37;&#51;&#53;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#55;&#37;&#51;&#50;&#37;&#53;&#99;&#37;&#55;&#53;&#37;&#51;&#48;&#37;&#51;&#48;&#37;&#51;&#55;&#37;&#51;&#52;&#40;&#51;&#41;">test3</a>

图片.png

图片.png

图片.png

经测试只有2和3可以弹窗,1不能。

【过程分析】
许多童鞋把Test1放到HTML里发现脚本并没有正常执行,就会想按照刚才分析的,URL解码之后Javascript解析器完成解码操作,脚本应该会正常执行啊,这里就有一个URL解析过程中的一个细节了,不能对协议类型进行任何的编码操作,否则URL解析器会认为它无类型,就导致Test1中被编码的“javascript”没有解码,当然不会被URL解析器识别了。

那Test2也是对javascript编码了为什么可以执行呢?因为"javascript"是做的HTML实体编码,HTML解析器工作时,href里的HTML实体会被解码,接下来URL解析器工作解析href属性里的链接时,"javascript"协议在第一步被HTML解码了,这样URL解析器是可以识别的,然后继续解析后面的”%61%6C%65%72%74%28%32%29”,最后JavaScript解析器完成解析操作,脚本执行。

Test3实现了3层复合编码,每一层编码都能正常执行,贴出来供大家可以自行验证加深理解

<img src=x onclick=” {$value}”>

下面我们分析一下2层复合编码的img标签

代码如下:

image

假设onclick属性值为“用户可控”数据,思考一下该如何编码才能防住XSS?

首先传入的“用户可控”数据处在HTML环境中,然后再是onclick环境中,因此浏览器的解析顺序为:HTML解码àJS解码;

HTML解码: \u0061\u006c\u0065\u0072\u0074('YISRC')

JS解码:alert('YISRC')

解码完成,脚本执行,细心的童鞋可能会问了value值的编码顺序为解码的逆序,先将alert进行javascript编码为\u0061\u006c\u0065\u0072\u0074,然后再对整个value值进行HTML编码,居然还可以弹框?

我们来分析一下JavaScript解析的一个细节,Javascript解析器工作的时候将\u0061\u006c\u0065\u0072\u0074进行js解码后为“alert”,而“alert”是一个有效的标识符名称,它是能被正常解析的。像圆括号、双引号、单引号等等这些控制字符,在进行JavaScript解析的时候仅会被解码为字符串文本或者上面讲的标识符名称,例如:<script>alert('YISRC\u0027)</script>对控制字符单引号进行js编码,解析时\u0027被解码成文本单引号,无法闭合因此不能成功执行。本例中只对“alert”进行了Unicode,并没有对圆括号这类控制字符进行Unicode,是因为我想弹框啊,但在正常的XSS防御中肯定要对这些控制字符进行Unicode的。
下面通过几个简单的场景加深理解一下:

假设:alert里的值为用户输入的可控数据,服务端为了防御XSS做了HTML编码

示例一:

用户输入的【");alert("SRC】在服务端HTML实体编码之后返回到前端被浏览器解析执行


图片.png

1、首先【");alert("SRC 】在HTML解码后变成了【");alert("SRC】。

2、JavaScript解析时,变成了【alert("YISRC ");alert("SRC】,当然可以正常执行了,如下图所示:


图片.png

图片.png

事实证明,该上下文环境中只做HTML编码是不能完全防御XSS的。
示例二:

现在调整服务端XSS防御策略为:JS编码àHTML编码

如下图所示,成功防御:


图片.png

图片.png

来分析一下:

 1、首先【&#92;&#117;&#48;&#48;&#50;&#55;&#92;&#117;&#48;&#48;&#50;&#57;&#92;&#117;&#48;&#48;&#51;&#98;&#92;&#117;&#48;&#48;&#54;&#49;&#92;&#117;&#48;&#48;&#54;&#99;&#92;&#117;&#48;&#48;&#54;&#53;&#92;&#117;&#48;&#48;&#55;&#50;&#92;&#117;&#48;&#48;&#55;&#52;&#92;&#117;&#48;&#48;&#50;&#56;&#92;&#117;&#48;&#48;&#50;&#55;&#92;&#117;&#48;&#48;&#53;&#51;&#92;&#117;&#48;&#48;&#53;&#50;&#92;&#117;&#48;&#48;&#52;&#51;】经过第一步HTML解码后变为【\u0027\u0029\u003b\u0061\u006c\u0065\u0072\u0074\u0028\u0027\u0053\u0052\u0043】

 2、JavaScript解析器工作,【\u0027\u0029\u003b\u0061\u006c\u0065\u0072\u0074\u0028\u0027\u0053\u0052\u0043】变为【');alert('SRC】,刚才已经讲过JavaScript解析时只有标识符名称不会被当做字符串,控制字符仅会被解析为标示符名称或者字符串,因此'\u0027'被解释成单引号文本,\u0028和\u0029被解释成为圆括号文本,不会变为控制字符被解析执行。

事实证明,合理的编码方式是防御XSS中首先要考虑到的。

结合上面的内容,自己分析一下value1和value2所处的上下文环境,要防御XSS需要怎么做组合编码?


image
     浏览器解码顺序:

               Value1:HTML解码àJavaScript解码àURL解码

               Value2:HTML解码àURL解码àJavaScript解码àURL解码
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342