Златни правила на уеб разработчика (web developers golden rulez):
1. Няма абсолютна и универсална защита, всичко подлежи на хакване!
2. Най-добре си го хаквай {скрипта} често, често сам и се.. оправяй.. сам, преди да те оправят други!
3. Грам никакво доверие на потребителя, т.е на каквото и да е идващо от GET, POST, COOKIE, SESSION, REQUEST (ако някой все още го ползва), HTTP Headers, etc.
4. 13 проверки са по-добре от една или николко, но все пак не се знае дали са достатъчни..
5. Ученето трябва да продължи!
Във връзка с една тема от миналата седмица в BGDev, ето един метод за почистване на GET заявки от излишни боклуци.
В заявката са допустими само параметри, дефинирани в масива $allowableParams и са забранени символите, посочени в другия conf масив: $forbiddenSymbols.
Разбира се, подобна реализация има своите ограничения (modRewrite, кирилица, search формуляри, събмитващи през GET и т.н.), така че в зависимост от приложението може да се променя съдържанието на масивите и изобщо цялата реализация на метода. Също така, при установяване на непозволени параметри или забранени символи (опити за XSS или SQL injection), освен логването на опита и редиректването към страница с “чиста” GET заявка, може да се добави и друга някаква функционалност: мейл до администратор, бан на потребител и т.н.
Така, ето как изглежда началото на една страница, която ще използва този клас:
< ?php
define('CLASSES_PATH', ".");
$forbiddenSymbols = array('<', '>', '(', ')',
'..', '%', '*', '+', '!', '@');
$allowableParams = array('p', 'id');
if (isset($_SERVER['QUERY_STRING']) &&
!еmрty($_SERVER['QUERY_STRING'])) {
require_once(CLASSES_PATH . "/class.clean.php");
$clean = new MrGETClean;
$queryString = $clean->queryWalk($_SERVER['QUERY_STRING'],
$forbiddenSymbols,
$allowableParams,
$_SERVER['SCRIPT_NAME']);
if ($queryString != $_SERVER['QUERY_STRING']) {
$newURL = basename($_SERVER['SCRIPT_NAME']) .
'?' . $queryString;
header("location: " . $newURL);
}
}
Ето го и самия клас с основния метод queryWalk:
< ?php
define('LOG_PATH', "log");
class MrGETClean {
function queryWalk($queryString,
$forbiddenSymbols,
$allowableParams,
$scriptURL) {
$flag = false;
$queryFragments = array();
$queryArr = array();
$cleanedQueryFragments = array();
$queryFragments = explode("&", $queryString);
foreach ($queryFragments as $key => $value) {
$queryArr[$key]['p'] =
substr($value, 0, strpos($value, '='));
$queryArr[$key]['v'] =
substr($value, strpos($value, '=') + 1);
}
foreach ($queryArr as $key => $value) {
if (!in_array($queryArr[$key]['p'],
$allowableParams)) {
$queryArr[$key] = null;
$flag = true;
}
foreach ($forbiddenSymbols as $symbol) {
if (stristr($queryArr[$key]['v'],
$symbol)) {
$queryArr[$key] = null;
$flag = true;
}
}
}
foreach ($queryArr as $key => $value) {
if ($queryArr[$key]['p'] != null) {
$cleanedQueryFragments[$key] =
$queryArr[$key]['p'] . "=" .
$queryArr[$key]['v'];
}
}
if ($flag) {
$this->MrGETCleanMakeLog($queryString,
$scriptURL);
}
$queryString = implode("&", $cleanedQueryFragments);
return $queryString;
}
А това са методът, който генерира лог файла и този, който връща IP адреса на “атакуващия”:
function MrGETCleanMakeLog($queryString, $scriptURL) {
$date = date ("d-m-Y @ H:i:s");
$log = LOG_PATH . "/log.txt";
$handle = fopen($log,"a+" );
fputs ($handle, 'Attack Date: ' . $date .
' | Attacker IP: ' . $this->getIP() .
' | Query: ' . htmlentities(urldecode($queryString)) .
' | Script: ' . $scriptURL . "\r\n");
fclose($handle);
}
function getIP() {
$IP = '';
if (isset($_SERVER)) {
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$IP = $_SERVER['HTTP_X_FORWARDED_FOR'];
}
elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
$IP = $_SERVER['HTTP_CLIENT_IP'];
}
else {
$IP = $_SERVER['REMOTE_ADDR'];
}
}
else {
if (getenv('HTTP_X_FORWARDED_FOR')) {
$IP = getenv('HTTP_X_FORWARDED_FOR');
}
elseif (getenv('HTTP_CLIENT_IP')) {
$IP = getenv( 'HTTP_CLIENT_IP' );
}
else {
$IP = getenv('REMOTE_ADDR');
}
}
return $IP;
}
Файловете, които са ви нужни са примерният index.php и класът class.clean.php. Демото можете да пробвате тук: www.vlkomarov.info/projects/mr-get-clean (Log: log.txt).
Променяйте съобразно вашите нужди и спецификата на приложението.
Линкването на това демо не е задължително, но ще съм ви благодарен, ако го правите ![]()
Tags: GET, PHP, SQL Injection, XSS, заявка, проверка, сигурност
‹ Холитутки - за дамите, само с любоФ •

3 коментара
RSS емисия за коментарите към тази публикация
Trackback линк
http://www.vlkomarov.info/blog/2008/08/17/mr-get-clean/trackback/
17.08.2008, 18:32
Pingback от Hamaelleon: Коментари и.. edno23.com
18.08.2008, 1:40
Pingback от » Вовата, s. Hamaelleon ™ · Mr GET Clean « Аз, пиратът
17.08.2008 at 18:26
Hamaelleon
Този плъгин ме дразни. Не стига, че не оцветява контекстно сорс кода така, както се очаква, но и с това пренасяне на нов ред за да се побера в 500px на блога прецаквам всякаква идея за четимост и нормални indent-и.
A BGDev в момента е паднал (?) и не мога да линкна темата, заради, която писах всичко това.. Трябва да намеря и примера, който послужи за основа на този клас (например, метода за логването е почти същия. getIP() e от php.net.