【问题标题】:Make <img> src point to a php page使 <img> src 指向一个 php 页面
【发布时间】:2014-06-23 21:21:34
【问题描述】:

我将所有图像保存在普通用户无法访问的根目录中。我随机生成所有文件名,所以我不希望他们知道文件的路径或名称。目前,我有 img 元素:

<img src="get_image.php?id=1">

我的get_image.php 页面是这样的:

<?php
include_once 'includes/db_connect.php';
include_once 'includes/functions.php';

$uploaddir = '/root/......./uploads/'; //Direct path from root to folder holding files
$id = $_GET['id'];

if(!is_numeric($id)) {
    die("File id must be numeric");
}

// A QUICK QUERY ON A FAKE USER TABLE
$stmt = $mysqli->prepare("SELECT `name`, `mime` FROM `uploads` WHERE `filmId`=?");
$stmt->bind_param("i", $id); 
$stmt->execute();

$stmt->bind_result($name, $mime);

// GOING THROUGH THE DATA
while($stmt->fetch()) {

    header("Content-Type: " . $mime);
    readfile($uploaddir.$name);
}

?>

如果有办法我可以做到这一点?我不想像这样直接调用图像文件src:

<img src="../../../uploads/file.jpg"> <!-- I don't want to do this -->

这样做会让用户(或攻击者)知道我将上传的文件保存在哪里。这些图片是用户上传的,所以如果攻击者上传带有恶意代码的图片(即使我有很多代码检查和验证文件),他们也不知道该文件的保存位置。

另外,我是 Web 开发和保持安全的新手。如果您有任何提示或指针可以添加到我必须使我的网页更安全的内容上,请随意。谢谢!

我正在使用this link 来确保此功能的安全性。

解决方案:

代替:

    header("Content-Type: " . $mime);
    readfile($uploaddir.$name);

我把这个:

    header("Content-Type: " . $mime);
    $contents = file_get_contents($uploaddir . $name);
    echo $contents;

它有效。

【问题讨论】:

  • 为什么暴露文件路径是一个安全问题?
  • @rpax 我猜如果他们能够以某种方式访问​​根目录,他们将确切地去哪里。更不用说我给我的图像随机命名,所以像这样“硬编码”可以帮助他们知道哪个文件是哪个文件。我只是偏执,希望我的网站尽可能安全。
  • 那么有什么办法可以阻止某人尝试get_image?id=1get_image?id=99999999 并抓取您的所有图像呢?您在“安全”方面一无所获。最多你已经阻止他们知道图像的“真实”名称是什么,所以id=1 -> boobies.jpgid=50 -> kittens.jpg
  • @RobAveryIV 您当前的代码有什么问题?见stackoverflow.com/questions/1851849/output-an-image-in-php。除此之外,隐藏图像名称并没有安​​全优势。如果 atacker 设法上传了恶意代码,如果他无法执行,知道它存储在哪里有什么帮助?如果他可以在你的系统上执行代码,他为什么还要费心找出“真实”的图像路径?
  • @webnoob:互联网还有什么用?

标签: php html mysql image


【解决方案1】:

不仅可以做到这一点。您甚至可以将&lt;img&gt; 指向似乎是图像路径的PHP 脚本。例如:

<img src="phpimages/my_image.png" />

这个技巧需要一个 Apache HTTP 服务器(你肯定会使用它)和它的mod_rewrite 插件(你肯定已经安装了)。 您可以在 /phpimages/ 中添加一个 .htaccess 文件,其中包含以下内容:

RewriteRule ^([^\.]+)\.(png|jpg|gif)$   /image.php?file=$1.png [NC,L]

如果您只需要用户 ID,您可以将正则表达式限制为:

RewriteRule ^([0-9]+)\.(png|jpg|gif)$   /image.php?file=$1.png [NC,L]

这个过程进一步解释here

在脚本image.php(在同一目录中)中,您将获得文件名作为字符串,例如:

$filename = $_GET["file"];  //eg.: "file1.jpg"

不要忘记过滤掉../ 黑客攻击。要将文件打印给用户,只要它确实存在,请使用readfile

const REAL_AVATAR_PATH = "../../../uploads/"
if(file_exists(REAL_AVATAR_PATH.$username)) {
     header("Content-Type: image/jpg");  //For simplicity, I have ommited to send different header for different images as "png", "gif" and so on.
     readfile(REAL_AVATAR_PATH.$username);
}
else {
     header("HTTP/1.0 404 Not Found");
     die("Error 404 - sorry");
}

在您的情况下,您可以将路径设置为 /avatars/[number].png(并将所有图像转换为 png)。

【讨论】:

    【解决方案2】:

    代替:

    header("Content-Type: " . $mime);
    readfile($uploaddir.$name);
    

    我把这个:

    header("Content-Type: " . $mime);
    $contents = file_get_contents($uploaddir . $name);
    echo $contents;
    

    它有效。

    【讨论】:

      【解决方案3】:

      我不得不不同意当前的答案。如果您正在查看数据库,那么您可以轻松地执行以下操作:

      <img src="/phpimages.php?id=23" alt="{ALT}" />
      

      phpimages.php 然后将获取 ID 23 并输出文件。您的最终用户将不知道图像的来源;他们甚至可能来自另一台服务器。此选项还允许代码更具可读性,同时仍保持相同的安全性。

      <img src="/phpimages.php?frontImage" alt="{ALT}" />
      

      现在您只需使用下面链接中描述的方法,即可获取第一个 $_GET 关联的密钥。或者你可以把它设为id=frontImage,然后使用$_GET['id']

      Get first key in a (possibly) associative array?

      【讨论】:

      • 这只是基本答案的附加值。真正的答复是,既然您不同意 - 为什么不呢?这有什么问题?
      【解决方案4】:

      在 PHP 文件中,您需要将标题内容类型设置为

       header('Content-Type: image/png');
      

      让浏览器知道 get_image.php 给出了一个图像作为响应

      让你的临时图片的路径存放在$path中

      <?php
      $im = imagecreatefrompng($path);
      
      header('Content-Type: image/png');
      
      imagepng($im);
      imagedestroy($im);
      ?>
      

      【讨论】:

      • 等等,你为什么要读入图像并重新编码?绝对没有理由在这里往返 GD。如果你想通过就使用readfile()
      猜你喜欢
      • 1970-01-01
      • 2013-02-17
      • 1970-01-01
      • 2011-03-04
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-09
      相关资源
      最近更新 更多