How secure (hardened) is this script?
The script below, test.php, is intended to be placed in a specific directory of all my wordpress sites. Its purpose is to grab the file at the $source address below and extract it to the directory in which it resides. That's all its intended to do.
For example, I will have a dashboard interface on my central server that lists all my sites in which this script is present. I will then execute a cURL routine that iterates over every site and performs a call on this script, effectively sending the update file to all of them at once.
The call is made like so...
...processing site 1 update...
http://targetsite1.com/somedeepdirectory/test.php?query=updates.zip
...processing site 2 update...
http://targetsite2.com/somedeepdirectory/test.php?query=updates.zip
...etc until all my sites have been updated.
My question is (1) how secure (hardened) is this script, as is. and (2) what checks should I put in place to make more so...
I'm thinking that at a minimum I would restrict the character count for myquery as well as check the payload in myquery for malicious开发者_如何学运维, unexpected filetypes?
<?php
// TEST.PHP
$source = 'http://mycentralserver.com/protected/'.$_GET['myquery'];
$target = '.';
$out_file = fopen(basename($source), 'w');
$in_file = fopen($source, 'r');
while ($chunk = fgets($in_file)) {
fputs($out_file, $chunk);
}
fclose($in_file);
fclose($out_file);
$zip = new ZipArchive();
$result = $zip->open(basename($source));
if ($result) {
$zip->extractTo($target);
$zip->close();
}
?>
The security of this script in its current state is pretty good. I do have a few concerns. Under NO CONDITION must you accidentally download a .php file and store it in your web root. This is the worst thing that could happen for this script as it would be a remote code execution vulnerability. Files should be downloaded into a specific directory, if you are concerned with other accessing this file you should do a "deny from all" in a .htaccess in that folder. If there are any errors in this script you should delete the downloaded file. In fact I recommend deleting the downloaded files asap.
My concern is that the script should error gracefully. You should check to make sure that you have obtained what you are looking for. Even if the file isn't a .php file it can contain php code <?php ?>
which then could be include()'ed which would turn a Local File Include (LFI) vulnerability into full blown remote code execution.
In a secure php configuration allow_url_fopen should be OFF and PhpInfoSec agrees with me. This means that fopen() cannot be used for HTTP. allow_url_fopen is enabled by default and I disable it on all production systems. The reason why is because I have personally written a remote code execution exploit in Coppermine Photo gallery that took advantage of this insecure default. CURL should ALWAYS be used for HTTP in PHP, it is more secure and more stable.
I could pass
http://targetsite1.com/test.php?query=/tmp/somefile.zip
and clobber your site with any file I could manage to get somewhere on your webhost.
-- actually I'm not sure about that. It would have to be web accessible on mycentralserver.com.
The sites in question dumbly download the .ZIP file from your central server on command. They don't verify that the .ZIP file came from you, or that your central server hasn't been compromised.
I'd use GPG to sign your ZIPs. They don't need to be encrypted (but that never hurts) but they need to be signed.
Consider what your script is doing. You are accessing some sort of query engine, creating a zip file, and passing data back and forth to that file and query engine. Fortunately this code is executed on the server and not the client machine, so it at least as insecure as access to your web server. After consideration for your web server it is only as secure as your network architecture necessary to access the service running that query engine or as secure as access to that zip file the script creates.
Unless those data repositories store personally identifiable information nobody is going to want to mess with your code unless messing with your code provides an easy means to defacing a site with some degree of traffic or reputation. So, what mechanisms exist to prevent people from freely injecting malicious code into your query engine or your zip archive?
Consider switching off fopen_wrappers and using the curl or http libraries to access intended HTTP content.
This will secure your system from other vulnerabilites where a malicious attacker can gain access to web content inside a script where you intended to rectrict access to the local file system. With fopen_wrappers off, file means (local) file and http means http.
Think also about who can execute this script. I would protect it in some way, so that a random guy/robot on the internet can't call it easily. Consider restricting it by source IP, or maybe implement a password check, if the script is intended to be called interactively.
One problem here is that you dont check for directory traversal, so one can copy the whole disk (in principle) to location '.'
If ./ is accessible from the web, you have a big problem.
My advice is to recursively remove all the instances of .. so you can avoid directory traversal
To be more precise, if I would pass as input ../../../../../../etc/passwd then this file will be copied to the current working directory. Since your script has access to write there, obviously, the passwd file would be exposed.
Also not the encoding a . or a / can be encoded in a dozen different ways, so dont do a hardcoded search and replace on ../
精彩评论