CVE-2019-17059: Pojasnjena Preauth-RCE v Sophosovem Cyberoamu

Pri TheBestVPN smo se zelo trudili z raziskovalci notranje in zunanje varnosti, da bi odkrili resne oddaljene izkoriščene vrzeli v VPN-jih SSL in požarni zidovi, kot so Cyberoam, Fortigate in Cisco VPN. Ta članek je tehnična rešitev glede zakrpa kritične ranljivosti, ki vpliva na Cyberoam SSL VPN, znan tudi kot CyberoamOS.


To izkoriščanje Cyberoam, poimenovano CVE-2019-17059, je kritična ranljivost, ki napadalcem omogoča dostop do vaše naprave Cyberoam, ne da bi podali uporabniško ime ali geslo. Poleg tega je dostop odobren na najvišji ravni (root), ki v bistvu daje napadalcu neomejene pravice na vaši napravi Cyberoam.

V večini omrežnih okolij se naprave Cyberoam uporabljajo kot požarni zidovi in ​​SSL prehodi VPN. To potencialnemu napadalcu omogoči močno oporo v mreži. Omogoča lažje napadanje gostiteljev znotraj omrežja, in ker je napravam Cyberoam običajno zaupanje v večini okolij, to daje potencialnemu napadalcu dodatno prednost.

Po besedah ​​Shodana (iskalnika internetnih naprav) obstaja več kot 96.000 internetnih naprav Cyberoam z vsega sveta. Večina teh naprav je nameščena v podjetjih, univerzah in nekaj v svetovno priznanih bankah. To vodi do napadov, ki imajo v teh okoljih velik vpliv.

Delo z varnostno skupino Sophos je bilo v veliko veselje, saj so hitro ukrepali s priznanjem in uvajanjem obližev le nekaj dni po našem prvotnem poročilu zanje. Kudos jim! (punka namenjena!)

odkrivanje Cyberoama

In ker je večina teh subjektov privlačna tarča napadalcev, je hrošče vse bolj kritično.

CyberoamOS Oddaljeno nepooblaščeno izvajanje korenskega ukaza

CyberoamOS je spremenjen operacijski sistem, ki temelji na Linuxu za naprave Cyberoam. Ta operacijski sistem ima spletni konfiguracijski vmesnik in SSLVPN portal.

Spletni vmesnik je razdeljen na dva glavna dela:

  • Prednja stran napisana v Javi
  • Zaledje, ki uporablja kombinacijo C in Perl

Ne bomo se poglobili v notranjost sprednje ali zadnje kode, predvsem zato, da prihranimo čas in omejimo količino razkritih informacij. Na kratko pa se bomo pogovorili, kako se sproži hroščev.

Tako konfiguracijski kot SSLVPN vmesniki imajo servlet, ki upravlja glavne operacije. Te operacije so določene s parametrom z imenom "način".

Večina teh je overjena. Toda do nekaterih možnosti lahko dostopamo brez preverjanja pristnosti (na primer prijava).

Napake, ki smo jih našli, se nahajajo v e-poštnem protivirusnem / antispam modulu. Način zahteve za to končno točko (modul, op) je 458.

Treba je opozoriti, da so kode preslikane na njihova imena v bazi Cyberoam (notranja baza podatkov Postgres). Če pogledamo 458, lahko ugotovimo, kako je ime te kode.

Tu je vrstica iz skripta SQL za inicializacijo baze podatkov, ki prikazuje ime opcode 458:

vstavite v tblcrevent (opcode, opis, način, vrsta zahteve)
vrednosti („RELEASEQUARANTINEMAILFROMMAIL“, „SPROSTITEV KARANTINSKE POŠTE IZ POŠTE“, „458“, 2);

Funkcije za kodiranje so shranjene v imeniku / _conf / csc / cscconf /. Ne bomo razkrili celotne kode ranljive funkcije, vendar bomo zagotovili nekaj odrezkov, ki prikazujejo, kje in kako se napaka pojavlja.

Koda iz Java frontenda, ki obravnava opcode 458:

if ((jsonObject.getString ("hdnSender") .equals ("") ||
validateEmail (jsonObject.getString ("hdnSender"))) &&
validateEmail (jsonObject.getString ("hdnRecipient")) &&
isSafeFilePath (jsonObject.getString ("hdnFilePath")) && b) {
httpServletResponse.setContentType ("besedilo / html");
CyberoamLogger.debug ("Antivirus / AntiSpam", "Stalna vrednost CSC " +
CSCConstants.isCCC);

Kot lahko vidite zgoraj, je nekaj parametrov preverjenih veljavnosti. Če so veljavne vrednosti, se zgodi naslednje:

končni EventBean eventByMode = EventBean.getEventByMode (363);
... redigovano.
končni int sendWizardEvent = cscClient.sendWizardEvent (eventByMode, hashMap, sqlReader);

Kot lahko vidimo zgoraj, imamo novo kodo dogodka (363), ki bo poslana v zaledje. Napaka, ki smo jo odkrili, je v kodi, ki to obravnava v zaledju.

Opcode je poimenovan sendmail, in da se izognemo izkoriščanju te napake, bomo večino kode uredili iz naslednje kode.

Upravljavec opcode za send_mail.

...redigovano ...

$ param = $ zahteva->{javnost};
param = DLOPEN (base64_decode, param)
LOG applog " Vrednosti dekodiranja :: $ param \ n"
% requestData = razdeljena (/ [&=] /, $ param);
$ mailServerHost = $ requestData {hdnDestDomain};
$ mailFrom = $ requestData {hdnSender};
$ mailTo = $ requestData {hdnRecipient};
$ file = $ QUARANTINE_PATH."/".$ requestData {hdnFilePath};

$ mailfile = $ requestData {hdnFilePath};
$ validate_email ="lažno";
moj $ email_regex = '^ ([\.]? [_ \ - \! \ # \ {\} \ $ \% \ ^ \&\ * \ + \ = \ | \? \ '\\\\\ / a-zA-Z0-9]) * @ ([a-zA-Z0-9] ([-]? [a-zA- Z0-9] +) * \.) + ([A-zA-Z0-9] {0,6}) $ ';
if ($ requestData {hdnRecipient} = ~ / $ email_regex / && ((definirano $ requestData {hdnSender} && $ requestData {hdnSender} eq '') || $ requestData {hdnSender} = ~ / $ email_regex /) && indeks ($ requestData {hdnFilePath}, '.. /') == -1) {
$ validate_email ="prav";
}
.... redigovano....

Kot lahko vidimo zgoraj, nam psevdo-Perlova koda prikazuje, kako podpornik sprejema vhod iz sprednjega dela ($ requestData) in kako poskuša preveriti nekatere parametre, ki jih pošljemo.

Če so naši parametri veljavni, se po preverjanju izvede naslednja koda:

% mailreq = ("klicanje"=>"$ MAIL_FORWARD","predmet"=>"$ strSpredmet","doEmail"=>"$ mailTo","datoteko priloge"=>"$ datoteka","smtpserverhost"=>"$ mailServerHost","iz naslova"=>"$ mailOd");

ven = OPCODE mail_sender json% mailreq

Zgornja koda nastavi naše zahteve zahteve v spremenljivko mailreq in pokliče funkcijo mail_sender (OPCODE). Videli bomo, kako se izvaja ta koda in kje točno se dogaja RCE:

#mailaction 0 = mail_with_var, 1 = mail_forward, 2 = mail_attachment
$ mailaction = $ zahteva->{mailaction};
$ subject = $ zahteva->{zadeva};
$ mailbody = '';
$ attachmentfile = $ zahteva->{attachmentfile};
$ toEmail = $ zahteva->{toEmail};

#mail body
ČE ("določena $ zahteva->{mailbody} && '' ne $ zahteva->{mailbody}") {
$ mailbody = $ zahteva->{mailbody};
}
Gostitelj strežnika #SMTP
ČE ("določena $ zahteva->{smtpserverhost} && '' ne $ zahteva->{smtpserverhost}") {
$ smtpserverhost = $ zahteva->{smtpserverhost};
} ELSE {
rezultat = QUERY "izberite servisno vrednost iz tblclientservices, kjer je servicekey = 'MailServer'"
ČE ("določen $ rezultat->{izhod}->{servicevalue} [0] && '' ne $ rezultat->{izhod}->{servicevalue} [0]") {
$ smtpserverhost = $ rezultat->{izhod}->{servisna vrednost} [0];
} ELSE {
$ smtpserverhost ="127.0.0.1";
}
}

#SMTP strežniška vrata
ČE ("določena $ zahteva->{smtpserverport} && '' ne $ zahteva->{smtpserverport}") {
$ smtpserverport = $ zahteva->{smtpserverport};
} ELSE {
rezultat = QUERY "izberi servisno vrednost iz tblclientservices, kjer servicekey = 'MailServerPort'"
ČE ("določen $ rezultat->{izhod}->{servicevalue} [0] && '' ne $ rezultat->{izhod}->{servicevalue} [0]") {
$ smtpserverport = $ rezultat->{izhod}->{servisna vrednost} [0];
} ELSE {
$ smtpserverport ="25";
}
}

Oznaka #SMTP auth
$ smtpauthflag ="0";
ČE ("določena $ zahteva->{smtpauthflag} && '' ne $ zahteva->{smtpauthflag}") {
$ smtpauthflag = $ zahteva->{smtpauthflag};
} ELSE {
rezultat = QUERY "izberi servisno vrednost iz tblclientservices, kjer je servicekey = 'SMTPAuthenticationFlag'"
ČE ("določen $ rezultat->{izhod}->{servicevalue} [0] && '' ne $ rezultat->{izhod}->{servicevalue} [0]") {
$ smtpauthflag = $ rezultat->{izhod}->{servisna vrednost} [0];
}
}

ČE ("$ smtpauthflag == 1") {
ČE ("določena $ zahteva->{mailusername} && '' ne $ zahteva->{mailusername}") {

$ mailusername = $ zahteva->{mailusername};
$ mailpassword = $ zahteva->{mailpassword};

} ELSE {
rezultat = QUERY "izberi servisno vrednost iz tblclientservices, kjer servicekey = 'MailServerUsername'"
$ mailusername = $ rezultat->{izhod}->{servisna vrednost} [0];
rezultat = QUERY "izberi servisno vrednost iz tblclientservices, kjer servicekey = 'MailServerPassword'"
$ mailpassword = $ rezultat->{izhod}->{servisna vrednost} [0];
}
} ELSE {

$ mailusername = "";
$ mailpassword = "";

}
ČE ("določena $ zahteva->{fromaddress} && '' ne $ zahteva->{fromaddress}") {
$ fromaddress = $ zahteva->{iz naslova};
} ELSE {
rezultat = QUERY "izberite servisno vrednost iz tblclientservices, kjer je servicekey = 'FromAddress'"
$ fromaddress = $ rezultat->{izhod}->{servisna vrednost} [0];
}

# Varnostni način
ČE ("določena $ zahteva->{smtpsecurity} && '' ne $ zahteva->{smtpsecurity}") {
$ smtpsecurity = $ zahteva->{smtpsecurity};
} ELSE {
rezultat = QUERY "izberite servisno vrednost med tblclientservices, kjer je servicekey = 'smtpsecurity'"
$ smtpsecurity = $ rezultat->{izhod}->{servisna vrednost} [0];
}

$ smtpsecuritymode = 0;
ČE ("$ smtpsecurity eq 'STARTTLS'") {
$ smtpsecuritymode = 1;
} ELSE IF ("$ smtpsecurity eq 'SSL / TLS'") {
$ smtpsecuritymode = 2;
}

#SMTP Potrdilo

$ smtpcertificate = '';
$ certpassword = '';

ČE ("$ smtpsecuritymode! = 0") {
ČE ("določena $ zahteva->{smtpcertificate} && '' ne $ zahteva->{smtpcertificate}") {
rezultat = QUERY "izberite certname, geslo iz tblvpncertificate, kjer certid = $ zahteva->{smtpcertificate}"
} ELSE {
rezultat = QUERY "izberite certname, geslo iz tblvpncertificate, kjer je certid = (izberite servicevalue :: int iz tblclientservices, kjer je servicekey = 'smtpcertificate')"
}

$ smtpcertificate = $ rezultat->{izhod}->{certname} [0];
$ certpassword = $ rezultat->{izhod}->{geslo} [0];

}

# Od naslova z imenom
ČE ("določena $ zahteva->{fromaddresswithname} && '' ne $ zahteva->{fromaddresswithname}") {
$ fromaddresswithname = $ zahteva->{fromaddresswithname};
} ELSE {
$ fromaddresswithname = $ OEMNAME . " <" . $ iz naslova . ">";
}

Zgornja koda naredi isto, kot je naredila druga koda, ko se zažene. Inicializira spremenljivke (nekatere od nas ali iz naprave, če niso podane).

Po dodelitvi spremenljivk se izvede naslednji blok kode.

ven = EXECSH "/ bin / cschelper mail_send '$ fromadress' '$ fromaddresswithname' '$ toEmail' '$ toEmail' '$ subject' '$ mailbody' '$ smtpserverhost' '$ smtpserverport' '$ mailusername' '$ mailpassword' '$ mailaction' ' $ smtpsecuritymode '' $ smtpcertificate '' $ certpassword '' 1 '' $ attachmentfile '"

In tu je, izvedba ukaza. Zdaj je klic tukaj EXECSH, ki kliče / bin / sh -c "ARGUMENTI". Z izvajanjem, ki se uporablja z vrednostmi, ki jih nadzorujemo, lahko enostavno dosežemo oddaljeno izvajanje ukazov, vse brez pristnosti.

Čez nekaj mesecev bomo objavili celotno poročilo in Dokazilo o konceptu s primernimi osnutki.

Nadgradnja: Ta raziskava je bila najprej obravnavana na spletnem mestu TechCrunch, več si preberite tukaj.

Brayan Jackson
Brayan Jackson Administrator
Sorry! The Author has not filled his profile.
follow me