file_put_contents之后的标题位置


Header Location after file_put_contents

我尝试从文件中读取一个常量,并能够根据需要更改这个常量。

因此,当需要写入该常量时(在本例中通过GET),就在我想重新加载页面以获得正确的值之后。

但是在重新加载之后,即使我的文件包含了新值,似乎常量仍然定义为旧值。

如果我在标题(Location)前放一个sleep,一切都可以正常工作。有没有不睡觉的解决办法,为什么?

下面是示例文件:

<?php
  include_once 'toto.php';
  if (isset($_GET['test'])) {
    $file = "<?php const TOTO = '$_GET[test]'; ?>";
    file_put_contents('toto.php', $file);
    // sleep(3);
    header('Location: index.php');
    exit;
  }
  echo TOTO;
?>

我尝试将file_put_contents替换为fopen+fwrite+fflush+fclose,但没有成功。

以上代码对我来说运行良好。

你的index.php包含什么?

概念打破

常量的概念是在整个应用程序中它的值不会改变。你违背了常量的原则。

安全

另外,由于常量是通过用户输入定义的,并写入到文件中,因此我们可以很容易地用任何恶意代码劫持您的服务器。即:

http://localhost/index.php?test=42%27;eval($_GET[%27hack%27]);%3F>

然后我们可以在查询字符串后面添加任何我们想要执行的内容。

http://localhost/index.php?hack=echo%20shell_exec(%27cat%20%2Fetc%2Fpasswd%27)

中提琴,我们有你的/etc/passwd文件。从那里,我们可以拿到你的/etc/shadow文件然后劫持你的整个服务器。我们可以创建更多的后门到您的服务器-几乎做任何到您的服务器通过传递我们的命令hack查询字符串参数。

修复

修改你的脚本,使它不会打破这个概念,或者你没有竞争条件写入新的值到文件和读取,考虑使用cookie或会话(两者都是唯一的客户端;cookie可以被客户端编辑,而会话通常不能(会话ID可以,但是绑定到会话ID的值不能)。

<?php
  session_start();
  include_once 'toto.php'; //or put session_start(); at the top of this file
  if (isset($_GET['test'])) {
     $_SESSION['TOTO'] = $_GET['test']; //Do some sanitation here since it's user input.
     header('Location: index.php');
     exit;
  }

现在要阅读这个,只需使用$_SESSION['TOTO'];

但是,既然你已经提到这应该是一个全局配置(即:贯穿整个应用程序和所有用户),那么使用ini文件或数据库

你可以试着把这段代码-

<?php
include_once 'toto.php';
if (isset($_GET['test'])) {
    $file = "<?php const TOTO = '$_GET[test]'; ?>";
    if (file_put_contents('toto.php', $file)) {
        // sleep(3);
        header('Location: index.php');
        exit;
    }
}
echo TOTO;
?>

在这段代码中,只有当常量被正确写入文件时,头函数才会被调用。

您的问题也可能发生,因为在写toto.php之前页面被重定向。