在 HTML 中,有一些特殊字符不可直接使用,需要使用转义字符或实体编码来表示。这是为了避免这些字符与 HTML 标签和语法产生冲突。同时,也是为了防范前端XSS。
例如,有些特殊字符(如 <
和 >
)作为HTML标签的一部分,要是没有被特殊处理可能被恶意XSS。
HTML的特殊字符转义及编码在防范跨站脚本攻击(Cross-Site Scripting, XSS)方面起到关键作用。XSS是一种常见的安全漏洞,攻击者通过在受信任网站上插入恶意脚本,使其在用户浏览器中执行。
以下是四个例子来说明HTML的特殊字符转义及编码的作用:
(1)阻止脚本注入:
假设一个博客网站允许用户发表评论,并将评论内容直接显示在页面上。如果没有进行转义或编码处理,攻击者可以在评论中插入恶意脚本。例如:
用户评论:
如果评论内容未经过转义或编码,这段恶意脚本将在其他用户浏览该页面时被执行。
接下来以XSS-Labs靶场为例,成功执行XSS时将弹窗“完成的不错”
由于后端无任何过滤及转义处理,可以看到,XSS语句执行成功:
然而,通过将特殊字符转义为实体编码,将评论内容显示为普通文本,如下所示:
<script>alert('XSS Attack');</script>
这样,评论内容不再被解释为可执行的脚本,保护了页面和用户的安全。
(2)防止HTML标签和属性的滥用:
假设一个社交媒体网站允许用户在个人简介中添加自我介绍。如果用户输入的内容未经过转义或编码处理,并且在个人简介页面上直接显示,那么攻击者可以在自我介绍中插入恶意HTML标签或属性。例如:
用户输入:
如果该内容未经过任何处理,则图像标签会被解释并执行其中的JavaScript代码。
举个例子:
通过将特殊字符转义为实体编码,将自我介绍内容显示为普通文本,如下所示:
<img src="javascript:alert('XSS Attack');" />
这样,HTML标签和属性不再被解析为可执行的代码,保护了页面和用户的安全。
同时,我们可以看到,在一些程序中,输入XSS语句之后并不会被转义,也不会被执行:
这是运用了更高级XSS防护技术的缘故。
(3)防止URL注入:
假设一个电子商务网站允许用户在评论中包含链接,并直接将这些链接显示在页面上。如果URL未经过适当的编码处理,攻击者可以在URL中注入恶意脚本或其他恶意内容。例如:
用户评论:https://www.example.com?param=
如果该评论未经过任何处理,链接将会被解释并执行其中的JavaScript代码。
通过对URL进行编码,如下所示:
https://www.example.com?param=%3Cscript%3Ealert('XSS%20Attack')%3C/script%3E
这样,URL中的特殊字符被转义为实体编码,防止了恶意代码的执行。
(4)XSS过滤器的辅助作用:
许多现代浏览器和Web应用程序框架提供内置的XSS过滤器,其中一部分依赖于合适的HTML转义和编码。
例如,当浏览器检测到页面中的特殊字符被正确转义或编码时,它们会将其视为纯文本,不会将其解析为HTML标签或脚本。这有助于识别和阻止潜在的XSS攻击。
下面列举两个常见的浏览器XSS过滤器:
1.Chrome浏览器:
2.Firefox浏览器:
然而,需要注意的是,只依赖字符转义和编码并不能完全解决XSS问题。其他安全措施如输入验证、输出过滤、域间隔离等也都至关重要。
进行特殊字符转义和编码可以使用不同的方法和工具,具体取决于你使用的编程语言或开发框架。
下面是一些常见的方式:
(1)使用内置函数或方法:
大多数编程语言和框架提供了内置的函数或方法来进行字符转义和编码。例如:
encodeURIComponent()
或encodeURI()
来对URL进行编码,使用innerHTML
或innerText
属性来进行HTML转义。htmlspecialchars()
或htmlentities()
来进行HTML转义。URLEncoder.encode()
来对URL进行编码,使用StringEscapeUtils.escapeHtml()
来进行HTML转义。举个使用内置函数或方法的例子(JavaScript):
// URL编码
let url = 'https://www.example.com/?param=' + encodeURIComponent('');
console.log(url);
// 输出:https://www.example.com/?param=%3Cscript%3Ealert(%22XSS%20Attack%22);%3C/script%3E
// HTML转义
let userInput = '';
let escapedHtml = document.createElement('div');
escapedHtml.textContent = userInput;
console.log(escapedHtml.innerHTML);
// 输出:<script>alert("XSS Attack");</script>
在上述代码中,encodeURIComponent()
用于对URL参数进行编码,将特殊字符转换为相应的实体编码。
对于HTML转义,使用textContent
属性创建一个新的DOM元素,并将用户输入设置为其文本内容,然后通过访问innerHTML
属性获取HTML转义后的输出。
(2)使用专门的编码库:
有一些专门用于字符转义和编码的开源库,可以提供更强大和全面的功能。例如:
举个使用专门的编码库的例子(Java):
import org.owasp.encoder.Encode;
// URL编码
String url = "https://www.example.com/?param=" + Encode.forUriComponent("");
System.out.println(url);
// 输出:https://www.example.com/?param=%3Cscript%3Ealert(%22XSS%20Attack%22);%3C/script%3E
// HTML转义
String userInput = "";
String escapedHtml = Encode.forHtml(userInput);
System.out.println(escapedHtml);
// 输出:<script>alert("XSS Attack");</script>
在Java代码中,使用OWASP Java Encoder库来进行URL编码和HTML转义。Encode.forUriComponent()
用于对URL参数进行编码,而Encode.forHtml()
用于进行HTML转义。
(3)手动实现转义规则:
可以创建自定义的转义表或函数来执行特殊字符的转义。这需要仔细研究和了解特殊字符的转义规则,并编写相应的代码来替换字符。
转义时应考虑多重编码:当字符传输经过多个层级或环节时,确保在每个层级或环节上都进行了正确的编码和转义处理。
1.小于号 <
:
<
<
2.大于号 >
:
>
>
3.和符号 &
:
&
&
4.双引号 "
:
"
"
5.单引号 '
:
'
'
6.版权符号 ©
:
©
©
7.注册商标符号 ®
:
®
®
8.省略号 …
:
…
…
9.非断空格(不换行空格):
10.破折号 –
:
- 转义形式:–
- 实体编码:–
在 HTML 中,使用转义字符或实体编码确保这些字符正确地显示而不会被解析为 HTML 标签或语法。
以上为HTML的特殊字符转义及编码详解,具体分析了前端XSS危害、转义的必要性、如何进行字符转义及编码、常见的字符转义及编码等知识点,读者可躬身实践。
我是秋说,我们下次见。