如何保护 PHP Web 应用程序并防止攻击?

作为开发人员,您必须知道如何构建安全且防弹的应用程序。您的职责是确保应用程序的安全性并防止攻击。

PHP 和 Web 安全问题清单

确保在将应用程序部署到生产环境时整理好这些项目:

  1. 跨站脚本 (XSS)
  2. 注射
  3. 跨站请求伪造(XSRF/CSRF)
  4. 公共文件
  5. 密码
  6. 上传文件
  7. 会话劫持
  8. 远程文件包含
  9. PHP 配置
  10. 使用 HTTPS
  11. 未列出的东西

跨站脚本 (XSS)

当客户端代码(通常是 JavaScript)被注入 PHP 脚本的输出时,就会发生 XSS 攻击。这可以通过 URL,但也可以通过诸如数据库之类的存储技术进行。

// GET data is sent through URL: http://example.com/search.php?search=<script>alert('test')</script>
$search = $_GET['search'] ?? null;
echo 'Search results for '.$search;

// This can be solved with htmlspecialchars
$search = htmlspecialchars($search, ENT_QUOTES, 'UTF-8');
echo 'Search results for '.$search;
  • ENT_QUOTES用于转义 HTML 实体旁边的单引号和双引号
  • UTF-8 用于 PHP 5.4 之前的环境(现在是默认设置)。在某些浏览器中,某些字符可能会通过htmlspecialchars().

注射

SQL注入

从您的应用程序访问数据库时,SQL 注入攻击可能通过将恶意 SQL 部分注入您现有的 SQL 语句来发生。

目录遍历(路径注入)

目录遍历攻击,也称为../(点、点、斜线)攻击,发生在用户提供文件名作为可以遍历父目录的输入时。数据可以设置为index.php?page=../secret、 或 /var/www/secret,或者更具灾难性的东西:

$page = $_GET['page'] ?? 'home';

require $page;
// or something like this
echo file_get_contents('../pages/'.$page.'.php');

在这种情况下,您必须检查是否有人尝试访问父文件夹或某个远程文件夹:

// Checking if the string contains parent directory
if (strstr($_GET['page'], '../') !== false) {
    throw new \Exception("Directory traversal attempt!");
}

// Checking remote file inclusions
if (strstr($_GET['page'], 'file://') !== false) {
    throw new \Exception("Remote file inclusion attempt!");
}

// Using whitelists of pages that are allowed to be included in the first place
$allowed = ['home', 'blog', 'gallery', 'catalog'];
$page = (in_array($page, $allowed)) ? $page : 'home';
echo file_get_contents('../pages/'.$page.'.php');

命令注入

在处理执行您不信任的功能和数据的命令时要小心。

exec('rm -rf '.$GET['path']);

代码注入

当可以通过该eval() 函数注入恶意代码时,就会发生代码注入,因此请记住在使用数据时始终清理您的数据:

eval('include '.$_GET['path']);

跨站请求伪造(XSRF/CSRF)

跨站点请求伪造、一键式攻击或会话骑行是一种利用,用户可借此在 Web 应用程序上执行不需要的操作。

公共文件

确保将所有应用程序文件、配置文件和 Web 应用程序的类似部分移动到当您访问 Web 应用程序的 URL 时不可公开访问的文件夹中。.yml 您的网络服务器可能无法处理某些类型的文件(例如文件),用户可以在线查看它们。

良好文件夹结构的示例:

app/
  config/
    parameters.yml
  src/
public/
  index.php
  style.css
  javascript.js
  logo.png

将您的 Web 服务器配置为从该public文件夹而不是从您的应用程序根文件夹提供文件。公共文件夹包含前端控制器 ( index.php)。如果 Web 服务器配置错误导致 PHP 文件无法正确提供,源代码index.php将对公众可见。

密码

使用用户密码时,请使用该 password_hash()函数正确地对它们进行哈希处理。

上传文件

当用户可以将文件上传到服务器时,就会发生许多安全漏洞。确保检查与上传文件相关的所有漏洞,并对这些漏洞采取适当的预防措施,例如重命名上传的文件、将它们移动到公共无法访问的文件夹、检查上传的文件类型等。由于这里有很多问题需要检查,更多信息也位于单独的常见问题解答中:

会话劫持

会话劫持是一种攻击者窃取用户会话 ID 的攻击。会话 ID 被发送到$_SESSION 填充相关阵列的服务器。会话劫持可能通过 XSS 攻击或当某人获得对存储会话数据的服务器上的文件夹的访问权限时。

远程文件包含

RFI(远程文件包含)攻击是指攻击者可以包含自定义脚本:

$page = $_GET['page'] ?? 'home'

require $page . '.php';

在上面的代码中,$_GET可以设置一个远程文件http://yourdomain.tld/index.php?page=http://example.com/evilscript

php.ini除非您知道自己在做什么,否则请确保禁用此功能:

; Disable including remote files
allow_url_fopen = off
; Disable opening remote files for include(), require() and include_once() functions.
; If above allow_url_fopen is disabled, allow_url_include is also disabled.
allow_url_include = off

PHP 配置

始终保持已安装的 PHP 版本更新。您可以使用 versionscan检查您的 PHP 版本可能存在的漏洞。更新开源库和应用程序,并保持您的 Web 服务器得到良好维护。

以下是php.ini您应该检查的一些重要设置。您还可以使用iniscan扫描您的 php.ini文件以获得最佳安全实践。

错误报告

在您的生产环境中,您必须始终关闭在屏幕上显示错误。如果您的应用程序中出现错误并且它们对外界可见,那么攻击者可能会获取有价值的数据来攻击您的应用程序。display_errors和文件log_errors中的指令php.ini :

; Disable displaying errors to screen
display_errors = off
; Enable writing errors to server logs
log_errors = on
  • 更多信息参见错误一章。

暴露 PHP 版本

PHP 版本在 HTML 标头中可见。您可能需要考虑通过关闭expose_php指令来隐藏您的 PHP 版本,以防止 Web 服务器发回X-Powered-By标头:

expose_php = off

远程文件

在大多数情况下,禁用对远程文件的访问很重要:

; disabled opening remote files for fopen, fsockopen, file_get_contents and similar functions
allow_url_fopen =  0
; disabled including remote files for require, include ans similar functions
allow_url_include = 0

基于开放的

此设置定义一个或多个目录(包括子目录),PHP 可以在其中读取和写入文件。这包括文件处理(fopenfile_get_contents),也包括文件(includerequire):

open_basedir = "/var/www/test/uploads"

会话设置

  • session.use_cookiessession.use_only_cookies

    PHP 默认配置为将会话数据存储在服务器上,并在客户端(通常称为PHPSESSID)上存储一个跟踪 cookie,该 cookie 具有会话的唯一 ID。

; in most cases you'll want to enable cookies for storing session
session.use_cookies = 1
; disabled changing session id through PHPSESSID parameter (e.g foo.php?PHPSESSID=<session id>)
session.use_only_cookies = 1
session.use_trans_sid = 0
; rejects any session ID from user that doesn't match current one and creates new one
session.use_strict_mode = 1
  • session.cookie_httponly

    如果攻击者设法注入 JavaScript 代码来窃取用户当前的 cookie(document.cookie字符串),那么HttpOnly 您设置的 cookie 将不会显示在列表中。

session.cookie_httponly = 1
  • session.cookie_domain

    这设置了 cookie 应用的域。对于通配符域,您可以使用.example.com,或将其设置为应应用的域。默认情况下,它未启用,因此强烈建议您启用它:

session.cookie_domain = example.com
  • session.cookie_secure

    对于 HTTPS 站点,这仅接受通过 HTTPS 发送的 cookie。如果你还没有使用 HTTPS,你应该考虑一下。

session.cookie_secure = 1

使用 HTTPS

HTTPS 是一种用于通过网络进行安全通信的协议。强烈建议您在所有站点上启用它。在专门的常见问题解答中阅读有关 HTTPS 的更多信息: 如何安装 SSL 证书并启用 HTTPS

接下来是什么?

上面我们介绍了很多安全问题。安全性、攻击和漏洞不断发展。花点时间阅读一些好的资源,以了解有关安全性的更多信息并将此检查清单变成一种习惯:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值