php生成随机数-PHP 安全问题入门:10 个常见安全问题 + 示例

2023-08-24 0 5,399 百度已收录

与其他几种语言相比,PHP在构建网站方面具有更大的优势,即使是菜鸟也可以轻松构建网站。 但这些优点也容易产生一些负面影响,因为很多PHP教程并不涉及安全知识。

SF为您推荐的这篇文章虽然不一定能阻止您的网站出现安全问题,但也包含了各种不同的安全威胁和应对策略。

快来看看吧!

出于演示目的,代码可能并不完美。 在日常的开发过程中,框架和各种库中都会包含大量的代码。 作为后台开发,除了精通基础的CURD之外,还需要知道如何保护自己的数据。

1. SQL注入

我打赌一袋薯片,你听到了。 SQL 注入是网站面临的最大威胁之一。 如果你的数据库被别人的SQL注入攻击,别人就可以转移你的数据库,这可能会造成更严重的后果。

网站要从数据库获取动态数据,必须执行SQL语句,例如如下:

<?php
$username = $_GET['username'];$query = "SELECT * FROM users WHERE username = '$username'";

攻击者控制通过 GET 和 POST 发送的查询(或其他一些查询,例如 UA)。 一般来说,要查询名为“peter”的用户,形成如下SQL语句:

SELECT * FROM users WHERE username = 'peter'

然而,攻击者发送了特定的用户名参数,例如:' OR '1'='1,这会导致 SQL 语句如下所示:

SELECT * FROM users WHERE username = 'peter' OR '1' = '1'

这样他就可以不用密码导入你整个用户表的数据了。

那么,我们该如何避免此类事故的发生呢? 主流的解决方案有两种。 转义用户输入的数据或使用封装的单词。 转义的方式是封装一个函数,对用户提交的数据进行过滤,去除有害标签。 然而,我不太推荐这种技术,因为很容易忘记在任何地方都这样做。

接下来介绍一下如何使用PDO执行封装的语句(mysqli也是一样):

$username = $_GET['username'];$query = $pdo->prepare('SELECT * FROM users WHERE username = :username');$query->execute(['username' => $username]);$data = $query->fetch();

动态数据的每个部分都带有前缀: 。 然后将所有参数作为形式参数传递给执行函数,看起来 PDO 为您通配了错误数据。

几乎所有数据库驱动程序都支持封装语句,没有理由不使用它们! 养成使用它们的习惯,这样以后就不会忘记它们。

您还可以参考 phpdelusions 中有关动态重构 SQL 查询时处理安全问题的文章。 关联:

2.跨站脚本攻击

XSS也称为CSS(Cross Site Script),跨站脚本攻击。 它是指恶意攻击者在网页中插入恶意的html代码。 当用户浏览页面时,嵌入Web中的html代码就会被执行,从而达到恶意攻击用户的特殊目的。

这是搜索页面的反例:

<body><?php$searchQuery = $_GET['q'];/* some search magic here */?><h1>You searched for: <?php echo $searchQuery; ?></h1><p>We found: Absolutely nothing because this is a demo</p></body>

由于我们直接复制用户的内容,没有经过任何过滤,非法用户可以拼接URL:

search.php?q=%3Cscript%3Ealert(1)%3B%3C%2Fscript%3E

PHP渲染的内容如下,可以看到直接执行了Javascript代码:

You searched for: alert(1);

We found: Absolutely nothing because this is a demo

问:执行 JS 代码有什么大不了的?

JavaScript 可以:

问:如何预防这个问题?

好消息是,如今更高级的浏览器已经具有一些基本的 XSS 防护功能,但请不要依赖于此。

正确的做法是坚决不相信用户的任何输入,并过滤掉输入中的所有特殊字符。 这样就可以消灭大部分XSS攻击:

<?php
$searchQuery = htmlentities($searchQuery, ENT_QUOTES);

或者可以使用模板引擎Twig,一般模板引擎默认会在输出中添加htmlentities保护。

如果保留了用户的输入内容,那么还应该高度关注输出。 在下面的例子中,我们允许用户填写自己的博客链接:

<body>  <a href="">Visit Users homepage</a></body>

上面的代码乍一看可能没有错,但假设用户填写了以下内容:

#" onclick="alert(1)

将呈现为:

Visit Users homepage

永远、永远不要相信用户输入的数据,或者,总是假设用户的内容是令人反感的,要有正确的态度,然后谨慎处理每一个用户的输入和输出。

控制 XSS 攻击的另一种方法是提供 CSP 元标记或焦距信息。

对于其他类型的cookie,如果不需要JS读取,请设置“HTTP ONLY”。 此设置可以防止 JavaScript 读取 PHP 端的 cookie。

3.XSRF/CSRF

CSRF是跨站请求伪造的缩写。 是攻击者利用一些技术手段,误导用户访问原来经过认证的网站并执行某些操作。

虽然这里显示的示例是 GET 请求,但它比 POST 更容易理解,并且它不是一种保护手段。 它们都不是私人 cookie 或多步骤形式。

假设您有一个允许用户删除帐户的页面,如下所示:

<?php//delete-account.php
$confirm = $_GET['confirm'];
if($confirm === 'yes') { //goodbye}

攻击者可以在自己的站点上创建一个表单来触发此 URL(这同样适用于 POST 表单),或者将 URL 作为图像加载以诱使用户单击:

<img src="https://example.com/delete-account.php?confirm=yes" />

一旦用户触发,就会执行删除账户的命令,眨眼间你的账户就会消失。

防御此类攻击比防御 XSS 和 SQL 注入稍微复杂一些。

最常见的防御方法是生成CSRF令牌加密安全字符串php生成随机数,一般称为Token,并将Token存储在Cookie或Session中。

每次在网页上构建表单时,将Token令牌放入表单中的隐藏数组中。 表单请求服务器后,会与用户的Cookie或Session中的Token令牌进行比较,验证成功才批准。

由于攻击者不知道Token令牌的内容(每种形式的Token令牌都是随机的),因此很难冒充用户。

<?php /* 你嵌入表单的页面 */ ?>
<form action="/delete-account.php" method="post"> <input type="hidden" name="csrf" value=""> <input type="hidden" name="confirm" value="yes" /> <input type="submit" value="Delete my account" /></form>##
<?php//delete-account.php
$confirm = $_POST['confirm'];$csrf = $_POST['csrf'];$knownGoodToken = $_SESSION['csrf'];
if($csrf !== $knownGoodToken) { die('Invalid request');}
if($confirm === 'yes') { //goodbye}

请注意,这是一个非常简单的示例,您可以添加更多代码。 如果您使用的是 Symfony 等 PHP 框架,则有内置的 CSRF 令牌功能。

4.LFI

LFI(本地文件包含)是一个允许未经身份验证的用户从 C 盘读取文件的漏洞。

我时不时地会遇到编程不良的路由代码示例,这些代码示例无法验证和过滤用户输入。 我们以以下文件为例,并加载它将通过 GET 请求呈现的模板文件。

<body><?php  $page = $_GET['page'];  if(!$page) {    $page = 'main.php';  }  include($page);?></body>

由于 Include 可以加载任何文件,而不仅仅是 PHP,因此攻击者可以将系统上的任何文件作为包含目标传递。

index.php?page=../../etc/passwd

这将导致 /etc/passwd 文件被读取并显示在浏览器上。

为了防御这种攻击,您必须仔细考虑允许的用户输入类型,并删除潜在有害的字符,例如“。” “/”“”中输入字符。

如果你真的想使用这样的路由系统(我不建议以任何形式),你可以手动附加 PHP 扩展,删除任何不是 [a-zA-Z0-9-_] 的字符,并从专用模板文件夹中指定,以便不包含任何非模板文件。

我在不同的开发文档中多次看到导致此类漏洞的PHP代码。 从一开始就有清晰的设计思路,允许需要包含的文件类型,删除多余的内容。 您还可以构造要读取的文件的绝对路径,并验证该文件是否存在作为保护,而不是从任何位置读取。

5. 密码散列不足

大多数Web应用程序都需要保存用户身份验证信息。 如果密码散列做得足够好,它可以在您的网站受到威胁时保护用户的密码不被非法读取。

首先,您最不应该做的是以纯文本形式存储用户密码。 事实上,大多数用户在多个网站上使用相同的密码。 当您的网站被盗用时,意味着其他网站上的用户帐户也被盗用。

其次,您不应该使用简单的散列算法,事实上,任何未专门针对密码散列优化的算法都不应该使用。 MD5 或 SHA 等哈希算法的设计速度极快。 这不是你所需要的,密码哈希的最终目的是让黑客难以花费无尽的时间和精力来破解密码。

另一个重要的一点是,您应该在密码哈希中添加水(盐)。 添加盐可以避免两个相同的密码形成相同的哈希值的问题。

以下以 MD5 为例,因此请不要使用 MD5 来哈希您的密码,MD5 不安全。

如果我们的用户user1和user315都有相同的密码ilovecats123,这个密码实际上看起来像是一个由字母和数字组成的强密码,但在数据库中,两个用户的密码哈希数据将是相同的:5e2b4d823db9d044ecd5e084b6d33ea5。

如果黑客攻陷您的网站并获取此哈希值,他将不需要暴力破解用户 user315 的密码。 我们想让他花费尽可能多的精力来破解你的密码,所以我们给数据加水:

<?php//warning: !!这是一个很不安全的密码哈希例子,请不要使用!!
$password = 'cat123';$salt = random_bytes(20);
$hash = md5($password . $salt);

最后,在保存唯一密码哈希数据时,不要忘记也保存 $salt,否则您将难以验证用户身份。

目前,最好的密码哈希选项是bcrypt,这是一种专门为哈希密码而设计的哈希算法,并且这种哈希算法还允许您配置一些参数以增加破解难度。

新版本的PHP还附带了安全密码哈希函数password_hash,其中已经包含了米醋处理。 对应的密码验证函数是password_verify,用来衡量密码是否正确。 password_verify还可以有效避免定时攻击。

以下是使用示例:

<?php
//user signup$password = $_POST['password'];$hashedPassword = password_hash($password, PASSWORD_DEFAULT);
//login$password = $_POST['password'];$hash = '1234'; //load this value from your db
if(password_verify($password, $hash)) { echo 'Password is valid!';} else { echo 'Invalid password.';}

澄清一点:密码散列不是密码加密。 哈希是将目标文本转换为相同宽度的不可逆哈希字符串(或消息摘要),加密是将目标文本转换为不同宽度的可逆密文。 显然它们之间最大的区别是可逆性。 在存储密码时,我们想要的是对这些不可逆的属性进行哈希处理。

6.中间人攻击

MITM(中间人)攻击不是针对服务器,而是针对用户。 攻击者充当中间人,误导服务器认为他是用户php生成随机数,欺骗用户认为他是服务器,从而拦截用户与网站之间的流量,并注入恶意内容或以其他方式读取隐私信息,通常发生在公共场合WiFi 网络,但也可能发生在其他流量经过的地方,例如 ISP 运营商。

防止这种情况的唯一方法是使用 HTTPS,它会加密您的连接并使其难以读取或篡改流量。 您可以从 Let's Encrypt 获得免费的 SSL 证书,或者从其他提供商处订购它们,我不会详细介绍如何正确配置您的 Web 服务器,因为这与应用程序安全性无关,并且在很大程度上取决于您的设置。

您还可以采取一些措施使 HTTPS 更加安全。 将 Strict-Transport-Security 徽标标头添加到 WEB 服务器配置中。 此返回信息告诉浏览器您的网站仍然通过 HTTPS 访问。 如果不通过HTTPS,则会返回错误报告,提示浏览器不应显示该页面。

然而,这里有一个明显的问题。 如果浏览器以前从未访问过您的网站,则很难知道您使用了此标识标头。 这时候就需要用到Hstspreload了。

您可以在这里注册您的网站:

您在此处提交的所有网站都将被标记为仅 HTTPS,并硬编码到 Google Chrome、FireFox、Opera、Safari、IE11 和 Edge 的源代码中。

您还可以在您的DNS配置中添加一条证书颁发机构授权(CAA)记录,只允许一个证书颁发机构(例如Let's crypt)为您颁发域名证书,这进一步增强了用户的安全性。

7.命令注入

这可能是服务器遇到过的最严重的攻击。 命令注入的目的是误导服务器执行任意shell命令。

如果使用shell_exec或exec函数。 让我们做一个小的反例,允许用户简单地从服务器 ping 不同的主机。

<?php
$targetIp = $_GET['ip'];$output = shell_exec("ping -c 5 $targetIp");

输出将包括 ping 目标主机 5 次。 除非使用 sh 命令执行 shell 脚本,否则攻击者就可以为所欲为。

ping.php?ip=8.8.8.8;ls -l /etc

shell 将执行攻击者连接的 ping 和第二个命令,这看起来非常危险。

感谢 PHP 提供了通配符 Shell 参数的函数。

escapeshellarg 通配符用户的输入并将其包装到单个冒号中。

<?php
$targetIp = escapeshellarg($_GET['ip']);$output = shell_exec("ping -c 5 $targetIp");

现在你的命令应该相当安全了,就个人而言,我一直避免使用 PHP 调用外部命令,但这完全取决于你的偏好。

另外,我建议更进一步,按照您期望的方式验证用户输入。

8.XXE

XXE(XML外部实体)是一种使用不正确配置的XML解析器来解析外部XML的应用程序,导致本地文件包含攻击甚至远程代码执行。

XML 的一个鲜为人知的功能是它允许文档作者将远程和本地文件作为实体包含在其 XML 文档中。

 <!DOCTYPE foo [      ]>   <foo>&passwd;</foo>

就像这样,/etc/passwd 文件的内容被轮询到 XML 文件中。

如果您使用 libxml,您可以调用 libxml_disable_entity_loader 来保护自己免受此攻击。 使用前请仔细检查XML库的默认配置,以确保配置成功。

9. 生产中不正确的错误报告会暴露敏感数据

[](,可能会由于不正确的错误报告而泄露生产中的文件夹结构、数据库结构、连接信息和用户信息等敏感信息。

您不希望用户听到这个,是吗?

一般来说,根据您使用的框架或CMS,配置方法会有所不同。 通常框架具有允许您将站点修改为某种生产环境的设置。 这会将所有用户可见的错误消息重定向到日志文件,向用户显示非描述性 500 错误,并允许您通过代码检测错误。

但你应该根据你的PHP环境来设置:error_reporting和display_errors。

10. 登录限制

像登录这样的敏感表单应该有严格的速率限制,以避免暴力攻击。 存储过去几分钟内每个用户登录尝试失败的次数,如果该比率超过您定义的阈值,则拒绝进一步的登录尝试,直到冷却期到期。 用户还可以通过电子邮件收到登录失败的通知,以便他们知道自己的帐户已成为目标。

其他一些补充提示

我不是安全专家,所以恐怕很难涵盖所有内容。 尽管编写安全软件可能是一个乏味的过程,但通过遵循一些基本规则,可以编写相当安全的应用程序。 其实很多框架在这方面也为我们做了很多工作。

安全问题不像拼写错误等可以在问题发生之前在开发阶段进行跟踪。 因此,在编写代码的过程中,要时刻有规避安全风险的意识。 如果您因为业务需求的压力而不得不暂时忽略一些安全工作,我想您有必要提前告知您这样做可能存在的风险。

如果您受益于本文,请分享给您的朋友,让我们共同建设安全网站。

相关好课程推荐

扫码学习

>>>>

讲师周孟康

高级研发工程师,PHP技术专家,《深入PHP内核》作者之一,《PHP进阶之路》系列四星好评讲师。

>>>>

课程介绍

我看过很多架构分享,99%都在分享他们搭建的系统有多么庞大,提供了多么惊人的性能,但他们从来没有提到如何实现。

>>>>课程亮点

>>>>主题概要

后端架构例程

完善的监控系统

流量估计和压力测量

日志收集与分析

分布式计划任务

性能优化的想法

服务修复的实现

轻量级发布系统

>>>>

学生评价

arvin 阿亮 2 月 13 日

真的很需要! 之前也看过大佬的深入php内核,收获颇多!

泰洛弗 十一月 12, 2018

服务监管这块给我带来了一个新的概念,让我在分布式处理方面学到了很多东西。

亿级光伏架构讲解得很详细,让人一目了然。

恩达 2018 年 4 月 16 日

非常有用的讲座,其中服务治理框架派上了用场。 康深真的很努力啊~

蒸不是蒸·2018-03-05

厉害了,- -,作为一个PHP新手,基础知识还勉强能看懂,但是看了几遍回放,完全能理解孟康老师说的了(≧▽≦),回味无穷。 几次都会有新的收获。

炸鱼·2018年3月5日

给孟康点个赞,这个课程很适合进阶观看,干货满满

我第一次听的时候的体会是“这不就是我一开始遇到的问题和案例吗”,所以仔细听可以收获很多,关键是要吸收上面的思想。

另外,在老铁系列中,我觉得每一大章都可以说是一个技术阶段。 做笔记并拓展,你会发现你会收获更多。

子晨 2017年10月25日

老师讲课很好,提到了很多点,一些不清楚的东西一下子就明白了,非常有用!

web_zheng 2017 年 10 月 24 日

今年秋天我去了phpcon,会议上很多嘉宾都在谈论“微服务”、“服务整改”、“跨语言调用”等与服务相关的分享。 因为我公司的业务还没有达到需要进行服务整改的规模,所以我从来没有接触过,也不是很了解。 这个问题一直困扰着我。 我找了一些资料看了一下,但不是很清楚。 我偶然听到了有关段错误的课程。 上周日听了之后,再加上孟康博客上写的信息代码,就研究了一下。 这两天,我突然恍然大悟。 心里的苦恼解除了,心情舒畅极了!

展翅飞翔 · 2017 年 7 月 31 日

突然我明白了,驻留在视频内存中的服务器就是这个意思。 我以前听说过它,但从未接触过它。 还学会了idea中如何运行java T_T。 性价比很高,真的! ! ! 希望老大以后能讲比这更深入的服务器的东西。

tvelve码首页·2017年7月19日

老师接地气地讲了一些高层次的概念,说起话来如沐春风。

欢迎关注SegmentFault微信公众号:)

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

悟空资源网 php php生成随机数-PHP 安全问题入门:10 个常见安全问题 + 示例 https://www.wkzy.net/game/149505.html

常见问题

相关文章

官方客服团队

为您解决烦忧 - 24小时在线 专业服务