有没有办法判断用户上传的文件是否是服务器脚本?



我正在为我的Web主机编写一些服务器端脚本,这些脚本将为客户端应用程序进行大量自动更新。 只要用户使用应用程序名称和密码正确标识自己是所有者,他们就应该能够上传到自动创建的服务器上的存储库;但是,我不想允许上传任何脚本,以便它可以在服务器上运行。 我打算允许人们创建自己的存储库而无需询问我,那么无论如何都可以阻止此潜在漏洞吗?

这是存储库的设置代码,名为 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: 008rn"; return false; }
if (!startsWith($path, "/scripts/Apps/")) { echo "API FAILURE: 009rn"; return false; }
if (!Get_API_PW("./security.LOCK", $pass)) { echo "API FAILURE: 010rn"; return false; }
if ($path != "/scripts/Apps/".$api."/APPSETUP.php") { echo "API FAILURE: 011rn"; 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: 012rn"; return false; }
if ($up == "true" && !(file_exists("./".$dir."/UploadFile.php") || copy("./UploadFile.php", "./".$dir."/UploadFile.php"))) {
echo "API FAILURE: 013rn"; 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: 001rn"; return false; }
if (!(file_exists($dest2) || mkdir($dest2, 0777, true))) { echo "API FAILURE: 002rn"; return false; }
if (!file_exists($dest4)) { if (!App_Reset($dest2, $dest4, $pw)) { echo "API FAILURE: 003rn"; return false; } } 
if (!Get_API_PW($dest4, $pw)) { echo "API FAILURE: 004rn"; return false; }
if (!copy($temp1, $dest3)) { echo "API FAILURE: 005rn"; return false; }
if (!copy($temp2, $dest5)) { echo "API FAILURE: 006rn"; return false; }
if (!copy($temp3, $dest6)) { echo "API FAILURE: 007rn"; 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);
}
?>

这是用于上传文件的脚本。

<?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");
}
?>

请注意,上载脚本名为 UploadFile.php位于安装脚本中引用的模板文件夹中。

因此,按照问题评论中的建议,我尝试使用 .htaccess 禁用脚本执行,但由于我使用的是由 godaddy 托管的 Windows 服务器,所以我使用了错误类型的文件来执行此操作。 我找到了这个链接,它解释了如何在适用于Windows服务器的web.config中做同样的事情。

http://issues.umbraco.org/issue/U4-8472

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<system.webServer>
<handlers>
<clear />
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule,DefaultDocumentModule,DirectoryListingModule" resourceType="Either" requireAccess="Read" />
</handlers>
</system.webServer>
</configuration>

最新更新