我创建了一个下载脚本,以便隐藏文件位置并强制人们通过我们的网站下载文件。它应该返回一个.jar文件。 当我发布.jar文件下载它将返回腐败! 所以我们将文件扩展名更改为.zip以测试是否可行。现在我可以自己下载,但其他人仍然报告文件损坏......
这是指向实时下载页面的链接:https://www.run2stay.com/?p=download
这里是download.php中使用的代码:
<? session_start();
include_once("inc/conf.php");
if ($stmt = $slc->prepare("SELECT id,
creator,
name,
version,
discription,
changelog,
readme,
file,
datum,
downloads
FROM download ORDER by id desc")) {
$stmt->execute();
$stmt->store_result();
if ($stmt->num_rows == 0) {
echo "<h3>Oops!</h3><p>Seems like there are no downloads yet!</p>";
} else {
$stmt->bind_result($down_id, $creat, $name, $vers, $disc, $change, $read, $file, $dat, $down);
while ($stmt->fetch()) { ?>
<h3 id="<?=$down_id;?>"><?=$name;?> <?=$vers;?> <i>by <?=$creat;?></i></h3>
<?=$dat;?>
<? if (!empty($disc)) { ?>
<h4>Discription:</h4>
<p id="ber"><?=$disc;?></p>
<? } if (!empty($change)) { ?>
<h4>Changelog:</h4>
<p id="ber"><?=$change;?></p>
<? } if (!empty($read)) { ?>
<h4>Readme:</h4>
<p id="ber"><?=$read;?></p>
<? } ?>
<h4>Download:</h4>
<? $_SESSION["dl"] = $_SERVER["HTTP_HOST"]; ?>
<input type="button" value="download" onclick="location.href='?p=dl&get=<?=$file;?>&w=<?=$down_id;?>';"> <?=$down;?> times downloaded.
<hr>
<? } } } ?>
我在dl.php中使用的代码
<?php
include_once("inc/conf.php");
if (!empty($_GET)) {
$file = htmlspecialchars($_GET['get']);
$file = "mods/$file";
$down_id = htmlspecialchars($_GET['w']);
session_start();
if(isset($_SESSION["dl"])) {
$referrer = $_SERVER["HTTP_REFERER"];
$referrer = parse_url($referrer);
if($referrer["host"] != $_SESSION["dl"]) {
echo "<meta http-equiv=refresh content=0;URL=?p=download>";
die();
}
} else {
echo "<meta http-equiv=refresh content=0;URL=?p=download>";
die();
}
unset($_SESSION["dl"]);
if (file_exists($file)) {
header('Content-Description: File Transfer');
header("Expires: fri, 1 Jan 2016 00:00:00 GMT"); // Don't change.
header('Content-Type: application/java-archive');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile("$file");
$qry = "UPDATE download SET downloads=downloads+1 WHERE id=?";
$stmt = $slc->prepare($qry);
$stmt->bind_param('s',$down_id);
$stmt->execute();
$stmt->close();
exit;
} else {
echo "<h3>Oops!</h3><p>Looks like something horrible went wrong!</p>";
}
}
?>
答案 0 :(得分:1)
下载文档并使用文本编辑器(如NotePad ++)打开文档,看起来您首先输出整个HTML文档标题(直到您的网站的导航菜单和section
元素) - 然后才会出现二进制数据,看起来可能是zip-ped数据。
我假设您的结构设置方式是根据查询字符串参数动态包含内容,例如下载页面为?p=download
,下载二进制文件时?p=dl&get=r2s-Radio-1.7.10-1.0.0.ALPHA.zip&w=1
文件内容本身。
您的错误似乎是,您在任何情况下都包含了页面的HTML标头,在评估p
参数包含的内容之前。
你需要反过来做:如果请求zip文件内容,输出那个,并且在它之前(或之后)没有HTML代码 - 并且仅当请求不应该是文件时才输出HTML代码下载。
编辑:顺便说一句,那是你在那里的危险设置。 p
参数似乎允许在服务器上包含任何带有结尾.php
的文件 - 例如https://www.run2stay.com/?p=index
,这将使索引页面反复包含自身。如果其他脚本文件可能存在,也可能包含密码等敏感内容,甚至可能包括path traversal(未检查),那么您在此处遇到严重问题。