编程语言安全编程指南
1. Tcl 语言安全编程要点
在使用 Tcl 语言时,有一些安全和风格方面的要点需要注意。首先,对于潜在恶意文本的处理,要确保攻击者无法控制格式文本,并且假定潜在恶意文本会被连接到文本末尾。
在风格上,使用
if
、
while
、
for
、
expr
以及其他使用
expr/eval/subst
解析参数的命令时,始终使用花括号。这样可以避免 Tcl 中常见的意外双重替换(即双重替换)错误。例如,下面的代码是错误的:
while ![eof $file] {
set line [gets $file]
}
这段代码错误的原因是,
"![eof $file]"
文本会在
while
命令首次执行时由 Tcl 解析器进行计算,而不是在每次迭代时重新计算。正确的做法是:
while {![eof $file]} {
set line [gets $file]
}
要注意,条件和要执行的操作都要用花括号括起来。虽然在某些情况下花括号是多余的,但它们不会有坏处,而且如果在需要花括号的地方忘记使用,往往会导致难以发现的细微错误。
2. PHP 语言安全编程
2.1 PHP 旧版本的安全问题
在 PHP 旧版本(4.1.0 及以下)中,存在一个突出的安全问题,即数据加载到命名空间的方式。默认情况下,所有环境变量和通过网络发送给 PHP 的值都会自动加载到与普通变量相同的命名空间(全局变量)中。这使得攻击者可以将任意变量设置为任意值,除非 PHP 程序显式重置这些变量,否则它们的值会一直保留。此外,PHP 在首次请求变量时会自动创建具有默认值的变量,因此 PHP 程序通常不初始化变量。如果忘记设置变量,PHP 默认不会报告,但这只是一个错误报告,无法阻止攻击者利用异常方式造成的问题。
例如,下面的 PHP 程序本意是只允许知道密码的人获取重要信息,但攻击者可以在浏览器中设置
auth
来破坏授权检查:
<?php
if ($pass == "hello")
$auth = 1;
...
if ($auth == 1)
echo "some important information";
?>
2.2 解决方法
可以通过将
register_globals
设置为
off
来禁用这个问题。从 PHP 4.2.0 版本开始,外部变量(来自环境、HTTP 请求、cookie 或 Web 服务器)默认不再注册到全局作用域。PHP 4.1.0 引入了新的超全局数组,如
$_REQUEST
,使得在
register_globals
关闭时开发软件更加简单。
以下是一些使用 PHP 进行安全编程的建议:
-
设置
register_globals
为
off
:使用 PHP 4.2.0 或更高版本。如果假设
register_globals
是关闭的,应该先检查这个设置(如果不是则停止程序)。对于 Apache 服务器,可以在
.htaccess
文件中插入以下代码:
php_flag register_globals Off
php_flag track_vars On
但需要确保 Apache 服务器配置允许覆盖
.htaccess
文件。
-
设置所有变量的值
:如果在运行时
register_globals
可能是开启的,要始终设置用户未提供的值,不依赖 PHP 的默认值,不信任未显式设置的任何变量。最佳做法是在每个 PHP 程序开始时设置所有要使用的变量。
-
设置错误报告级别为
E_ALL
:在测试期间解决报告的所有错误。可以在
php.ini
文件、
.htttpd.conf
文件、
.htaccess
文件或脚本顶部通过
error_reporting
函数设置错误报告级别。建议在
php.ini
文件和脚本顶部都设置:
<?php error_reporting(E_ALL);?>
- 过滤用户信息 :仔细过滤用于创建文件名的用户信息,防止远程文件访问。
-
使用新的文件上传方式
:不使用旧的 PHP 文件上传方式,使用
HTTP_POST_FILES数组和相关函数。 - 合理放置代码 :只将受保护的入口点放在文档树中,将其他代码(大部分代码)放在文档树之外。
- 避免使用会话机制 :会话机制在存储持久数据时存在很多问题,如默认将会话信息存储在临时文件中,容易受到攻击。
- 检查输入并进行类型转换 :对于所有输入,检查其是否符合可接受的模式,然后使用类型转换将非字符串数据转换为应有的类型。例如:
$bar = (double) $bar;
- 小心使用危险函数 :特别注意执行 PHP 代码、命令执行和打开文件的函数。
-
使用
magic_quotes_gpc():在适当的地方使用该函数,消除多种攻击。 -
避免文件上传
:考虑修改
php.ini文件以禁用文件上传(file_uploads = Off)。
3. 密码处理
- 避免编写处理密码的代码 :如果应用程序是本地的,尽量依赖用户的正常登录认证;如果是 CGI 脚本,尽量依赖 Web 服务器提供保护;如果是网络应用程序,尽量避免以明文形式发送密码。
- 考虑使用摘要密码 :摘要密码是基于哈希值的密码,服务器向客户端发送一些数据,客户端将这些数据与用户密码组合并哈希,然后将哈希结果返回给服务器进行验证。摘要密码可以防止被动网络嗅探,但服务器需要保存所有未哈希的密码,容易成为攻击目标。
- 检查用户设置的密码 :如果应用程序允许用户设置密码,要检查密码是否符合要求(如不在字典中、具有一定的最小长度等)。可以使用 PAM 来支持可插拔的密码检查器。
4. Web 认证
- 服务器认证 :Web 服务器通常使用 SSL 或 TLS 和服务器证书向用户进行认证。
- 用户认证的困难 :认证用户相对困难,SSL 和 TLS 支持客户端证书,但实际使用存在很多问题,如浏览器不支持单一用户证书格式、用户安装困难等。
-
常见认证技术
:
- 基本认证 :所有浏览器和服务器都支持,但以未加密形式发送密码,仅适用于不重要的信息。
- 将认证信息存储在 URL 中 :不建议使用,因为 URL 未受保护传输,且信息容易泄露。
- 使用 SSL/TLS 连接 :安全但性能成本高。
- 摘要认证 :可以在不暴露密码的情况下认证用户,但浏览器和服务器的支持不广泛,且 Microsoft 的 Web 客户端和服务器实现不正确。
- 使用 cookie :是目前最常见的 Web 认证技术,但使用不当会产生安全漏洞。一些浏览器可能要求有隐私配置文件。
- 使用 HTML 表单隐藏字段 :可以支持不接受 cookie 的用户,但开发成本较高。
用户认证的流程可以用以下 mermaid 流程图表示:
graph LR
A[开始] --> B{选择认证方式}
B -->|基本认证| C(不安全,适用于不重要信息)
B -->|URL 存储认证信息| D(信息易泄露,不建议)
B -->|SSL/TLS 连接| E(安全但性能成本高)
B -->|摘要认证| F(支持不广泛)
B -->|cookie| G(常见但有安全风险)
B -->|HTML 表单隐藏字段| H(开发成本高)
C --> I[结束]
D --> I
E --> I
F --> I
G --> I
H --> I
5. 客户端认证建议
对于大多数网站,建议采用将客户端认证分为“登录过程”和“后续请求”两部分的方法。在登录过程中,服务器要求用户提供用户名和密码,用户提供后,服务器返回“认证令牌”。在后续请求中,客户端(浏览器)将认证令牌发送给服务器,服务器验证令牌的有效性,如果有效则处理请求。
同时,要注意一些 Web 认证技术存在“会话固定”问题,攻击者可以在用户登录目标服务器之前固定用户的会话 ID,从而无需获取用户的会话 ID。
以下是一个总结表格:
| 语言/主题 | 要点 | 建议 |
| ---- | ---- | ---- |
| Tcl | 避免意外双重替换 | 使用花括号 |
| PHP | 旧版本数据加载问题 | 设置
register_globals
为
off
,设置所有变量,过滤输入等 |
| 密码处理 | 避免明文传输 | 使用摘要密码,检查用户密码 |
| Web 认证 | 多种认证技术 | 选择合适的认证方式,注意会话固定问题 |
编程语言安全编程指南
6. 不同认证技术对比
为了更清晰地了解各种 Web 认证技术的特点,我们可以通过以下表格进行对比:
| 认证技术 | 优点 | 缺点 | 适用场景 |
| ---- | ---- | ---- | ---- |
| 基本认证 | 所有浏览器和服务器都支持 | 以未加密形式发送密码,安全性低 | 不重要信息的访问 |
| URL 存储认证信息 | 实现简单 | 信息易泄露,不安全 | 几乎不适用 |
| SSL/TLS 连接 | 安全性高 | 性能成本高 | 重要信息的传输 |
| 摘要认证 | 不暴露密码 | 浏览器和服务器支持不广泛 | 对安全性有一定要求且网络环境较简单的场景 |
| cookie | 常见且实现相对容易 | 使用不当会产生安全漏洞 | 大多数 Web 应用 |
| HTML 表单隐藏字段 | 支持不接受 cookie 的用户 | 开发成本高 | 有特定用户需求的场景 |
7. 密码处理流程
密码处理在安全编程中至关重要,以下是一个 mermaid 流程图展示密码处理的基本流程:
graph LR
A[开始] --> B{应用类型}
B -->|本地应用| C(依赖正常登录认证)
B -->|CGI 脚本| D(依赖 Web 服务器保护)
B -->|网络应用| E{是否可避免明文传输}
E -->|是| F(使用摘要密码)
E -->|否| G(考虑其他安全措施)
C --> H{用户是否可设置密码}
D --> H
F --> H
G --> H
H -->|是| I(检查密码是否符合要求)
H -->|否| J[结束]
I --> K(使用 PAM 进行密码检查)
K --> J
8. PHP 安全编程的详细操作步骤
8.1 设置
register_globals
为
off
对于 Apache 服务器,具体操作步骤如下:
1. 打开
.htaccess
文件。
2. 在文件中插入以下代码:
php_flag register_globals Off
php_flag track_vars On
-
确保 Apache 服务器配置允许覆盖
.htaccess文件。可以在 Apache 的全局配置文件(通常是/etc/http/conf/http.conf)中设置AllowOverride Options。
8.2 设置错误报告级别为
E_ALL
可以通过以下几种方式设置错误报告级别:
-
全局设置
:在
php.ini
文件中找到
error_reporting
选项,将其值设置为
E_ALL
。
-
单主机设置
:在
.htttpd.conf
文件中添加
php_value error_reporting E_ALL
。
-
多主机设置
:在
.htaccess
文件中添加
php_value error_reporting E_ALL
。
-
脚本顶部设置
:在每个 PHP 脚本的顶部添加以下代码:
<?php error_reporting(E_ALL);?>
8.3 过滤用户信息
当使用用户信息创建文件名时,要仔细过滤,防止远程文件访问。可以使用以下代码示例:
$user_input = $_GET['filename'];
$safe_filename = preg_replace('/[^a-zA-Z0-9_.-]/', '', $user_input);
8.4 使用新的文件上传方式
使用
HTTP_POST_FILES
数组和相关函数来处理文件上传,示例代码如下:
if ($_FILES["file"]["error"] == 0) {
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["file"]["name"]);
move_uploaded_file($_FILES["file"]["tmp_name"], $target_file);
}
9. 总结
在安全编程中,不同的编程语言和应用场景有不同的安全要点和处理方法。对于 Tcl 语言,要注意避免意外双重替换;对于 PHP 语言,要解决旧版本的数据加载问题,采取一系列安全措施。在密码处理方面,要避免明文传输,使用摘要密码并检查用户设置的密码。在 Web 认证中,要根据不同的情况选择合适的认证方式,并注意会话固定等问题。
通过遵循这些安全编程的建议和操作步骤,可以提高程序的安全性,减少安全漏洞的出现。同时,随着技术的不断发展,我们也需要持续关注新的安全问题和解决方案,不断完善我们的编程实践。
超级会员免费看

被折叠的 条评论
为什么被折叠?



