目录
常见编码
一、ASCII码
二、URL编码
三、Unicode编码
四、HTML实体编码
结合编码理解浏览器解析机制
常见编码
一、ASCII码
ASCII (American Standard Code for Information Interchange,美国信息交换标准代码)
计算机内部,所有信息最终都是一个二进制值。每一个二进制位(bit)有0
和1
两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte)。也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从00000000
到11111111
。
上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。
ASCII码对照 👉 点此进入
二、URL编码
URL:
URL - 统一资源定位器(Uniform Resource Locator)
- Web 浏览器使用 URL 从 Web 服务器请求页面。
- URL 只能使用 ASCII 字符集 通过因特网进行发送。
- 由于 URL 通常包含 ASCII 集之外的字符,因此必须将 URL 转换为有效的 ASCII 格式。
URL编码:
- 将字符转换为可通过因特网传输的格式。
- 使用后跟十六进制数字的 "%" 替代不安全的 ASCII 字符。
- URL 不能包含空格。URL 编码通常使用加号(+)或 %20 替代空格
👉URL编码对照表以及编码解码工具
三、Unicode编码
统一码(Unicode),也叫万国码、单一码,由统一码联盟开发,是计算机科学领域里的一项业界标准,包括字符集、编码方案等。
Unicode 源于一个很简单的想法:将全世界所有的字符包含在一个集合里,计算机只要支持这一个字符集,就能显示所有的字符,再也不会有乱码了。
它从 0 开始,为每个符号指定一个编号,这叫做”码点”(code point)。比如,码点 0 的符号就是 null(表示所有二进制位都是 0)。
👉在线 Unicode 编码转换
四、HTML实体编码
为什么有HTML实体编码
在 HTML 中不能使用小于号(<)和大于号(>),这是因为浏览器会误认为它们是标签。如果希望正确地显示预留字符,我们必须在 HTML 源代码中使用字符实体(character entities)。
- HTML 实体是一段以连字号 (&)开头、以分号 (;)结尾的文本 (字符串),形如 j
- 实体常常用于显示保留字符 (这些字符会被解析为 HTML 代码)和不可见的字符 (如“不换行空格”)
- 应用场景:在前端,一般为了避免 XSS 攻击,会将 <> 编码为 < 与 >,这些就是 HTML 实体编码
- 使用须知:在 HTML 转义时,仅仅只需要对六个字符进行编码:&、<、>、"、' 和 `。 我们可以使用 he 库进行编码及转义
👉 在线Html实体编码解码 (config.net.cn)
结合编码理解浏览器解析机制
①<a href="%6a%61%76%61%73%63%72%69%70%74:%61%6c%65%72%74%28%31%29">aaa</a>
分析:a标签中的href属性放的是url,然后现在里面全是url编码,URL模块解码出来就是javascript:alert(1),因为是url解码后才能看到javascript所以最后没识别到这个协议,即alert没被执行
结果:执行失败
②<a href="javascript:%61%6c%65%72%74%28%32%29">
分析:先通过HTML解码得到javascript:%61%6c%65%72%74%28%32%29,再丢给URL模块,URL模块识别到Javascript协议,把:后边的内容解码后丢给js的模块去处理
结果:执行成功
③<a href="javascript%3aalert(3)"></a>
分析:和①类似,URL识别到完整的javascript:后才能识别出这个协议
结果:执行失败
④<div><img src=x οnerrοr=alert(4)></div>
分析:<是< ,>是> HTML实体编码把这俩转化成尖括号后token就被消耗掉了所以并不会进入到标签开始状态,自然<img>里面的内容也失效了
结果:执行失败
⑤<textarea><script>alert(5)</script></textarea>
分析:这个看起来和④差不多,但其实<textarea>与<title>都是RCDATA元素,即在这俩标签里面,不可能有别的标签存在,所以最后也会把<>变成实体编码
结果:执行失败
⑥<textarea><script>alert(6)</script></textarea>
分析:这里与⑤做对照,就算<>不用html实体编码,最后也不会识别到<script>标签
结果:执行失败
⑦<button οnclick="confirm('7');">Button</button>
分析:html实体解码后得到'7'然后有js的函数confirm就会丢给js模块去处理
结果:执行成功
⑧<button οnclick="confirm('8\u0027);">Button</button>
分析:confirm函数里面用了unicode编码,没别的编码了,所以会解析过后会丢给js模块去处理,但是unicode只能用来表示字符串和标识符,所以最后右边的'没有解析成功
结果:执行失败
⑨<script>alert(9);</script>
分析:html实体解析完后<script>中间的内容是alert(1)乍一看应该能执行,但是<script>是原始文本元素,只能放文本内容,在这里的话里面的东西html不会解析,会直接以文本格式丢给js模块去处理,js不认识html实体编码
结果:执行失败
⑩<script>\u0061\u006c\u0065\u0072\u0074(10);</script>
分析:<script>原始文本元素,丢给js模块去处理,解析出来的alert函数是个标识符,直接就执行了
结果:执行成功
⑪<script>\u0061\u006c\u0065\u0072\u0074\u0028\u0031\u0031\u0029</script>
分析:类似于⑧,虽然看起来能解析出个alert(10)但是()不在标识符范围内,js解析执行失败
结果:执行失败
⑫<script>\u0061\u006c\u0065\u0072\u0074(\u0031\u0032)</script>
分析:与⑪做比较,js模块解析出来alert(12)看起来没什么问题,但是这里12是两个unicode编码,意思就是字符串,字符串是必须要''才能执行的
结果:执行失败
⑬<script>alert('14\u000a')</script>
分析:\u000a解码后就是换行,解码出来直接执行
结果:执行成功
⑭<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(15)"></a>
分析:先进行html解码得到👇
<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(15)"></a>
再进行URL解码得到👇
javascript:\u0061\u006c\u0065\u0072\u0074(15)
因为被URL模块识别到js协议了,所以丢给js模块解码
javascript:alert(15)
结果:执行成功