html代码工作原理,浏览器工作原理与XSS-HTML编码

简介

编码问题一直是个痛点,尤其是当我们对XSS攻击原理不是很熟悉的话,防护起来很容易造成遗漏。要想很好的防护住XSS攻击,需要对浏览器解析HTML、JS、CSS的原理弄清楚,了解浏览器的工作原理,才能做好防护工作。小编也是搜集网上资料进行学习,并整理分享下该篇文档。

(一)浏览器的结构

浏览器的主要组件,包含用户界面、浏览器引擎、呈现引擎、网络、用户界面后端、JavaScript解释器、数据存储。这里我们主要需要了解呈现引擎,其主要负责显示请求内容,如果请求的内容是HTML,它就负责解析HTML和CSS内容,并将解析后的内容显示在屏幕上。

c0dc4bbab8e8

值得注意的是,Chrome浏览器的每个标签页都分别对应一个呈现引擎实例,每个标签页都是独立的进程。

呈现引擎一开始会从网络层获取请求文档的内容,内容的大小一般限制在 8000 个块以内。

呈现引擎解析HTML文档,将标记转换成内容树上的DOM节点,将CSS元素样式转换成另外的树结构:呈现树。构建完成后,进入布局阶段,每个节点都会分配一个应该出现在屏幕上的坐标,由用户界面后端层将每个节点绘制出来。

解析的过程其实就是编译原理那一套东西,由解析器和词法分析器将文档内容构造成一个有效的解析树,最后由翻译器,将解析树翻译成浏览器可执行的机器指令,最后我们看到的就是一个可视化的web页面。

HTML解析器的任务是将HTML标记解析成解析树,常规解析器是不适用与HTML的,因为我们知道HTML具有很强的容错性,并不是与上下文无关的语法,我们会通过document.write添加额外的标记。HTML的定义采用了DTD格式,包括允许使用的元素及其属性和层次结构。HTML的解析是浏览器通过标记化、树结构的形式完成解析构建的。

CSS是上下文无关的语法,可以使用常规的解析器进行解析。  关于具体如何解析,便不在这里阐述,大家只需要有个大致的了解即可。

处理脚本和样式表的顺序

HTMl==》CSS==》JavaScript 针对这个顺序我是报迟疑态度的,因为上述我们也提到过,在遇到

(二)浏览器解码过程

HTMl==》CSS==》JavaScript ,针对这个解析顺序,我们这里可以先不讨论,我们的目的是关心如何正确的编码,那么我只需要关注,对于常用的HTML页面,浏览器是如何解码的即可。

1、HTML实体

${content}

如上述代码所示,在P标签中存在一个输出变量${content},浏览器解析的过程,首先是HTML解析,解析到P标签时,解析Content的内容,然后将其在页面显示出来。

如果我们把Content的内容换成上面内容,即script脚本,那么浏览器解析的时候,当解析到P标签时,发现里面的内容存在script标签,便会把其当做JavaScript脚本进行解析,从而达到XSS攻击的目的。

c0dc4bbab8e8

所以针对此类HTML实体间的输出,我们希望输出的是HTML文本内容,而不是HTML标签、JS代码等,所以我们在输出时,需要对Content进行HTML编码,可使用OWASP ESAPI的ESAPI.encoder().encodeForHTML()。 HTML编码一般将如下几个字符进行编码替换:

1. & —> &

2. < —> <

3. > —> >

4. " —> "

5. ' —> '

6. / —> /

在编码的字符中,其中&、、"、' 五个字符是XML中定义的实体,所以我们需要对其进行编码,因为HTML也算作XML的一种,/ 字符作为HTML标签的结束协助符,避免破坏标签。

HTML编码的作用就是将原本能被HTML解析成标签的东西,转换成字符串文本,以文本的形式展现

2、HTML通用属性

name是input的属性,所以HTML解析时,会对name属性的内容进行HTML解码,假如此时${firstname}的值为如下内容时,HTML属性被截断插入了onclick事件。

c0dc4bbab8e8

所以针对这种常规的HTML属性,都需要对其进行HTML属性编码,其实和HTML实体编码类似,只不过编码字符范围可能多些,除了字母数字外,所有ASCII码小于256的字符均进行XX;编码,具体的参见ESAPI.encoder().encodeForHTMLAttribute的实现。其实属性XSS中最主要的是拆分属性标签,注入可执行JS的属性,并对其添加而已代码。

对于通用属性的编码方式不适用于href、src、style、事件处理函数(onclick、onmouseover等),因为本身这些属性是支持伪协议的,该编码无效。

3、支持协议解析的HTML属性

在上述的2中场景中我们都可以使用HTML编码,基本都能够很好的防御住XSS攻击,在第二点中我们强调的是HTML通用属性,而并非全部属性,因为在HTML中H还存在许多支持协议解析的HTML属性,如onclick,onerror,href,src等,类似这种属性是无法通过HTML编码防范XSS攻击,因为浏览器会先解析HTML编码的字符,将其转换为该属性的值,但是该属性本身支持JS代码执行,所以浏览器在HTML解码后,对该属性的值进行JS解析,故会执行相应的代码。

3.1 href属性引入的XSS

href xss

c0dc4bbab8e8

href xss HTML属性编码无效

c0dc4bbab8e8

href属性的值应该是一个有效的URL链接,如果我们对整个href属性值进行URL编码,则会导致URL无法跳转,应为浏览器在解析href时,会通过分号、/字符解析出协议或目录,当对全部的值进行URL编码后,则无法进行正常解析;如果对协议后的内容进行URL编码则也无法防御XSS攻击,如下例所示:

Href xss 部分URL编码无效

c0dc4bbab8e8

此时假如我们对alert('href xss')进行JavaScript编码,结果又会如何?(JavaScript编码将字符编码成\x+16进制的形式,对款字节编码成Unicode)

Href XSS JavaScript编码

测试点击没有任何反应,XSS执行失败;

问什么会存在上述的结果?我们看一下href属性的解码解析过程,页面渲染,首先进行HTML解码解析,解析出是href属性后(点击),会对href的值进行URL解码解析,获取到URL的实际值,当发现不是HTTP/HTTPS,而是JavaScript协议后,就会执行JavaScript解码解析,从而执行了alert()函数。

3.2 onclick属性XSS

现在我们来看一下on事件属性:

点击增加一行显示

(此处的$value往往一般都是后台模板替换的变量)

点击增加一行显示

function addlinecontent(value){

document.getElementById("addlinecontent").innerText=value;

}

当$value的值 hello world'),alert('onclick xss 时,出发XSS攻击:

c0dc4bbab8e8

对$value进行HTML编码:hello world'),alert('onclick xss htmlencode ,结果显示如下,存在XSS

c0dc4bbab8e8

此时如果将$value进行JavaScript编码:显示正常,不存在XSS

c0dc4bbab8e8

onclick属性解析的过程:先进行HTML解析,再进行JavaScript解析,所以仅仅进行HTML编码是无法防御XSS的,需要对值进行JavaScript编码。

如果当存在 这种情况时,是很难进行防护的,因为无法直接对$event进行JavaScript编码,如果编码了,则无法解析出需要执行的函数代码。如果整个内容是来自客户端输入的,那么需要对event需要进行黑白名单的校验,防止出现危险字符,防止调用危险的JS函数。通常不建议出现这种写法,建议对event进行拆分,通过控制参数达到相应的目的:

关于如何编码,需要抓住一个重点,就是传进的值最终是谁消费(期望执行者),谁消费谁负责;对于支持伪协议的属性,仅仅通过编码是不行的,需要匹配过滤协议头,最好后台拆分拼接返回期望的值。(不能对协议类型进行任何的编码操作,否则URL解析器会认为它无类型)

编码的顺序和解码解析的顺序正好相反:

jsencode(htmlencode("))

htmlencode(jsencode("))

4、DOM XSS类型

DOM XSS是基于文档对象模型的XSS,属于反射型XSS。

1. 使用document.write直接输出

2. 使用innerHTML直接输出

3. 使用location、location.href、location.replace、iframe.src、document.referer、window.name等

.......

造成DOM XSS的原因主要是在重新修改页面时,没有考虑到对变量的编码和校验过滤;

document.body.innerHTML="url:" +url+" ";

其中对于变量url则是注入点:javascript:alert('dom xss');

对于DOM XSS主要是由于本地客户端获取DOM数据在本地执行导致的,所以在编码中,要避免客户端文档重写,重定向或其它修改DOM元素操纵,对于输出至HTML中的值进行HTML编码,输出至JS中的值进行JS编码。

5、setTimeout/setInterval/eval等XSS

针对这类的XSS,我们单独拿出来说,因为这类XSS隐藏的相对比较深,尤其经过JS层层封装的函数,我们不知道底层是否使用了这些函数,是否存在变量传入?

这类函数有一个共性,函数本身就是JS函数,但是能够将传入的参数当做JS代码执行。

function updatecontent(url){

setTimeout("showURL('"+url+"')");

}

function showURL(url){

document.getElementById("settimeoutxss").value=url;

}

当$value的值为:hello world\'\);alert\(0\);eval(\' ,XSS攻击成功

c0dc4bbab8e8

当你在οnclick="updatecontent('$value')"处,对$value进行HTML编码后,XSS攻击依旧存在;

Click setTimeOut HTMLEncode

c0dc4bbab8e8

当你在οnclick="updatecontent('$value')"处,对$value进行JavaScript编码后,XSS攻击依旧存在;(有兴趣的可以试一试)

Click setTimeout JavaScriptEncode

c0dc4bbab8e8

如果要想对$Value进行编码防范xss,需要对其进行doublejsencode,一次JavaScript编码是不够,需要2次,才能保证传入setTimeout中的参数url只是个字符串。如果仅仅进行一次javascript编码,能够保证updatecontent函数传入的是字符串,但是setTimeout会将该字符串当做代码执行,如果进行2次JS编码,在setTimeout接收到的参数是一次JS编码的值,只会对其进行一次JS解码,当做字符串处理。

Click setTimeout Double JavaScriptEncode

c0dc4bbab8e8

相关参考:

新式网络浏览器幕后揭秘:

XSS (Cross Site Scripting) Prevention Cheat Sheet:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值