Reputation: 1
I have created a download script in order to hide the file location and to force people passing by our website to download a file. it should return a .jar file. When i post a .jar file to download it'll return corrupt! so we changed the file-extension to .zip to test if that would work. Now i can download it for myself but other people still report corruption of the file...
here's a link to the live download page: https://www.run2stay.com/?p=download
here's the code used inside 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>
<? } } } ?>
The code i used inside 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>";
}
}
?>
Upvotes: 0
Views: 567
Reputation: 96151
Downloading the document and opening it with a text editor such as NotePad++, it looks like you are outputting a whole HTML document header first (up until your site’s nav menu and a section
element) – and only then there’s binary data that looks like it might be zip-ped data.
I presume that your structure is set up in a way where you dynamically include content based on the query string parameter, such as ?p=download
for the download page, and ?p=dl&get=r2s-Radio-1.7.10-1.0.0.ALPHA.zip&w=1
for the download of the binary file content itself.
Your mistake seems to be, that you are including the HTML header for the page in any case, before evaluating what the p
parameter contains.
You need to do it the other way around: If the zip file content is requested, output that, and no HTML code before (or after) it – and output HTML code only when the request is not supposed to be a file download.
Edit: And btw., that’s a dangerous setup you have there. The p
parameter seems to allow to include just about any file with the ending .php
on your server – such as https://www.run2stay.com/?p=index
, which will make the index page include itself into itself over and over again. If that is possible for other script files, with potentially sensitive content such as passwords, as well, maybe even including path traversal (didn’t check), then you have a serious problem here.
Upvotes: 1