Писане на сигурен код в PHP. Част 2
23-10-2012
Както ви казах в предишната статия(урок), ще има серия от уроци. А ето и втората част от поредицата - Писане на сигурен код в PHP. Част 2
В първата част, изброих някой от най-често срещаните проблеми в уеб приложенията. Сега продължаваме напред.

Мислех първо да започна с това: SQLi, XSS, Файл Ъплоад Атака (FUA). Но, като се замисля, ще го оставя за по нататък. Хахорите непрекъснато се самоусъвършенстват в методите за кражба на данни и влизане с неоторизиран достъп в определени сайтове.

Файлова система
Повечето Хостинг компании, както повечето уеб разработчици са предвидими. Повечето уеб разработчици си ползват готови шаблони(каталози) за файловите папки. Например www.sait.com/inc/, www.sait.com/includes/, www.sait.com/config/. Ако програмиста на сайта, постави файловете си в някоя от изброените директории, всеки ще може да ги види.

Какво имам предвид?
Създаваме си скрипт, с който се свързваме с MySQL или някоя друга база от данни и го записваме като: config.inc.
Това е много предвидимо, въпреки че напоследък се избягват тези имена. Е.. поне съм забелязал може и да има тук-там някой, който няма да си запише файла като .inc разширение. Защото това не е безопасно.
Защо да не е безопасно? Защото .inc разширението, може да се види като обикновен текст в браузъра и така да вземем информацията от файла(да е прочетем).
Не използвайте разширението на файла (.inc), за да съхранявате паролите до бази данни.
Ако е необходимо, използвайте разширението .inc.php, тогава файла ще бъде обработен като PHP-скрипт и по-този начин хахора няма да може да види съдържанието на файла.

Service команди PHP

В php-то има много команди, които имат достъп до сървъра. Следователно, с тези команди имаме достъп до операционната система, която може да взаимодейства с други такива програми.Не вярвам, че ще ви трябва да ги използвате и ако машината е ваша.. просто ги забранете. Не са безопасни - и това е дъвкано милиони пъти.
Давам пример. Например, функцията eval(); може да се разглежда като низ PHP код и да го изпълни. В някои случаи е доста полезно. Въпреки това, използването на eval() , може да навреди на вашия сайт. Чрез предоставяне на достъп до тази функция, трябва да сте особено внимателни, за да се провери постъпващите данни.
Има начини да се заобиколят тези функции, но все пак ги изключите по подразбиране - най-добре от файла php.ini. Функциите: ini_set(), exec(), fopen(), popen(), passthru(), readfile(), file(), shell_exec() и system().

Написал съм отделен урок за SQL Injection и XSS, за да бъде всичко отделно и подредено.
Ето и линк към урока: http://web-tourist.net/login/login/view.php?st=3443

Файл ъплоад (FUA).

FUA е една от най-сериозните заплахи за сайтовете, тъй като тя дава на хахора голяма свобода и почти неограничени възможности за злоупотреба. Атаката най-често се осъществява при сайтове, които предлагат на потребителите възможност за качване на файлове на уеб сървъра.
Слабото място на много PHP приложения е именно скриптът за качване на файлове.

Пример. Нека вземем за пример приложение, в което следната форма потребителя може да качи всякакъв файл.
/чрез този код по-долу, не проверяваме файла дали е даден формат и директно извършваме качването на файла/
<?php
if(isSet($_POST['submit'])) {
$uploadfile = 'pics/' . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "файла е качен успешно";
} else {
echo "проблем при качването";
}
} else {
echo '<form method="post" enctype="multipart/form-data">Качи снимка: <input type="file" name="userfile" /><input type="submit" name="submit"></form>';
}
?>


В горния код, забелязваме че файла се качва директно в директория на сървъра(нито го обработваме, нито нищо). Оттук можем да качим директно злонамерен код, с който да счупим/хакнем уеб сайта.
Например: http://saita.com/pics/shell.php

Сега, да разширим кода и да направим проверка за типа на файла(mime type проверката). Ако файла(снимката) е различен/а от разрешения тип (в нашия случай JPG), то файла няма да бъде качен в сървъра.
<?php
if(isSet($_POST['submit'])) {
if($_FILES['userfile']['type'] != "image/jpg") {
echo "разшрешен формат само jpg";
} else {
$uploadfile ='pics/' . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "файла е качен успешно";
} else {
echo "проблем при качването";
}
}
} else {
echo '<form method="post" enctype="multipart/form-data">Качи снимка: <input type="file" name="userfile" /><input type="submit" name="submit"></form>';
}
?>


С горния код ще проверим дали съдържанието/mime типа/ на файла е JPG или не е.

Нека видим за какво става дума.

"
POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=---------------------------23281168279961
Content-Length: 156
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: application/x-php(не е) <<<<<<
"


Има начин да заобиколим тази защита, чрез манипулация съдържанието с нужния инструмент. Например: Tamper Data

При опит да качим злонамерения код както виждаме по-горе, типа на файла е: application/x-php (с горната защита, няма да го позволи), но сега с помощта на TamperData можем да го променим на image/png
Тоест: "Content-Type" => "image/png"

След, което това ще създаде файл: shell.php в директорията където се качват изображенията и по тозин начин чупим кода.

Например: http://saita.com/pics/shell.php

Сега трябва да проверим, съдържанието на файла. Друг метод за разпознаване на изображения, който често се среща в PHP приложенията, е чрез функцията getimagesize()/трябва GD библиотека/, която връща типа и размера на дадено изображение.
Ако файлът, който се провери с getimagesize(), не е изображение, то типа и размера няма да бъдат валидни стойности:

<?php
if(isSet($_POST['submit'])) {
$imageinfo = getimagesize($_FILES['userfile']['tmp_name']);
if($imageinfo['mime'] != 'image/png' && $imageinfo['mime'] != 'image/jpeg') {
echo "разрешени формати само png и jpeg";
} else {
$uploadfile = 'pics/' . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "файла е качен успешно";
} else {
echo "проблем при качването";
}
}
} else {
echo '<form method="post" enctype="multipart/form-data">Качи снимка: <input type="file" name="userfile" /><input type="submit" name="submit"></form>';
}
?>


В горния пример PHP функцията getimagesize() връща размера и типа на изображението, ако файлът е валиден то тогава ще качи файла в директория /pics.
За съжаление подобна проверка само прави атаката малко по-сложна. Причината за това, че един файл може да бъде едновременно валидно изображение и PHP скрипт, тъй като повечето формати за изображение позволяват наличието на коментари във файловете.
Сега, за да заобиколим горната защита с getimagesize() ще трябва да сложим най-отгоре на нашият злонамерен скрипт този код: GIF89a;

Ето и как ще ни изглежда примерния код:
GIF89a;
<?php system($_GET['evil']); ?>


http://saita.com/pics/shell.php

Ето ви един примерен скрипт, с който можем да бъдем защитени. В него правим проверка на съдържанието на файла + разширението на файла.
<?php
if(isSet($_POST['submit'])) {
$imageinfo = getimagesize($_FILES['userfile']['tmp_name']);
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg') {
echo "разрешени формати само gif и jpeg";
} else {
if (!strpos($_FILES['userfile']['name'],".jpg") && !strpos($_FILES['userfile']['name'],".jpeg") && !strpos($_FILES['userfile']['name'],".gif")) {
echo "разрешени формати: .jpg, .jpeg, .gif";
} else {
$uploadfile = 'pics/' . basename($_FILES['userfile']['name']);
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "файла е качен успешно";
} else {
echo "проблем при качването";
}
}
}
} else {
echo '<form method="post" enctype="multipart/form-data">Качи снимка: <input type="file" name="userfile" /><input type="submit" name="submit"></form>';
}
?>


В папка pics/ , създайте един файл .htaccess , който да "блокира" други файлове, освен изображенията.

<Files ~ "^.*\.(php|cgi|pl|php3|php4|php5|php6|phtml|shtml|txt|html|asp)">
Order allow,deny
Deny from all
</Files>


За да не се превръща урока в ръководство за хахори спирам до тук.

Лек ден! :)

РЕ: Ако имате някакви предложения просто ми пишете ЛС.

/ Трябва да сте регистриран за да напишете коментар /
От: explozen
15:18 06-01-2013
Супер е!
1