在用于 Cronjobs 的 PHP 脚本中,在运行它们之前将 IP 地址列入白名单的风险是什么

我的服务器上有一些 PHP 脚本,用于定期的 cron 作业(例如,用于每日和谐和更新排行榜)。


为了防止外部人员手动运行这些脚本(http://url/script.php例如通过在浏览器中运行),我包含了以下代码以在运行实际脚本之前检查 IP 地址。其中XX.XX.XX.XX代表我自己网络的IP地址。


    $remote = isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '127.0.0.1';

    $whitelist = array('XX.XX.XX.XX', '127.0.0.1');


    if (!in_array($remote, $whitelist))

    {

        exit;

    } 

所以现在我有以下问题:

  • 这有多安全?

  • 有什么风险?

  • 我怎样才能使它更安全?

  • 还有其他(更好的)解决方案吗?

附言。我之前的问题已关闭,因为有人认为这个问题与PHP IP Address Whitelist with Wildcards重复。但我不是这样的!这个问题是关于在白名单中使用通配符,而这个问题是关于这个解决方案的安全性和风险。


慕村225694
浏览 100回答 2
2回答

不负相思意

所提出的方法并不完全安全。PHP 充当文本预处理器,这意味着在 Web 服务器网关错误的情况下,可以使用 mime 类型的文本/html 发送脚本内容,这存在泄露敏感数据(例如 SQL 数据库密码或(s)ftp 帐户。如果脚本中控制的 IP 地址是共享(或动态传输)地址,则公开放置的管理脚本也存在未经授权执行的风险。Cron 脚本是使用 php-cli 执行的,因此不需要 Web 服务器网关,如果它在公共目录之外,则不需要在脚本中进行 IP 分析。使用 curl 等远程执行可能是将管理脚本放置在 www 服务器公共空间的唯一原因。这通常是一个薄弱的解决方案,因为脚本会使用其他设置执行 php 解释器(而不是 php-cli),通常执行时间非常有限。但是,如果出于某种原因有必要,它应该位于一个单独的目录中,该目录的访问仅限于使用 .htaccess(和/或 .iptables)的特定 IP 地址,并使用 htpasswd(基本身份验证)分配的用户名和密码。理想情况是当www服务器的public目录(以下简称public)只包含静态内容(img,css,js...文件),应用触发器位于父目录。示例结构为:/home/username/domainname/(apps,crons,public,tmp)apps 目录应包含所有应用程序文件和目录。公共目录应该只包含静态内容(为了在某些子目录中排序)和指向应用程序主文件的符号链接,可以使用以下命令获得:ln&nbsp;-s&nbsp;../apps/app.php&nbsp;index.php某些服务器配置不允许使用符号链接。然后你可以使用包含以下内容的 index.php 文件:<?php include('/home/username/domainname/apps/app.php');这个解决方案有点糟糕,因为如果网关出现故障,目录结构就会暴露。但是,敏感数据仍然是安全的,因为 Web 服务器无法显示不存在的文件的内容。假设 php 文件本身位于公共 Web 服务器之外,所提供的 IP 分析可用于显示授权地址的部分内容。但是,如果这些是整个网站,我更愿意使用 iptables 或 .htaccess 来管理对它们的访问。

神不在的星期二

这有多安全?实际上,只要您控制地址(127.0.0.1 可以,XXX.XXX.XXX.XXX 可能不行),它就非常安全。我所说的相当安全的意思是,有人滥用该系统的可能性很小,滥用 Web 应用程序其余部分的可能性也不大。有什么风险?有人可能会从外部调用您的脚本,如果他们有办法以某种方式假设 IP 地址 XXX.XXX.XXX.XXX,或者欺骗 systemm 相信他们有。我怎样才能使它更安全?您可以在原始调用中包含一个秘密,并根据同一秘密的哈希值对其进行检查。即使有人能读懂剧本,秘密也不会泄露。if (!array_key_exists('key', $_GET)) {&nbsp; &nbsp; die('Access denied');}if (sha1($_GET['key']) !== '713dca7cf928f23a2347cae828d98879629e1e80') {&nbsp; &nbsp; die('Access denied');}也可以将脚本放在web根目录之外require,通过语句调用。这样,要么 PHP 子系统工作,脚本无法读取,要么不工作,显示的只是一个无法访问的目录的名称。您甚至可以合并这两种方法:if (sha1($_GET['key']) !== '713dca7cf928f23a2347cae828d98879629e1e80') {&nbsp; &nbsp; die('Access denied');}$realScript = $_GET['key'];require $realScript;现在,唯一可以包含的脚本是名称具有特定 SHA1 哈希的脚本,没有其他脚本(冲突的风险实际上可以忽略不计:您需要与有效文件名发生冲突,以及创建此类文件名的方法). 所以你知道脚本是有效的,但除非在调用中提供名称,否则整个构造将无法工作,它甚至不会告诉攻击者原因。curl http://yoursite.internal.address/cron/cron.php?key=../scripts7ab9ceef/mycron.php还有其他(更好的)解决方案吗?是和不是。使用命令行界面调用脚本同样安全,并且不需要工作的网络服务器。如果需要,它还允许以不同的用户身份运行。另一方面,它需要安装一个命令行界面,这可能会产生其他安全问题,即使使用相同的用户和主目录,这两个界面的行为仍然可能有微妙的不同(或不那么微妙:你可能有一个 PHP7.3 Web 模块和一个 PHP5.2 CLI 安装,反之亦然,这将使具有短数组语法(或具有类似结构if(empty(some_function($_GET['x'])))的脚本甚至无法加载到一个或另一个界面中。总而言之,对curlor 的crontab 调用lynx可能更易于维护和使用,即使它无疑效率较低。
打开App,查看更多内容
随时随地看视频慕课网APP