CVE-2019-17059: Izskaidrots Preauth-RCE Sophos Cyberoam

Mēs šeit TheBestVPN strādājam ar iekšējās un ārējās drošības pētniekiem, lai atklātu nopietnas attālināti izmantojamas nepilnības SSL VPN un ugunsmūros, piemēram, Cyberoam, Fortigate un Cisco VPN. Šis raksts ir tehniska informācija par ielāpu kritisku ievainojamību, kas ietekmē Cyberoam SSL VPN, kas pazīstams arī kā CyberoamOS.

Šis Cyberoam lietojums, saukts par CVE-2019-17059, ir kritiska ievainojamība, kas ļauj uzbrucējiem piekļūt jūsu Cyberoam ierīcei, nenodrošinot nevienu lietotājvārdu vai paroli. Turklāt piešķirtajai piekļuvei ir visaugstākais līmenis (sakne), kas būtībā uzbrucējam piešķir neierobežotas tiesības jūsu Cyberoam ierīcē..

Lielākajā daļā tīkla vides Cyberoam ierīces tiek izmantotas kā ugunsmūri un SSL VPN vārtejas. Tas potenciālajam uzbrucējam dod spēcīgu atbalstu tīklā. Tas ļauj vieglāk uzbrukt resursdatoriem tīklā, un, tā kā Cyberoam ierīcēm parasti uzticas lielākajā daļā vides, tas potenciālajam uzbrucējam piešķir papildu priekšrocības.

Pēc Shodan (meklētājprogramma ar internetu savienotu ierīču) ziņām, visā pasaulē ir vairāk nekā 96 000 Cyberoam ierīču, kas vērstas uz internetu. Lielākā daļa šo ierīču ir uzstādītas uzņēmumos, universitātēs un dažas - pasaules slavenās bankās. Tas noved pie tā, ka uzbrukumiem ir milzīga ietekme uz šo vidi.

Darbs ar Sophos drošības komandu bija liels prieks, jo viņi rīkojās ātri, atzīstot un izlaižot ielāpus tikai dažas dienas pēc mūsu sākotnējā ziņojuma viņiem. Kudos viņiem! (pun-paredzēta!)


atklājot Cyberoam

Un tā kā vairums no šiem subjektiem ir pievilcīgi mērķi uzbrucējiem, tas kļūdas padara vēl kritiskāku.

CyberoamOS attāla neautentificēta saknes komandu izpilde

CyberoamOS ir pārveidota operētājsistēma uz Linux bāzes, kas paredzēta Cyberoam ierīcēm. Šai operētājsistēmai ir tīmekļa konfigurācijas saskarne un SSLVPN portāls.

Tīmekļa saskarne ir sadalīta divās galvenajās daļās:

  • Java valodā rakstīta priekšpuse
  • Pamatprogramma, kurā tiek izmantota C un Perl kombinācija

Mēs neiedziļināsimies priekšējā vai aizmugurējā koda iekšējos punktos, galvenokārt, lai ietaupītu laiku un ierobežotu atklātās informācijas daudzumu. Bet īsi apspriedīsim, kā kļūda tiek iedarbināta.

Gan konfigurācijas, gan SSLVPN saskarnēm ir serversīklietotne, kas apstrādā galvenās operācijas. Šīs operācijas tiek definētas, izmantojot parametru ar nosaukumu “mode”.

Lielākā daļa no tām ir autentificētas. Bet ir dažas iespējas, kurām mēs varam piekļūt bez autentifikācijas (piemēram, pieteikšanās).

Mūsu atrastās kļūdas atrodas e-pasta antivīrusu / pretspam modulī. Pieprasījuma režīms šim parametram (modulis, op) ir 458.

Viena lieta, kas jāņem vērā, ir tas, ka opcodes tiek kartēti pēc to nosaukumiem Cyberoam datu bāzē (iekšējā datu bāze Postgres). Uzmeklējot 458. numuru, mēs varam uzzināt, kāds ir šī opkoda nosaukums.

Šeit ir rinda no datu bāzes inicializācijas SQL skripta, kurā norādīts nosaukums opcode 458:

ievietot tblcrevent (opcija, apraksts, režīms, pieprasījuma tips)
vērtības ('RELEASEQUARANTINEMAILFROMMAIL', 'RELEASE QUARANTINE MAIL FROM PASTS', '458', 2);

Opcode funkcijas tiek glabātas direktorijā / _conf / csc / cscconf /. Mēs neatklājam visu neaizsargāto funkciju kodu, bet mēs sniegsim dažus fragmentus, kas parādīs, kur un kā rodas kļūda.

Kods no Java interfeisa, kas apstrādā opciju 458:

if ((jsonObject.getString ("hdnSender") .equals ("") ||
validateEmail (jsonObject.getString ("hdnSender"))) &&
validateEmail (jsonObject.getString ("hdnRecipient")) &&
isSafeFilePath (jsonObject.getString ("hdnFilePath")) && b) {
httpServletResponse.setContentType ("teksts / html");
CyberoamLogger.debug ("Antivīruss / AntiSpam", "CSC nemainīgā vērtība " +
CSCConstants.isCCC);

Kā redzat iepriekš, dažu parametru derīgums tiek pārbaudīts. Ja tās ir derīgas vērtības, notiek šādi:

final EventBean eventByMode = EventBean.getEventByMode (363);
... rediģēts.
final int sendWizardEvent = cscClient.sendWizardEvent (eventByMode, hashMap, sqlReader);

Kā redzam iepriekš, mums ir jauns notikuma kods (363), kas tiks nosūtīts uz aizmugures versiju. Kļūda, ko esam atklājuši, ir kodā, kas ar to apstrādā aizmugures versijā.

Opcija ir nosaukta sendmail, un, lai izvairītos no šīs kļūdas izmantošanas, lielāko daļu koda mēs rediģēsim no šī koda.

Send_mail opciju koda apstrādātājs.

...rediģēts ...

$ param = $ pieprasījums->{atbrīvot};
param = DLOPEN (base64_decode, param)
LOG applog " Atšifrēt vērtības :: $ param \ n"
% requestData = split (/ [&=] /, $ param);
$ mailServerHost = $ requestData {hdnDestDomain};
$ mailFrom = $ requestData {hdnSender};
$ mailTo = $ requestData {hdnRecipient};
$ fails = $ QUARANTINE_PATH."/".$ requestData {hdnFilePath};

$ mailfile = $ requestData {hdnFilePath};
$ validte_email ="viltus";
my $ 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 / && ((noteikts $ requestData {hdnSender} && $ requestData {hdnSender} ek. '') || $ requestData {hdnSender} = ~ / $ email_regex /) && indekss ($ requestData {hdnFilePath}, '.. /') == -1) {
$ validte_email ="taisnība";
}
.... rediģēts....

Kā mēs redzam iepriekš, pseido-Perl kods parāda, kā aizmugures programma saņem ievadi no priekšējās platformas ($ requestData) un kā tā mēģina pārbaudīt dažus no mūsu nosūtītajiem parametriem..

Pēc verifikācijas, ja mūsu parametri ir derīgi, tiek izpildīts šāds kods:

% mailreq = ("mailaction"=>"MAIL_FORWARD","priekšmets"=>"$ strSubject","uz e-pastu"=>"$ mailTo","pielikumsfails"=>"$ fails","smtpserverhost"=>"$ mailServerHost","no adreses"=>"$ pastsNo");

out = OPCODE mail_sender json% mailreq

Iepriekš norādītais kods nosaka mūsu pieprasījuma parametrus mainīgajā mailreq un izsauc funkciju mail_sender (OPCODE). Mēs redzēsim, kā tiek izpildīts šis opkods un kur tieši notiek RCE:

#mailaction 0 = mail_with_var, 1 = mail_forward, 2 = mail_attachment
$ mailaction = $ pieprasījums->{mailaction};
$ subjekts = $ pieprasījums->{subjekts};
$ mailbody = '';
$ pielikumsfile = $ pieprasījums->{pielikumsfails};
$ toEmail = $ pieprasījums->{uz e-pastu};

# pasta korpuss
IF ("noteikts $ pieprasījums->{mailbody} && '' ne $ pieprasījums->{mailbody}") {
$ mailbody = $ pieprasījums->{mailbody};
}
#SMTP servera resursdators
IF ("noteikts $ pieprasījums->{smtpserverhost} && '' ne $ pieprasījums->{smtpserverhost}") {
$ smtpserverhost = $ pieprasījums->{smtpserverhost};
} ELSE {
rezultāts = QUERY "atlasiet pakalpojuma vērtību no tblclientservices, kur servicekey = 'MailServer'"
IF ("noteikts $ rezultāts->{output}->{servicevalue} [0] && '' nav $ rezultāts->{output}->{servicevalue} [0]") {
$ smtpserverhost = $ rezultāts->{output}->{servisa vērtība} [0];
} ELSE {
$ smtpserverhost ="127.0.0.1";
}
}

#SMTP servera ports
IF ("noteikts $ pieprasījums->{smtpserverport} && '' ne $ pieprasījums->{smtpserverport}") {
$ smtpserverport = $ pieprasījums->{smtpserverport};
} ELSE {
rezultāts = QUERY "atlasiet servisa vērtību no tblclientservices, kur servicekey = 'MailServerPort'"
IF ("noteikts $ rezultāts->{output}->{servicevalue} [0] && '' nav $ rezultāts->{output}->{servicevalue} [0]") {
$ smtpserverport = $ rezultāts->{output}->{servisa vērtība} [0];
} ELSE {
$ smtpserverport ="25";
}
}

#SMTP autentifikācijas karogs
$ smtpauthflag ="0";
IF ("noteikts $ pieprasījums->{smtpauthflag} && '' ne $ pieprasījums->{smtpauthflag}") {
$ smtpauthflag = $ pieprasījums->{smtpauthflag};
} ELSE {
rezultāts = QUERY "atlasiet servisa vērtību no tblclientservices, kur servicekey = 'SMTPAuthenticationFlag'"
IF ("noteikts $ rezultāts->{output}->{servicevalue} [0] && '' nav $ rezultāts->{output}->{servicevalue} [0]") {
$ smtpauthflag = $ rezultāts->{output}->{servisa vērtība} [0];
}
}

IF ("$ smtpauthflag == 1") {
IF ("noteikts $ pieprasījums->{mailusername} && '' ne $ pieprasījums->{mailusername}") {

$ mailusername = $ pieprasījums->{mailusername};
$ mailpassword = $ pieprasījums->{pasta parole};

} ELSE {
rezultāts = QUERY "atlasiet pakalpojuma vērtību no tblclientservices, kur servicekey = 'MailServerUsername'"
$ mailusername = $ rezultāts->{output}->{servisa vērtība} [0];
rezultāts = QUERY "atlasiet servicevalue no tblclientservices, kur servicekey = 'MailServerPassword'"
$ mailpassword = $ rezultāts->{output}->{servisa vērtība} [0];
}
} ELSE {

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

}
IF ("noteikts $ pieprasījums->{fromaddress} && '' ne $ pieprasījums->{fromaddress}") {
$ fromaddress = $ pieprasījums->{no adreses};
} ELSE {
rezultāts = QUERY "izvēlieties pakalpojumu vērtību no tblclientservices, kur servicekey = 'FromAddress'"
$ fromaddress = $ rezultāts->{output}->{servisa vērtība} [0];
}

#Drošības režīms
IF ("noteikts $ pieprasījums->{smtpsecurity} && '' ne $ pieprasījums->{smtpsecurity}") {
$ smtpsecurity = $ pieprasījums->{smtpsecurity};
} ELSE {
rezultāts = QUERY "izvēlieties servisa vērtību no tblclientservices, kur servicekey = 'smtpsecurity'"
$ smtpsecurity = $ rezultāts->{output}->{servisa vērtība} [0];
}

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

#SMTP sertifikāts

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

IF ("$ smtpsecuritymode! = 0") {
IF ("noteikts $ pieprasījums->{smtpcertificate} && '' ne $ pieprasījums->{smtpcertificate}") {
rezultāts = QUERY "izvēlieties sertifikātu, paroli no tblvpncertificate, kur pieprasīt sertifikātu = $->{smtpcertificate}"
} ELSE {
rezultāts = QUERY "izvēlieties sertifikātu, paroli no tblvpncertificate, kur certid = (atlasiet servicevalue :: int no tblclientservices, kur servicekey = 'smtpcertificate')"
}

$ smtpcertificate = $ rezultāts->{output}->{sertvārds} [0];
$ certpassword = $ rezultāts->{output}->{parole} [0];

}

#No adrese ar vārdu
IF ("noteikts $ pieprasījums->{fromaddresswithname} && '' ne $ pieprasījums->{fromaddresswithname}") {
$ fromaddresswithname = $ pieprasījums->{fromaddresswithname};
} ELSE {
$ fromaddresswithname = $ OEMNAME . " <" . $ no adreses . ">";
}

Iepriekš norādītais kods dara to pašu, ko otrs opods, kad tas startēja. Tas inicializē mainīgos (dažus no mums vai no ierīces, ja tie nav norādīti).

Pēc mainīgo piešķiršanas tiek izpildīts šāds koda bloks.

ārā = EXECSH "/ bin / cschelper mail_send '$ fromaddress' '$ fromaddresswithname' '$ toEmail' '$ toEmail' '$ subjekts' '$ mailbody' '$ smtpserverhost' '$ smtpserverport' '$ mailusername' '$ mailpassword' '$ mailaction' ' $ smtpsecuritymode '' $ smtpcertificate '' $ certpassword '' 1 '' $ pielikumufails '"

Un tur tas ir, komandu izpilde. Tagad zvans ir EXECSH, kurš izsauc / bin / sh -c “ARGUMENTS”. Tā kā izpilde notiek, izmantojot mūsu kontrolētās vērtības, mēs varam viegli panākt attālinātu komandu izpildi, bez autentifikācijas.

Pēc dažiem mēnešiem mēs izlaidīsim pilnu ziņojumu un koncepcijas apliecinājumu ar atbilstošiem izklāstu.

Atjaunināt: Šis pētījums vispirms tika apskatīts vietnē TechCrunch, lasiet vairāk šeit.

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