CVE-2019-17059: הסביר את Preauth-RCE בסייברעם של סופוס

עבדנו קשה עם חוקרי אבטחה פנימיים וחיצוניים כאן ב- TheBestVPN בכדי לחשוף פרצות רציניות ניתנות לניצול מרחוק ב- VPLs SSL ובחומות אש כמו Cyberoam, Fortigate ו- VPNs Cisco. מאמר זה הנו מידע טכני אודות פגיעות קריטיות מתוקנות המשפיעות על Cyberoam SSL VPN הידוע גם בשם CyberoamOS.

ניצול Cyberoam זה, המכונה CVE-2019-17059 הוא פגיעות קריטית המאפשרת לתוקפים לגשת למכשיר Cyberoam שלך מבלי לספק שם משתמש או סיסמא. נוסף על כך, הגישה שניתנה היא הרמה הגבוהה ביותר (שורש), מה שבעיקר מעניק לתוקף זכויות בלתי מוגבלות במכשיר ה- Cyberoam שלך..

ברוב סביבות הרשת, מכשירי Cyberoam משמשים חומות אש ושערים של SSL VPN. זה נותן לתוקף פוטנציאלי דריסת רגל חזקה ברשת. זה מקל על התקיפה של מארחים ברשת, ומאחר שמכשירי Cyberoam בדרך כלל מהימנים ברוב הסביבות, הדבר מעניק יתרון נוסף לתוקף נחוץ..

לפי שודן (מנוע חיפוש למכשירים המחוברים לאינטרנט), ישנם יותר מ- 96,000 מכשירי Cyberoam הפונים לאינטרנט מכל רחבי העולם. רוב המכשירים הללו מותקנים בארגונים, אוניברסיטאות וחלקם בבנקים בעלי שם עולמי. זה מוביל לכך שההתקפות משפיעות רבות על סביבות אלה.

העבודה עם צוות האבטחה של סופוס הייתה תענוג גדול מאחר שהם פעלו במהירות באמצעות הכרה והוצאת טלאים רק מספר ימים לאחר הדיווח הראשוני שלנו אליהם. קודוס להם! (משחק מילים מיועד!)


גילוי Cyberoam

ומכיוון שרוב הגורמים הללו הם יעדים אטרקטיביים עבור התוקפים, זה הופך את הבאגים לקריטיים יותר.

ביצוע פיקוד שורש לא מאומת מרחוק CyberoamOS

CyberoamOS היא מערכת הפעלה מבוססת Linux המותקנת למכשירי Cyberoam. מערכת הפעלה זו כוללת ממשק תצורה מבוסס אינטרנט ופורטל SSLVPN.

ממשק האינטרנט מחולק לשני חלקים עיקריים:

  • חזית כתובה בג'אווה
  • תומך שמשתמש בשילוב של C ופרל

לא נצלול לעומק הפנימיות של הקוד הקדמי או האחורי, בעיקר כדי לחסוך זמן ולהגביל את כמות המידע שנחשף. אך נדון בקצרה כיצד מופעל הבאג.

גם לממשקי התצורה וגם לממשקי SSLVPN יש סרבלט שמטפל בפעולות העיקריות. פעולות אלה מוגדרות באמצעות פרמטר בשם "מצב".

רוב אלה מאומתים. אבל יש כמה אופציות שאליהן אנו יכולים לגשת ללא אימות (כמו התחברות).

הבאגים שמצאנו נמצאים במודול האנטי-וירוס / אנטי-ספאם בדוא"ל. מצב הבקשה לנקודת קצה זו (מודול, op) הוא 458.

דבר אחד שיש לשים לב הוא שהמיקודים האוטומטיים ממופים לשמותיהם במסד הנתונים Cyberoam (מסד נתונים פנימי Postgres). על ידי הסתכלות למעלה 458, אנו יכולים לגלות מה שמו של קוד האפוד הזה.

להלן שורה מתוך סקריפט SQL לאתחול בסיס הנתונים המציג את השם opcode 458:

הכנס ל- tblcrevent (קוד קוד, תיאור, מצב, סוג בקשה)
ערכים ('RELEASEQUARANTINEMAILFROMMAIL', 'RELEASE QUARANTINE MAIL FRA MAIL', '458', 2);

פונקציות ה- opcode מאוחסנות בספרייה / _conf / csc / cscconf /. לא נחשוף את כל הקוד של הפונקציה הפגיעה, אך אנו נספק כמה קטעים המראים היכן ואיך הבאג מתרחש.

קוד מקדמת Java המטפל בקודקוד 458:

אם ((jsonObject.getString ("hdnSender").שווים("") ||
validateEmail (jsonObject.getString ("hdnSender"))) &&
validateEmail (jsonObject.getString ("hdnRecipient")) &&
isSafeFilePath (jsonObject.getString ("hdnFilePath")) && ב) {
httpServletResponse.setContentType ("טקסט / HTML");
CyberoamLogger.debug ("אנטי-וירוס / אנטי-ספאם", "ערך קבוע של CSC " +
CSCConstants.isCCC);

כפי שתוכלו לראות לעיל, בודקים תקפות של כמה פרמטרים. אם הם ערכים תקפים, הדבר קורה:

eventBean eventByMode אחרון = EventBean.getEventByMode (363);
... בוצע מחדש.
sent int sendWizardEvent = cscClient.sendWizardEvent (eventByMode, hashMap, sqlReader);

כפי שניתן לראות לעיל, יש לנו קוד אירוע חדש (363) שיישלח לאחור. הבאג שגילינו נמצא בקוד המטפל בזה בנדנד.

לקוד ה- opode קוראים sendmail, וכדי להימנע מניצול באג זה, אנו מבצעים מחדש של רוב הקוד מהקוד הבא..

מטפל ה- opcode עבור send_mail.

...בוצע מחדש ...

$ param = $ בקשה->{שחרור};
param = DLOPEN (base64_decode, param)
יומן לוג " פענח ערכים :: $ param \ n"
% requestData = פיצול (/ [&=] /, $ param);
$ mailServerHost = $ requestData {hdnDestDomain};
$ mailFrom = $ requestData {hdnSender};
$ mailTo = $ requestData {hdnRecipient};
קובץ $ = $ QUARANTINE_PATH."/".$ requestData {hdnFilePath};

$ mailfile = $ requestData {hdnFilePath};
$ validate_email ="שקר";
$ 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 / && ((מוגדר $ requestData {hdnSender} && $ requestData {hdnSender} eq '') || $ requestData {hdnSender} = ~ / $ email_regex /) && אינדקס ($ requestData {hdnFilePath}, '.. /') == -1) {
$ validate_email ="נכון";
}
.... בוצע מחדש....

כפי שניתן לראות לעיל, קוד הפסאודו-פרל מראה לנו כיצד ה- backend מקבל קלט מהחזית ($ requestData) וכיצד הוא מנסה לאמת כמה מהפרמטרים שאנו שולחים.

לאחר האימות, אם הפרמטרים שלנו תקפים, הקוד הבא יבוצע:

% mailreq = ("פעולת דואר"=>"$ MAIL_FORWARD","נושא"=>"$ strSubject","לדואר אלקטרוני"=>"$ mailTo","קובץ מצורף"=>"קובץ $","smtpserverhost"=>"$ mailServerHost","מכתובת"=>"$ mailFrom");

out = OPCODE mail_sender json% mailreq

הקוד שלמעלה מגדיר את פרמטרי הבקשה שלנו למשתנה mailreq ומתקשר לפונקציית mail_sender (OPCODE). נראה כיצד מבוצע קוד האופן הזה ואיפה בדיוק קורה ה- RCE:

#mailaction 0 = mail_with_var, 1 = mail_forward, 2 = mail_attachment
$ mailaction = $ בקשה->{mailaction};
נושא נושא = $ בקשה->{נושא};
$ mailbody = '';
$ attachmentfile = $ בקשה->{קובץ מצורף};
$ toEmail = $ בקשה->{toEmail};

# גופה בדואר
אם("הגדרת בקשת $->{mailbody} && בקשת ne $->{mailbody}") {
$ mailbody = $ בקשה->{mailbody};
}
#SMTP שרת מארח
אם("הגדרת בקשת $->{smtpserverhost} && בקשת ne $->{smtpserverhost}") {
$ smtpserverhost = $ בקשה->{smtpserverhost};
} ELSE {
תוצאה = QUERY "בחר שירות שירות מ- tblclientservices שבהם servicekey = 'MailServer'"
אם("תוצאה מוגדרת $->{פלט}->{servicevalue} [0] && תוצאה ne $->{פלט}->{servicevalue} [0]") {
$ smtpserverhost = $ תוצאה->{פלט}->{servicevalue} [0];
} ELSE {
$ smtpserverhost ="127.0.0.1";
}
}

# יציאת שרת SSMTP
אם("הגדרת בקשת $->{smtpserverport} && בקשת ne $->{smtpserverport}") {
$ smtpserverport = $ בקשה->{smtpserverport};
} ELSE {
תוצאה = QUERY "בחר שירות שירות מ- tblclientservices שבהם servicekey = 'MailServerPort'"
אם("תוצאה מוגדרת $->{פלט}->{servicevalue} [0] && תוצאה ne $->{פלט}->{servicevalue} [0]") {
$ smtpserverport = $ תוצאה->{פלט}->{servicevalue} [0];
} ELSE {
$ smtpserverport ="25";
}
}

#SMTP דגל הרשאה
$ smtpauthflag ="0";
אם("הגדרת בקשת $->{smtpauthflag} && בקשת ne $->{smtpauthflag}") {
$ smtpauthflag = $ בקשה->{smtpauthflag};
} ELSE {
תוצאה = QUERY "בחר שירות שירות מ- tblclientservices שבהם servicekey = 'SMTPAuthenticationFlag'"
אם("תוצאה מוגדרת $->{פלט}->{servicevalue} [0] && תוצאה ne $->{פלט}->{servicevalue} [0]") {
$ smtpauthflag = $ תוצאה->{פלט}->{servicevalue} [0];
}
}

אם("$ smtpauthflag == 1") {
אם("הגדרת בקשת $->{mailusname} && בקשת ne $->{mailusname}") {

$ mailusname = $ בקשה->{mailusname};
$ mailpassword = $ בקשה->{סיסמת דואר};

} ELSE {
תוצאה = QUERY "בחר הערכת שירות מ- tblclientservices שבהם servicekey = 'MailServerUsername'"
$ mailusname = $ תוצאה->{פלט}->{servicevalue} [0];
תוצאה = QUERY "בחר שירות שירות מ- tblclientservices שבהם servicekey = 'MailServerPassword'"
$ mailpassword = $ תוצאה->{פלט}->{servicevalue} [0];
}
} ELSE {

$ mailusername = "";
סיסמת דואר $ "";

}
אם("הגדרת בקשת $->{מכתובת} && בקשת ne $->{מכתובת}") {
$ fromaddress = $ בקשה->{מכתובת};
} ELSE {
תוצאה = QUERY "בחר שירות שירות מ- tblclientservices שבהם servicekey = 'מאת כתובת'"
$ fromaddress = $ תוצאה->{פלט}->{servicevalue} [0];
}

#מצב ביטחון
אם("הגדרת בקשת $->{smtpsecurity} && בקשת ne $->{smtpsecurity}") {
$ smtpsecurity = $ בקשה->{smtpsecurity};
} ELSE {
תוצאה = QUERY "בחרו בשירות השירות החל מ- tblclientservices שבהם servicekey = 'smtpsecurity'"
$ smtpsecurity = $ תוצאה->{פלט}->{servicevalue} [0];
}

$ smtpsecuritymode = 0;
אם("$ smtpsecurity משווה 'STARTTLS'") {
$ smtpsecuritymode = 1;
} ELSE IF ("$ smtpsecurity שווה ערך 'SSL / TLS'") {
$ smtpsecuritymode = 2;
}

#SMTP תעודה

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

אם("$ smtpsecuritymode! = 0") {
אם("הגדרת בקשת $->{smtpcertificate} && בקשת ne $->{smtpcertificate}") {
תוצאה = QUERY "בחר certname, סיסמא מתוך tblvpncertificate היכן certid = $ בקשה->{smtpcertificate}"
} ELSE {
תוצאה = QUERY "בחר certname = סיסמה מ- tblvpncertificate איפה certid = (בחר servicevalue :: int מ- tblclientservices שבהם servicekey = 'smtpcertificate')"
}

$ smtpcertificate = $ תוצאה->{פלט}->{certname} [0];
$ certpassword = $ תוצאה->{פלט}->{סיסמה} [0];

}

# כתובת עם שם
אם("הגדרת בקשת $->{fromaddresswithname} && בקשת ne $->{fromaddresswithname}") {
$ fromaddresswithname = $ בקשה->{fromaddresswithname};
} ELSE {
$ fromaddresswithname = $ OEMNAME . " <" . כתף $ . ">";
}

הקוד שלמעלה עושה את אותו הדבר שקודם הקוד האחר עשה כאשר הוא מתחיל. זה מאתחל משתנים (חלקם מאיתנו או מהמכשיר אם לא צוין).

לאחר הקצאת המשתנים, מבוצעת חסימת הקוד הבאה.

out = EXECSH "/ bin / cschelper mail_send '$ fromaddress' '$ fromaddresswithname' '$ toEmail' '$ toEmail' '$ נושא' '$ mailbody' '$ smtpserverhost' '$ smtpserverport' '$ mailusername' '$ mailpassword' '$ mailaction' ' $ smtpsecuritymode '' $ smtpcertificate '' $ certpassword '' 1 '' $ attachmentfile '"

והנה זה, ביצוע הפקודה. עכשיו השיחה כאן היא EXECSH שקוראת / bin / sh-c "ARGUMENTS". כאשר הביצוע מתרחש באמצעות ערכים שאנו שולטים בהם, אנו יכולים להשיג ביצוע פקודות מרחוק בקלות, והכל ללא אימות.

אנו נפרסם דו"ח מלא והוכחת הקונספט עם מתארים נאותים בעוד מספר חודשים.

עדכון: מחקר זה סקר תחילה ב- TechCrunch, קרא עוד כאן.

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