1.7.3 数据与代码分离原则
另一个重要的安全原则是数据与代码分离原则。这一原则广泛适用于各种由于"注入"而引发安全问题的场景。
实际上,缓冲区溢出,也可以认为是程序违背了这一原则的后果--程序在栈或者堆中,将用户数据当做代码执行,混淆了代码与数据的边界,从而导致安全问题的发生。
在Web安全中,由"注入"引起的问题比比皆是,如XSS、SQL Injection、CRLF Injection、X-Path Injection等。此类问题均可以根据"数据与代码分离原则"设计出真正安全的解决方案,因为这个原则抓住了漏洞形成的本质原因。
以XSS为例,它产生的原因是HTML Injection 或 JavaScript Injection,如果一个页面的代码如下:
- <html>
- <head>test</head>
- <body>
- $var
- </body>
- </html>
其中 $var 是用户能够控制的变量,那么对于这段代码来说:
- <html>
- <head>test</head>
- <body>
- </body>
- </html>
就是程序的代码执行段。
而
- $var
就是程序的用户数据片段。
如果把用户数据片段 $var 当成代码片段来解释、执行,就会引发安全问题。
比如,当$var的值是:
- <script src=http://evil></script>
时,用户数据就被注入到代码片段中。解析这段脚本并执行的过程,是由浏览器来完成的--浏览器将用户数据里的<script>标签当做代码来解释--这显然不是程序开发者的本意。
根据数据与代码分离原则,在这里应该对用户数据片段 $var 进行安全处理,可以使用过滤、编码等手段,把可能造成代码混淆的用户数据清理掉,具体到这个案例中,就是针对 <、> 等符号做处理。
有的朋友可能会问了:我这里就是要执行一个<script>标签,要弹出一段文字,比如:"你好!",那怎么办呢?
在这种情况下,数据与代码的情况就发生了变化,根据数据与代码分离原则,我们就应该重写代码片段:
- <html>
- <head>test</head>
- <body>
- <script>
- alert("$var1");
- </script>
- </body>
- </html>
在这种情况下,<script>标签也变成了代码片段的一部分,用户数据只有 $var1 能够控制,从而杜绝了安全问题的发生。