CVE-2019-17059: Preauth-RCE i Sophos ‘Cyberoam Explained

Vi har arbejdet hårdt med interne og eksterne sikkerhedsforskere her på TheBestVPN for at afsløre alvorlige fjernudnyttelige smuthuller i SSL VPN'er og firewalls som Cyberoam, Fortigate og Cisco VPN'er. Denne artikel er en teknisk henvendelse til en opdateret kritisk sårbarhed, der påvirker Cyberoam SSL VPN, også kendt som CyberoamOS.

Denne Cyberoam-udnyttelse, kaldet CVE-2019-17059, er en kritisk sårbarhed, der lader angribere få adgang til din Cyberoam-enhed uden at give noget brugernavn eller adgangskode. Dertil kommer, at den tildelte adgang er det højeste niveau (root), hvilket væsentligt giver en angriber ubegrænsede rettigheder på din Cyberoam-enhed.

I de fleste netværksmiljøer bruges Cyberoam-enheder som firewalls og SSL VPN-gateways. Dette giver en potentiel angriber et stærkt fodfæste i et netværk. Det gør det lettere at angribe værter i netværket, og da Cyberoam-enheder normalt er tillid til i de fleste miljøer, giver dette en eftertragtende angriber ekstra fordel.

Ifølge Shodan (en søgemaskine efter internetforbundne enheder) er der mere end 96.000 internetvendte Cyberoam-enheder fra hele verden. De fleste af disse enheder er installeret i virksomheder, universiteter og nogle i verdenskendte banker. Dette fører til, at angrebene har store indvirkninger på disse miljøer.

Arbejdet med Sophos sikkerhedsteam har været en stor glæde, da de handlede hurtigt ved at anerkende og udrulde programrettelser kun få dage efter vores oprindelige rapport til dem. Kudos til dem! (Pun-tilsigtet!)

påvisning af Cyberoam

Og da de fleste af disse enheder er attraktive mål for angribere, gør det fejlene så meget mere kritiske.

CyberoamOS ekstern ikke-godkendt udførelse af rodkommando

CyberoamOS er et modificeret Linux-baseret operativsystem til Cyberoam-enheder. Dette operativsystem har en webbaseret konfigurationsgrænseflade og en SSLVPN-portal.

Webgrænsefladen er opdelt i to hoveddele:

  • En frontend skrevet i Java
  • En backend, der bruger en kombination af C og Perl

Vi dykker ikke dybt ned i internalen i front- eller back-end-koden, hovedsageligt for at spare tid og begrænse mængden af ​​afsløret information. Men vi vil kort diskutere, hvordan fejlen udløses.

Både konfigurations- og SSLVPN-grænseflader har en servlet, der håndterer hovedoperationer. Disse operationer defineres ved hjælp af en parameter, der hedder “mode”.

De fleste af disse er godkendt. Men der er et par ops, som vi kan få adgang til uden godkendelse (som login).

De fejl, vi har fundet, ligger i modulet til e-mail-antivirus / antispam. Anmodningstilstanden for dette slutpunkt (modul, op) er 458.

En ting at bemærke er at opcodes er kortlagt til deres navne i Cyberoam-databasen (intern database Postgres). Ved at slå op 458 kan vi finde ud af, hvad navnet på denne opcode er.

Her er en linje fra SQL-scriptet til databaseinitialisering, der viser navnet opcode 458:

indsæt i tblcrevent (opcode, beskrivelse, tilstand, anmodningstype)
værdier ('RELEASEQUARANTINEMAILFROMMAIL', 'RELEASE QUARANTINE MAIL FRA MAIL', '458', 2);

Opcode-funktionerne gemmes i biblioteket / _conf / csc / cscconf /. Vi afslører ikke hele koden for den sårbare funktion, men vi leverer et par kodestykker, der viser, hvor og hvordan fejlen opstår.

En kode fra Java-frontend, der håndterer opcode 458:

if ((jsonObject.getString ("hdnSender").lige med("") ||
validateEmail (jsonObject.getString ("hdnSender"))) &&
validateEmail (jsonObject.getString ("hdnRecipient")) &&
isSafeFilePath (jsonObject.getString ("hdnFilePath")) && b) {
httpServletResponse.setContentType ("text / html");
CyberoamLogger.debug ("Antivirus / AntiSpam", "CSC Konstant værdi " +
CSCConstants.isCCC);

Som du kan se ovenfor, kontrolleres et par parametre for gyldighed. Hvis de er gyldige værdier, sker følgende:

final EventBean eventByMode = EventBean.getEventByMode (363);
... redacted.
endelig int sendWizardEvent = cscClient.sendWizardEvent (eventByMode, hashMap, sqlReader);

Som vi kan se ovenfor, har vi en ny begivenhedskode (363), der sendes til backend. Den fejl, vi har opdaget, er i koden, der håndterer dette i backend.

Opkoden kaldes sendmail, og for at undgå udnyttelse af denne fejl, redigerer vi det meste af koden fra følgende kode.

Opcode-behandleren til send_mail.

...redacted ...

$ param = $ anmodning->{frigøre};
param = DLOPEN (base64_decode, param)
LOG-applog " Afkod værdier :: $ param \ n"
% requestData = split (/ [&=] /, $ param);
$ mailServerHost = $ requestData {hdnDestDomain};
$ mailFrom = $ requestData {hdnSender};
$ mailTo = $ requestData {hdnRecipient};
$ fil = $ QUARANTINE_PATH."/".$ RequestData {hdnFilePath};

$ Mailfile = $ requestData {hdnFilePath};
$ Validate_email ="falsk";
min $ email_regex = '^ ([\.]? [_ \ - \! \ # \ {\} \ $ \% \ ^ \&\ * \ + \ = \ |?? \ \ '\\\\\\ / a-zA-ZÆØÅ0-9]) * @ ([a-zA-ZÆØÅ0-9] ([-] [a-zA- ZÆØÅ0-9] +) * \) + ([a-zA-ZÆØÅ0-9] {0,6}) $. ';
if ($ requestData {hdnRecipient} = ~ / $ email_regex / && ((defineret $ requestData {hdnSender} && $ requestData {hdnSender} eq '') || $ requestData {hdnSender} = ~ / $ email_regex /) && indeks ($ requestData {hdnFilePath}, '.. /') == -1) {
$ Validate_email ="rigtigt";
}
.... redacted....

Som vi kan se ovenfor, viser pseudo-Perl-koden os, hvordan backend modtager input fra frontend ($ requestData), og hvordan den forsøger at verificere nogle af de parametre, vi sender.

Efter verificeringen, hvis vores parametre er gyldige, udføres følgende kode:

% Mailreq = ("mailaction"=>"$ MAIL_FORWARD","emne"=>"$ strSubject","toEmail"=>"$ mailto","attachmentfile"=>"$ fil","smtpserverhost"=>"$ mailServerHost","FROMADDRESS"=>"$ mailFrom");

out = OPCODE mail_sender json% mailreq

Koden ovenfor indstiller vores anmodningsparametre til mailreq-variabel og kalder mail_sender-funktionen (OPCODE). Vi vil se, hvordan denne opcode udføres, og hvor nøjagtigt RCE sker:

#mailaction 0 = mail_with_var, 1 = mail_forward, 2 = mail_attachment
$ Mailaction = $ anmodning->{Mailaction};
$ Subject = $ anmodning->{emne};
$ Mailbody = '';
$ Attachmentfile = $ anmodning->{Attachmentfile};
$ ToEmail = $ anmodning->{ToEmail};

#mail body
HVIS("defineret $ anmodning->{Mailbody} && '' ne $ anmodning->{Mailbody}") {
$ Mailbody = $ anmodning->{Mailbody};
}
#SMTP-server vært
HVIS("defineret $ anmodning->{Smtpserverhost} && '' ne $ anmodning->{Smtpserverhost}") {
$ Smtpserverhost = $ anmodning->{Smtpserverhost};
}ANDET{
resultat = SPØRGSMÅL "vælg servicevalue fra tblclientservices hvor servicekey = 'MailServer'"
HVIS("defineret $ resultat->{produktion}->{Servicevalue} [0] && ne ne resultat->{produktion}->{Servicevalue} [0]") {
$ Smtpserverhost = $ resultat->{produktion}->{Servicevalue} [0];
}ANDET{
$ Smtpserverhost ="127.0.0.1";
}
}

#SMTP-serverport
HVIS("defineret $ anmodning->{Smtpserverport} && '' ne $ anmodning->{Smtpserverport}") {
$ Smtpserverport = $ anmodning->{Smtpserverport};
}ANDET{
resultat = SPØRGSMÅL "vælg servicevalue fra tblclientservices hvor servicekey = 'MailServerPort'"
HVIS("defineret $ resultat->{produktion}->{Servicevalue} [0] && ne ne resultat->{produktion}->{Servicevalue} [0]") {
$ Smtpserverport = $ resultat->{produktion}->{Servicevalue} [0];
}ANDET{
$ Smtpserverport ="25";
}
}

#SMTP autorisationsflag
$ Smtpauthflag ="0";
HVIS("defineret $ anmodning->{Smtpauthflag} && '' ne $ anmodning->{Smtpauthflag}") {
$ Smtpauthflag = $ anmodning->{Smtpauthflag};
}ANDET{
resultat = SPØRGSMÅL "Vælg servicevalue fra tblclientservices hvor servicekey = 'SMTPAuthenticationFlag'"
HVIS("defineret $ resultat->{produktion}->{Servicevalue} [0] && ne ne resultat->{produktion}->{Servicevalue} [0]") {
$ Smtpauthflag = $ resultat->{produktion}->{Servicevalue} [0];
}
}

HVIS("$ smtpauthflag == 1") {
HVIS("defineret $ anmodning->{Mailusername} && '' ne $ anmodning->{Mailusername}") {

$ Mailusername = $ anmodning->{Mailusername};
$ Mailpassword = $ anmodning->{Mailpassword};

}ANDET{
resultat = SPØRGSMÅL "Vælg servicevalue fra tblclientservices hvor servicekey = 'MailServerUsnavn'"
$ mailusname = $ resultat->{produktion}->{Servicevalue} [0];
resultat = SPØRGSMÅL "Vælg servicevalue fra tblclientservices, hvor servicekey = 'MailServerPassword'"
$ mailpassword = $ resultat->{produktion}->{Servicevalue} [0];
}
}ANDET{

$ mailusnavn = "";
$ mailpassword = "";

}
HVIS("defineret $ anmodning->{FROMADDRESS} && '' ne $ anmodning->{FROMADDRESS}") {
$ FROMADDRESS = $ anmodning->{FROMADDRESS};
}ANDET{
resultat = SPØRGSMÅL "Vælg servicevalue fra tblclientservices hvor servicekey = 'Fra adresse'"
$ fromaddress = $ resultat->{produktion}->{Servicevalue} [0];
}

#Sikkerhedstilstand
HVIS("defineret $ anmodning->{Smtpsecurity} && '' ne $ anmodning->{Smtpsecurity}") {
$ Smtpsecurity = $ anmodning->{Smtpsecurity};
}ANDET{
resultat = SPØRGSMÅL "Vælg servicevalue fra tblclientservices hvor servicekey = 'smtpsecurity'"
$ smtpsecurity = $ resultat->{produktion}->{Servicevalue} [0];
}

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

#SMTP-certifikat

$ smtpcertificate = '';
$ Certpassword = '';

HVIS("$ Smtpsecuritymode! = 0") {
HVIS("defineret $ anmodning->{Smtpcertificate} && '' ne $ anmodning->{Smtpcertificate}") {
resultat = SPØRGSMÅL "vælg certifikatnavn, adgangskode fra tblvpncertificate hvor certid = $ anmodning->{Smtpcertificate}"
}ANDET{
resultat = SPØRGSMÅL "Vælg certnavn, adgangskode fra tblvpncertificate hvor certid = (vælg servicevalue :: int fra tblclientservices hvor servicekey = 'smtpcertificate')"
}

$ smtpcertificate = $ resultat->{produktion}->{Certname} [0];
$ Certpassword = $ resultat->{produktion}->{Password} [0];

}

# Fra adresse med navn
HVIS("defineret $ anmodning->{Fromaddresswithname} && '' ne $ anmodning->{Fromaddresswithname}") {
$ Fromaddresswithname = $ anmodning->{Fromaddresswithname};
}ANDET{
$ fromaddresswithname = $ OEMNAME . " <" . $ FROMADDRESS . ">";
}

Koden ovenfor gør det samme, som den anden opcode gjorde, da den starter. Det initialiserer variabler (nogle fra os eller fra enheden, hvis ikke angivet).

Når variablerne er tildelt, udføres følgende kodeblok.

ud = EXECSH "/ bin / cschelper mail_send '$ fromaddress' '$ fromaddresswithname' '$ toEmail' '$ toEmail' '$ subject' '$ mailbody' '$ smtpserverhost' '$ smtpserverport' '$ mailusname' '$ mailpassword' '$ mailaction' ' $ smtpsecuritymode '' $ smtpcertificate '' $ certifikatord '' 1 '' $ vedhæftningsfil '"

Og der er det, udførelsen af ​​kommandoen. Nu er opkaldet her EXECSH, der kalder / bin / sh -c “ARGUMENTS”. Når udførelsen sker ved hjælp af værdier, vi kontrollerer, kan vi let opnå udførelse af fjernkommando, alt uden godkendelse.

Vi udsender en komplet rapport og beviset for koncept med passende konturer om et par måneder.

Opdatering: Denne forskning blev dækket først på TechCrunch, læs mere her.

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