I'm writing some server side scripts for my web host that will do a whole bunch of auto updating for client side applications. As long as the user has properly identified themselves as the owner with the app name and password they should be able to upload to a repository on the server created automatically; however, I don't want to allow any scripts to be uploaded such that it could run on the server. I intend to allow people to create their own repositories without having to ask me so is there anyway to block this potential vulnerability?
This is the setup code for the repositories, named APPSEtUP.php :
<?php
$app = str_replace("_", " ", TDecode($_POST['app']));
$pass = str_replace("_", " ", TDecode($_POST['pass']));
$command = str_replace("_", " ", TDecode($_POST['command']));
$worked = false;
if ($command == "SETUP_API") { $worked = SETUP_API($app, $pass); }
if ($command == "MAKE_DIR") { $worked = Make_Directory($app, $pass, TDecode($_POST['DIR']), TDecode($_POST['up'])); }
if ($worked) { echo "SUCCESS!"; }
return;
function Make_Directory($api, $pw, $dir, $up) {
$path = $_SERVER['REQUEST_URI'];
if ($path == "/scripts/APPSETUP.php") { echo "API FAILURE: 008\r\n"; return false; }
if (!startsWith($path, "/scripts/Apps/")) { echo "API FAILURE: 009\r\n"; return false; }
if (!Get_API_PW("./security.LOCK", $pass)) { echo "API FAILURE: 010\r\n"; return false; }
if ($path != "/scripts/Apps/".$api."/APPSETUP.php") { echo "API FAILURE: 011\r\n"; return false; }
while (startsWith($dir, ".") || startsWith($dir, "/")) { $dir = substr($dir, -(strlen($dir)-1)); }
while (endsWith($dir, "/")) { $dir = substr($dir, 0, strlen($dir)-1); }
if (!(file_exists("./".$dir."/") || mkdir("./".$dir."/", "0777", true))) { echo "API FAILURE: 012\r\n"; return false; }
if ($up == "true" && !(file_exists("./".$dir."/UploadFile.php") || copy("./UploadFile.php", "./".$dir."/UploadFile.php"))) {
echo "API FAILURE: 013\r\n"; return false;
} return true;
}
function startsWith($haystack, $needle) {
$length = strlen($needle);
return (substr($haystack, 0, $length) === $needle);
}
function endsWith($haystack, $needle) {
$length = strlen($needle);
return $length === 0 || (substr($haystack, -$length) === $needle);
}
function SETUP_API($api, $pw) {
$temp1 = "./Templates/USERLOG.php";
$temp2 = "./Templates/UploadFile.php";
$temp3 = "./APPSETUP.php";
$dest1 = "./Apps/";
$dest2 = "./Apps/".$api."/";
$dest3 = "./Apps/".$api."/USERLOG.php";
$dest4 = "./Apps/".$api."/security.LOCK";
$dest5 = "./Apps/".$api."/UploadFIle.php";
$dest6 = "./Apps/".$api."/APPSETUP.php";
if (!(file_exists($dest1) || mkdir($dest1, 0777, true))) { echo "API FAILURE: 001\r\n"; return false; }
if (!(file_exists($dest2) || mkdir($dest2, 0777, true))) { echo "API FAILURE: 002\r\n"; return false; }
if (!file_exists($dest4)) { if (!App_Reset($dest2, $dest4, $pw)) { echo "API FAILURE: 003\r\n"; return false; } }
if (!Get_API_PW($dest4, $pw)) { echo "API FAILURE: 004\r\n"; return false; }
if (!copy($temp1, $dest3)) { echo "API FAILURE: 005\r\n"; return false; }
if (!copy($temp2, $dest5)) { echo "API FAILURE: 006\r\n"; return false; }
if (!copy($temp3, $dest6)) { echo "API FAILURE: 007\r\n"; return false; }
return true;
}
function App_Reset($api, $sec, $pw) {
try {
Delete_Bad_App($api);
$pWriter = fopen($sec, "w");
fwrite($pWriter, TEncode($pw));
fclose($pWriter);
return true;
} catch (exception $e) { return false; }
}
function Delete_Bad_App($api) {
$di = new RecursiveDirectoryIterator($api, FilesystemIterator::SKIP_DOTS);
$ri = new RecursiveIteratorIterator($di, RecursiveIteratorIterator::CHILD_FIRST);
foreach ( $ri as $file ) {
$file->isDir() ? rmdir($file) : unlink($file);
} return;
}
function Get_API_PW($sec, $guess) {
try {
$pReader = fopen($sec, "r");
$pw = TDecode(fread($pReader, filesize($sec)));
fclose($pReader);
return $pw == $guess;
} catch (exception $e) { return false; }
}
function TriceInt($c) {
$b = unpack("C*", $c)[1] % 255;
$foo = (string)$b;
while (strlen($foo) < 3) { $foo = "0".$foo; }
return $foo;
}
function TEncode($str) {
if (TEncoded($str)) { return $str; }
return implode(array_map("TriceInt", str_split($str, 1)));
}
function TDecode($str) {
if (!TEncoded($str)) { return $str; }
return implode(array_map("chr", array_map('intval', str_split($str, 3))));
}
function TEncoded($str) {
return (ctype_digit($str) && strlen($str) % 3 == 0);
}
?>
and here is the script that is for uploading files.
<?php
$uploads_dir = './';
if ($_FILES["file"]["error"] == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["file"]["tmp_name"];
$name = $_FILES["file"]["name"];
move_uploaded_file($tmp_name, "$uploads_dir/$name");
}
?>
Do note that the upload script is named UploadFile.php and is located in a templates folder as referenced in the setup script.