PHP.mk документација

Безбедност на датотечниот систем

Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.

security.filesystem.php PHP.net прокси Преводот се освежува
Оригинал на PHP.net
Патека security.filesystem.php Локална патека за оваа страница.
Извор php.net/manual/en Оригиналниот HTML се реупотребува и локално се стилизира.
Режим Прокси + превод во позадина Кодовите, табелите и белешките остануваат читливи во истиот тек.
Безбедност на датотечниот систем

Референца за `security.filesystem.php` со подобрена типографија и навигација.

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!";

?>
Пример #1 Слабата проверка на променливите води до.... "../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!";

?>
Пример #2 ... Напад на датотечниот систем
  • Постојат две важни мерки што треба да ги преземете за да ги спречите овие проблеми. 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);

?>
Пример #3 Посигурна проверка на имињата на датотеките "../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 белешки

anonymous
20 години пред
(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.");
}
fmrose на ncsu точка edu
20 години пред
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.
devik на cdi точка cz
figroc at gmail dot com
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.
devik
Лачезар Цветков
пред 17 години
A 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!');
    }
}
?>
cronos586(AT)caramail(DOT)com
figroc at gmail dot com
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
На оваа страница

Автоматски outline од активната документација.

Насловите ќе се појават тука по вчитување.

Попрегледно читање

Примерите, changelog табелите и user notes се визуелно издвоени за да не се губат во долгата содржина.

Брз совет Користи го outline-от Скокни директно на главните секции од активната страница.
Извор Оригиналниот линк останува достапен Кога ти треба целосен upstream context, отвори го PHP.net во нов tab.