一.HTML的字符集
1.字符集出现的原因
字符集是用来统一传输过程中信息的一致性,就如同,两个来自不同国家的人的对话一样。
一个俄罗斯人和一个中国人,两者都会英语和本国的语言。
中国人在大脑中构思好"你好啊"这句话,然后自己翻译成英语"hello"。
俄罗斯收到"hello",后再在大脑中翻译成俄语中"你好“的意思。这样一次简单的对话,才能成立,否则,只能是鸡同鸭讲。
同理我们在服务器和客户两者之间,也需要统一的"语言",否则也会出现理解不了的情况。
2.字符实体(Character entity)
在编写html中,如果我们要显示一些特殊字符,比如说:">"、"<"等,因为浏览器会将其误认为是标签,进而不能正确的显示
如,我们要在页面中显示"<a"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>是否能正确显示小于号和a标签呢?</p>
<a
</body>
</html>
现在打开火狐
下图是打开后的页面,很明显,未能正确的显示"<a",同时要注意,在查看元素中,浏览器会自动修正一些问题,如自动将a
标签闭合,并添加了</a>标签。
打开源代码,
还是原来的代码。
接下来是chrome浏览器,也没能正确显示
然后是,ie浏览器
此时,就需要字符实体来发挥作用了
只需要用"<"或者"<"或者"<"即可
修改代码为:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<p>是否能正确显示小于号和a标签呢?</p>
<a
<a
<a
</body>
</html>
打开页面
查看源代码
3.字符实体的格式
在html中字符实体的格式有两种:
类型一:
&#entity_number;
其中,entity_number,可以是十进制或者十六进制,如下
<
<
类型二:
&entity_name;
如
<
以上在html中都可以表示小于号。
注意:类型一中的entity_number的数值(十进制)与该字符的ascii值一致。
但是,我们知道ascii使用7个比特来表示的,所以最多只能有128个。但是能够在页面中显示的字符可远远超过128个,所以,还可以用较大的数来描述。
如 "∀",可以用"∂"或者"∂"来表示。
二、JS的编码总结
以下内容应用自《web安全功放:渗透测试指南》
js提供了四种字符编码的策略,如下所示。
- 三位八进制数字,如果个数不够,在前面补0,例如"e"的编码为"\145"
- 两位十六进制数字,如果个数不够,在前面补0,例如"e"的编码为"\x65"
- 四位十六进制数字,如果个数不够,在前面补0,例如"e"的编码为"\u0065"
- 对于一些控制字符,使用特殊的C类型的转义风格(例如\n和\r)
如,<script>eval("alert(1)")</script>,我们可以有一下三种表达:
八进制:<script>eval("\141\154\145\162\164\50\61\51")</script>
16进制:<script>eval("\x61\x6c\x65\x72\x74\x28\x31\x29")</script>
16进制:<script>eval("\u61\u6c\u65\u72\u74\u28\u31\u29")</script>
前面两个都能正常弹出警告框,为什么第三个不行呢?
在firefox中打开改页面,后发现:
SyntaxError: malformed Unicode character escape sequence,意思是unicode中的字符实体顺序出了问题。
查阅资料后发现,原因是这样的
js中可以直接通过eval执行的字符串有八进制和16进制两种编码方式,其中八进制用\56,十六进制用\x5c的格式。
需要注意的是这两种字符表示方式不能够直接给多字节字符编码(如汉字、韩文),如果代码中应用了汉字并且需要进行进制编码,那么只能进行十六进制Unicode编码,其表示形式为:\u4ee3\u7801("代码"二字的十六进制编码)。
所以,上述第三种方法在这里不能正确的执行,但是我们可以换一种其他的表达方式:
<a href="javascript:\u0061\u006c\u0065\u0072\u0074("您好")">test</a>
将其放在html中,执行下
点击test,后弹窗
上述\u0061\u006c\u0065\u0072\u0074,是对"alert"这个字符串进行的js编码,记住在js解析器中,必须是四位16进制,否则不能正确执行。
那现在能不能将<a href="javascript:alert(1) ">中的"alert(1)",进行16进制的编码呢?尝试下
打开页面,点击test3没有任何反应,问题出来了;
看一下,这个解释
https://security.yirendai.com/news/share/26
里面说了,"alert"是一个有效的标识名称,它可以被正常解析。但是像圆括号、双引号、单引号等等这些控制字符,在进行javascript解析的时候仅会被解码位字符串文本或者上面讲的标识符名称,但是在该过程中这些特殊字符已经没有控制字符的作用,所以无法闭合,因此执行失败。
三、URL编码
关于为什么要进行url编码,看看这篇文章?
https://www.cnblogs.com/jerrysion/p/5522673.html
URL编码的格式为:
URL编码通常也被称为百分号编码,是因为它的编码方式非常简单,使用%百分号加上两位的字符(16进制格式)。
这两位字符是依据ascii来决定的,
比如,英文单引号的ascii值为:27(16进制格式)
' 经过URL编码后为,%27