(A) Better not to create files or folders with user-supplied names. If you do not validate enough, you can have trouble. Instead create files and folders with randomly generated names like fg3754jk3h and store the username and this file or folder name in a table named, say, user_objects. This will ensure that whatever the user may type, the command going to the shell will contain values from a specific set only and no mischief can be done.
(B) The same applies to commands executed based on an operation that the user chooses. Better not to allow any part of the user's input to go to the command that you will execute. Instead, keep a fixed set of commands and based on what the user has input, and run those only.
For example,
(A) Keep a table named, say, user_objects with values like:
username|chosen_name |actual_name|file_or_dir
--------|--------------|-----------|-----------
jdoe |trekphotos |m5fg767h67 |D
jdoe |notes.txt |nm4b6jh756 |F
tim1997 |_imp_ folder |45jkh64j56 |D
and always use the actual_name in the filesystem operations rather than the user supplied names.
(B)
<?php
$op = $_POST['op'];//after a lot of validations
$dir = $_POST['dirname'];//after a lot of validations or maybe you can use technique (A)
switch($op){
case "cd":
chdir($dir);
break;
case "rd":
rmdir($dir);
break;
.....
default:
mail("[email protected]", "Mischief", $_SERVER['REMOTE_ADDR']." is probably attempting an attack.");
}Безбедност на датотечниот систем
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
Безбедност на датотечниот систем
Референца за `security.filesystem.php` со подобрена типографија и навигација.
Безбедност на датотечниот систем
Содржина
PHP е предмет на безбедноста вградена во повеќето серверски системи во однос на дозволите на основа на датотеки и директориуми. Ова ви овозможува да контролирате кои датотеки во датотечниот систем може да се читаат. Треба да се внимава со сите датотеки што се читливи од целиот свет за да се осигура дека тие се безбедни за читање од сите корисници кои имаат пристап до тој датотечен систем.
е предмет на безбедноста вградена во повеќето серверски системи во однос на дозволите на основа на датотека и директориум. Ова ви овозможува да контролирате кои датотеки во датотечниот систем може да се читаат. Треба да се внимава со сите датотеки што се читливи од сите за да се осигурате дека се безбедни за читање од сите корисници кои имаат пристап до тој датотечен систем. PHP Бидејќи PHP беше дизајниран да овозможи пристап на ниво на корисник до датотечниот систем, сосема е можно да се напише /etc/passwdскрипта што ќе ви овозможи да читате системски датотеки како што се
, да ги менувате вашите етернет конекции, да испраќате масовни печатарски задачи итн. Ова има некои очигледни импликации, во смисла дека треба да се уверите дека датотеките што ги читате и пишувате се соодветните. PHP Разгледајте ја следнава скрипта, каде што корисникот покажува дека би сакал да избрише датотека во својата домашна директорија. Ова претпоставува ситуација каде
веб интерфејсот редовно се користи за управување со датотеки, така што корисникот на Apache е дозволено да брише датотеки во домашните директориуми на корисникот.
<?php
// Remove a file from the user's home directory
$username = $_POST['user_submitted_name'];
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
unlink("$homedir/$userfile");
echo "The file has been deleted!";
?>"../etc/" and "passwd"Бидејќи корисничкото име и името на датотеката може да се испратат од корисничка форма, тие можат да испратат корисничко име и име на датотека што припаѓаат на некој друг, и да го избришат дури и ако не им е дозволено да го сторат тоа. Во овој случај, би сакале да користите некоја друга форма на автентикација. Размислете што може да се случи ако испратените променливи беа
. Кодот тогаш ефективно би гласел:
<?php
// Removes a file from anywhere on the hard drive that
// the PHP user has access to. If PHP has root access:
$username = $_POST['user_submitted_name']; // "../etc"
$userfile = $_POST['user_submitted_filename']; // "passwd"
$homedir = "/home/$username"; // "/home/../etc"
unlink("$homedir/$userfile"); // "/home/../etc/passwd"
echo "The file has been deleted!";
?>- Постојат две важни мерки што треба да ги преземете за да ги спречите овие проблеми. PHP Дозволете само ограничени дозволи за
- веб кориснички бинарен фајл.
Еве подобрена скрипта:
<?php
// Removes a file from the hard drive that
// the PHP user has access to.
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanism
$userfile = basename($_POST['user_submitted_filename']);
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (file_exists($filepath) && unlink($filepath)) {
$logstring = "Deleted $filepath\n";
} else {
$logstring = "Failed to delete $filepath\n";
}
$fp = fopen("/home/logging/filedelete.log", "a");
fwrite($fp, $logstring);
fclose($fp);
echo htmlentities($logstring, ENT_QUOTES);
?>"../etc/"Сепак, дури и ова не е без свои недостатоци. Ако вашиот систем за автентикација им дозволува на корисниците да креираат свои кориснички најавувања, а корисникот го избра најавувањето
, системот повторно е изложен. Од таа причина, можеби ќе претпочитате да напишете поконкретна проверка:
<?php
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanisim
$userfile = $_POST['user_submitted_filename'];
$homedir = "/home/$username";
$filepath = "$homedir/$userfile";
if (!ctype_alnum($username) || !preg_match('/^(?:[a-z0-9_-]|\.(?!\.))+$/iD', $userfile)) {
die("Bad username/filename");
}
// etc.
?>
Во зависност од вашиот оперативен систем, постојат широк спектар на датотеки за кои треба да се грижите, вклучувајќи записи за уреди (/dev/
or COM1), конфигурациски датотеки (/etc/ датотеки и .ini датотеки), добро познати области за складирање датотеки (/home/,
Мои документи), итн. Од оваа причина, обично е полесно да се создаде политика каде што забранувате сè освен она што експлицитно го дозволувате.
Белешки од корисници 5 белешки
All of the fixes here assume that it is necessary to allow the user to enter system sensitive information to begin with. The proper way to handle this would be to provide something like a numbered list of files to perform an unlink action on and then the chooses the matching number. There is no way for the user to specify a clever attack circumventing whatever pattern matching filename exclusion syntax that you may have.
Anytime you have a security issue, the proper behaviour is to deny all then allow specific instances, not allow all and restrict. For the simple reason that you may not think of every possible restriction.Well, the fact that all users run under the same UID is a big problem. Userspace security hacks (ala safe_mode) should not be substitution for proper kernel level security checks/accounting.
Good news: Apache 2 allows you to assign UIDs for different vhosts.
devikA basic filename/directory/symlink checking may be done (and I personally do) via realpath() ...
<?php
if (isset($_GET['file'])) {
$base = '/home/polizei/public_html/'; // it seems this one is good to be realpath too.. meaning not a symlinked path..
if (strpos($file = realpath($base.$_GET['file']), $base) === 0 && is_file($file)) {
unlink($file);
} else {
die('blah!');
}
}
?>when using Apache you might consider a apache_lookup_uri on the path, to discover the real path, regardless of any directory trickery.
then, look at the prefix, and compare with a list of allowed prefixes.
for example, my source.php for my website includes:
if(isset($doc)) {
$apacheres = apache_lookup_uri($doc);
$really = realpath($apacheres->filename);
if(substr($really, 0, strlen($DOCUMENT_ROOT)) == $DOCUMENT_ROOT) {
if(is_file($really)) {
show_source($really);
}
}
}
hope this helps
regards,
KAT44