查看原文
其他

Web之困笔记

2017-08-21 Styxz 合天智汇

点击蓝字

 

学习干货


前段时间orange的BH2017议题中提到的不同语言和库的url解析对SSRF的影响,让我想起了web之困中曾经讨论过浏览器对url的解析过程也同样是一团乱麻,之前只是快速过了一遍这本书,最近有时间了再重新看一遍。


ff = firefox; ch = chrome; sf = safari


一切从url开始


URL结构:

scheme://login:password@address:ort/path/to/resource?querystring#fragment


协议(scheme)

 : 结尾,规定在 : 之前,只能出现 + - .三个符号,但在实际环境里所有的浏览器都会忽略换行符和空格,IE还会允许所有的不可打印字符,chrome会忽略0x00和NUL。


层级url

含有 // 的url

问题:如果碰到一个非层级的url含有//如何处理?反之亦然

导致各家浏览器的解析不同:

1. http:example.com 在ff,ch,sf里会等同于http://*

2. javascript://example.com/%0Aalert(1) 所有常用浏览器会认为是非层级的javascript伪协议


身份验证

不提供则默认匿名,大多数浏览器对身份验证部分接受所有字符,而sf拒接< > { },ff拒绝换行符


服务器地址

必须提供:不区分大小写的域名、ipv4地址或在[]中的ipv6地址,ff还接受在[]中的IPv4和主机。ip地址可以使用八进制、十进制、十六进制,甚至可以吧其中几个或全部8位元数据拼在一起再转成单个整数的写法:127.0.0.1 -> 0x7f.1


层级的文件路径

/aaa/bbb/ccc.txt 这个格式是直接从UNIX目录语义借用过来的,所以也支持在路径中出现/../和/./


如何解析一个url

1. 提取协议名称:扫描第一个:字符,左边部分为协议名称

2. 去除层级url标记//

3. 获取授权部分信息:扫描/ ? #,首先定位登录信息(@),接着提取目标地址,大多数浏览器接受\作为分隔符的方法

4. 确定路径

5. 提取查询字符串

6. 提取片段id

实际上url的解析非常困难和混乱:


一个例子:http://example.com&xxx=123@167772161/这个url的目标地址实际是10.0.0.1(167772161转化为十六进制为A000001,即10.0.0.1)


又一个例子:http://a.com\@b.cx在ff里,会带往b.cx,而在其他浏览器,\会被认为是分隔符,会带往a.com

IE里一个更抓狂的例子:http://a.com/;.b.cx ie允许;出现在主机名称,其他浏览器会补全为/a.com/;.b.cx


保留字符和百分号编码

url解析的大前提:: / ? # [] @ ! $ & ‘ () * + , ; = 不出现在url里,否则会破坏解析。但是有时需要使用它们,就需要进行url编码,这个编码由浏览器完成,但是还是会出现分歧:


例如http://a@b@c 应该对哪个@进行url编码?ie和sf认为编码后一个,其他的编码前一个。


注意:禁止保留字符以非编码形式出现,但是不禁止非保留字符以url编码形式出现,所有浏览器都不会编码片段id


对非us-ascii文本字符的处理


IDNA标准,2002年被发现漏洞,前段时间无法分辨的钓鱼网站域名也是类似的方法?


常见的url协议及功能


浏览器本身支持的协议


由浏览器内部直接处理 http: https: ftp: file: ff仍然支持gopher: ie仍然支持shttp:


第三方应用和插件支持的协议


根据协议交给外部的应用程序 mialto: news: firefoxurl: (在浏览器里启动ff程序)cf: (在ie里调用chrome) 第三方协议的处理程序往往漏洞百出,尽量少用


未封装的伪协议

javascript: data:


封装过的伪协议

view-source: jar:


相对url的解析


如果url不是由有效协议开始,并且没有冒号或者//,那就是需要被引用的相对url,如果解析这个url的时候没有上下文,就拒绝访问。

相对url的类型:

1. 有协议名称,没有授权信息(http:foo.txt),以url自身为准,出了授权信息以引用页面为准。

2. //a.com: 保持当前页面的协议不变

3. ../1.txt: 拼接在url最右边的/后面

4. ?a=b: 原封不动的加上查询字符串和片段id

5.#url: 同上,不会导致页面重新加载


HTTP协议

HTTP/1.1 要求客户端不仅要接受CRLF和LF两种换行符,还要接受CR字符


对重复头域的解析

没有规定接收第一个或第二个,一半的浏览器接收第一个,而另一半接收第二个,而现在服务端,apche接收第一个host头,IIS不接收多个HOST头的情况


也没有规定两个版本不同(HTTP/1.0 HTTP/1.1)但是一样功能的头域同时出现会怎么样



HTML语言

传统HTML解析不严格,相反XML解析非常严格:所有标签必须严格匹配,命名大小写要一致,要显示明确的闭合


HTML解析器

用XHTML解析器,对格式错误的容忍度极低,而用传统HTML解析器,则会出现许多含混的解析 <img src="xx" title="hello" class=example>


img和src中的空格可以用不太常见的垂直制表符(0x0b)和进纸换页符(0x0c)替代,ff里可以用正斜杠代替,opera里可以用0xa0代替。


ie可以用`代替引号和双引号


ie会识别<img src=1.jpg?value=">123!">中的value为”>123!”


多重标签的交互

<i <b>


大多数浏览器会解析为<i>,但在ff4.0之前会解析为<i><b>


层叠样式表


在HTML里嵌入样式表时,会优先执行对HTML的解析,且HTML的解析是独立于CSS语法规则之外的,所以在CSS中如果包含HTML语法会非常不安全。


CSS的解析在遇到语法错误的时候仍会继续工作


CSS用\后面跟1-6位的十六进制数字来转义,例如e可以编码为\65 \065 \000065,但如果e后面一个字符是有效的十六进制数字的时候会出错,例如ea被编码为\65a,则会按照\65a整个来解析,成为unicode里一个阿拉伯符号。CSS针对这个问题有笨拙的解决方案:转以后加一个空格作为终止符。


浏览器端脚本


JS的解析和执行阶段被严格分开,所以允许在一个script标签内先调用函数再定义函数(只对函数有效而对变量无效)。


执行顺序和错误处理:同一个标签内解析正确后按顺序执行,如执行遇到错误不执行错误后面的语句,标签之间的错误互不干扰。


JS脚本字符编码

  1. 对某些控制字符,可以用c风格的方法:\b \t \v \r \n

  2. 3位数字按8位原字节八进制字符编码的方式,无前缀(\145代表e)

  3. 2位数字,按8位原字节16禁止字符编码,前缀位x(\x65代表e)

  4. 4位数字,按16位原字节的16禁止Unicode数值编码,前缀为u(\u0065代表e)

  5. 反斜杠后面跟非8进制数字,也不是1中的转义字符,按反斜杠后面的字符的字面意义直接处理


浏览器安全部分-内容隔离


DOM的同源策略


协议-域名-端口


document.domainpostMessage()


同源策略与浏览器身份验证信息缺少同步机制 -> csrf等漏洞的产生


XMLHttpRequest的同源策略


CORS:返回的数据包里包含特定响应头的时候,浏览器才能读取响应数据


源的继承

about:blank data: 和 javascript:


同源策略之外的世界

点击劫持

X-Fram-Options: sameorigin


其他的安全边界

直接跳转到 file: 会造成的安全影响 DNS rebinding -> DNS pinning


内容识别机制


本文作者:Styxz

别忘了投稿哟!!!

合天公众号开启原创投稿啦!!!

大家有好的技术原创文章。

欢迎投稿至邮箱:edu@heetian.com

合天会根据文章的时效、新颖、文笔、实用等多方面评判给予100元-500元不等的稿费哟。

有才能的你快来投稿吧!


 

合天网安实验室

网址 : www.hetianlab.com

电话:4006-123-731

长按图片,据说只有颜值高的人才能识别哦→

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存