
سطح جدیدی از حمله در MS Exchange قسمت 2 – ProxyOracle!
سلام ، این قسمت 2 از سطح جدید MS Exchange Attack Surface است. از آنجا که این مقاله به چندین معماری و مفاهیم سطح حمله در مقاله قبلی اشاره می کند ، می توانید اولین قطعه را در اینجا پیدا کنید:
این بار ، ما ProxyOracle را معرفی می کنیم. در مقایسه با ProxyLogon ، ProxyOracle یک بهره برداری جالب با رویکرد متفاوت است. ProxyOracle با هدایت یک کاربر به بازدید از یک پیوند مخرب ، به مهاجم اجازه می دهد تا رمز عبور کاربر را در قالب متن کامل به طور کامل بازیابی کند. ProxyOracle شامل دو آسیب پذیری است:
بنابراین ProxyOracle کجاست؟ بر اساس معماری CAS که قبلاً معرفی کردیم ، Frontend of CAS ابتدا هویت کاربر را در یک رشته سریال می کند و آن را در سربرگ X-CommonAccessToken
قرار می دهد. سرصفحه در درخواست HTTP سرویس گیرنده ادغام شده و بعداً به Backend ارسال می شود. هنگامی که Backend دریافت می شود ، سربرگ را به هویت اصلی کاربر در Frontend باز می کند.
ما اکنون می دانیم که چگونه Frontend و Backend هویت کاربر را همزمان می کنند. مورد بعدی توضیح این است که چگونه Frontend می داند شما کی هستید و اعتبارنامه خود را پردازش می کند. Outlook Web Access (OWA) از یک رابط فانتزی برای مدیریت کل مکانیسم ورود به سیستم استفاده می کند که به آن احراز هویت مبتنی بر فرم (FBA) می گویند. FBA یک ماژول ویژه IIS است که ProxyModule
را به ارث می برد و مسئول ایجاد تغییر بین اعتبار و کوکی ها قبل از ورود به منطق پروکسی است.
HTTP یک پروتکل بدون حالت است. برای حفظ وضعیت ورود ، FBA نام کاربری و رمز عبور را در کوکی ها ذخیره می کند. هر بار که از OWA دیدن می کنید ، Exchange کوکی ها را تجزیه می کند ، اعتبارنامه را بازیابی می کند و سعی می کند با آن وارد سیستم شوید. اگر ورود به سیستم موفقیت آمیز باشد ، Exchange هویت کاربر شما را در یک رشته سریال می کند ، آن را در سربرگ X-CommonAccessToken
قرار داده و به Backend
HttpProxy FbaModule.cs [19659007] محافظت لغو void OnBeginRequestInternal ( HttpApplication httpApplication ) {
1965909011] 1965909011] 1965909011] 1965909011] موارد [ "AuthType" ] = "FBA" ؛
اگر (! این . [[19659031] HandleFbaAuthFormPost ( httpApplication )) {
سعی کنید {
این . ParseCadataCookies ]) ؛
} گرفتن ( MissingSslCertificateException ) {
NameValueCollection nameValueCollection = جدید eValueCollection () ؛
nameValueCollection . اضافه ( "CafeError" ، ErrorFE . . FEErr 19659012] SSLCertificateProblem . ToString ()) ؛
پرتاب جدید HttpException ( 302 ، ، GetCafeErrorPageRedirectUrl ( httpApplication . زمینه ، nameValueCollection )) ؛
}} [196590890] OnBeginRequestInternal ( httpApplication ) ؛
}
همه کوکی ها رمزگذاری شده اند تا اطمینان حاصل شود حتی اگر مهاجم بتواند درخواست HTTP را ربوده باشد ، او هنوز نتوانسته است درخواست شما را دریافت کند اعتبار در قالب متن ساده FBA از 5 کوکی مخصوص برای تکمیل کل فرآیند رمزگذاری/رمزگذاری استفاده می کند:
cadata
– نام کاربری و رمز عبور رمزگذاری شدهcadataTTL
– Timeest -to -Live timestampcadataKey
– کلید رمزگذاریcadataIV
– IV برای رمزگذاریcadataSig
– امضا برای جلوگیری از دستکاری
منطق رمزگذاری ابتدا دو رشته تصادفی 16 بایت به عنوان IV و KEY برای جلسه جاری ایجاد می کند. سپس نام کاربری و گذرواژه با Base64 رمزگذاری شده ، توسط الگوریتم AES رمزگذاری شده و در کوکی ها به مشتری ارسال می شود. در همین حال ، IV و KEY نیز برای کاربر ارسال می شود. برای جلوگیری از رمزگشایی اعتبار کاربری توسط IV و KEY به طور مستقیم ، Exchange بار دیگر از الگوریتم RSA برای رمزگذاری IV و KEY از طریق کلید خصوصی گواهی SSL قبل از ارسال استفاده می کند!
در اینجا یک شبه کد برای منطق رمزگذاری:
key = GetServerSSLCert (). GetPrivateKey ()
cadataSig = RSA key ). رمزگذاری ( "Fba Rocks!" )
cadataIV = RSA (key [19659011]). رمزگذاری ( GetRandomBytes ( 16 ))
cadataKey = RSA (@[19659011]). رمزگذاری ( GetRandomBytes ( 16 ))
timestamp = GetCurrentTimestamp (19659011] cadataTTL = AES_CBC ( cadataKey [19659011] ، cadataIV ). رمزگذاری (timestamp )
blob = "Basic" +[19659010] ToBase64String ( نام کاربری + ":" + رمز عبور )
cadata = AES_CBC (19659011] ( ] cadataKey ، cadataIV ). رمزگذاری (blob )
صرافی CBC را به عنوان حالت پر کردن خود در نظر می گیرد. اگر با رمزنگاری آشنا هستید ، ممکن است این سال را داشته باشید که آیا حالت CBC در اینجا در برابر حمله Padding Oracle Attack آسیب پذیر است؟ بینگو! در حقیقت ، Padding Oracle Attack هنوز در نرم افزارهای ضروری مانند Exchange در 2021 وجود دارد!
هنگامی که مشکلی در FBA وجود دارد ، Exchange یک کد خطا ضمیمه می کند و درخواست HTTP را به صفحه ورود اصلی هدایت می کند. پس اوراکل کجاست؟ در رمزگشایی کوکی ها ، Exchange از یک استثنا برای تشخیص خطای Padding استفاده می کند و به دلیل استثنا ، برنامه بلافاصله برگشت ، بنابراین شماره کد خطا 0
است ، که به معنی هیچکدام
: [19659185] مکان: /OWA/logon.aspx؟url=…&reason=0
برعکس خطای Padding ، اگر رمزگشایی خوب باشد ، Exchange روند احراز هویت را ادامه می دهد و سعی می کند با نام کاربری و گذرواژه خراب وارد سیستم شود. در این لحظه ، نتیجه باید خراب باشد و شماره کد خطا 2
است که نشان دهنده InvalidCredntials
:
مکان: /OWA/logon.aspx؟url=…&season = 2
نمودار به این شکل است:
با این تفاوت ، ما اکنون یک اوراکل داریم که تشخیص می دهد فرایند رمزگشایی موفقیت آمیز است یا خیر.
HttpProxy FbaModule.cs
خصوصی باطل ParseCadataCookies ( HttpApplication httpApplication )
{
HttpContext 1965901 ]. زمینه ؛
HttpRequest درخواست = زمینه . درخواست ؛
HttpResponse ] = زمینه . پاسخ ؛
رشته متن = درخواست . کوکی ها [ "cadata" [19659011]]. ارزش ؛
رشته text2 = درخواست . کوکی ها [ "cadataKey" ] . ارزش ؛
رشته text3 = درخواست . کوکی ها [ "cadataIV" ]. [19659012] ارزش ؛
رشته text4 = درخواست . کوکی ها [ "cadataSig" ]. ارزش [19659011] ؛
رشته text5 = درخواست . کوکی ها [ "cadataTTL" ]. ارزش ؛
// ...
RSACryptoServiceProvider rsacryptoServiceProvider = ( x509Certificate . PrivateKey 19659008] 19659008] 19659008] 19659008] 19659008] 19659008] 19659008] 19659008] 19659008] 19659908] 19659008] 19659008] 19659908] 19659220] بایت [] آرایه = null ؛
بایت [] array2 = null ؛
بایت [] rgb2 = تبدیل . 196B9064] ( text2 )؛
بایت [] rgb3 = تبدیل . FromBase64String ( text3 [] ] = rsacryptoServiceProvider . رمزگشایی ( rgb3 ، true ) ؛
// ...
با استفاده از [196590315] . آرایه ؛
aesCryptoServiceProvider . IV = آرایه 2 ؛
با استفاده از ( ICryptoTransform cryptoTransform2 = aesCryptoServiceProvider {
بایت [] بایت 2 = null ؛
سعی کنید {
بایت [] [] ] array5 = تبدیل . FromBase64String ( متن ) ؛
bytes2 = cryptoTransform2 TransformFinalBlock ( آرایه 5 ، 0 ، آرایه 5 . طول ]؛
} گرفتن [196590008] CryptographicException ex8 ) {
if ( ExTraceGlobals . VerboseTracer . (19659031] ] 1 )) {
ExTraceGlobals . [19659012] VerboseTracer . TraceDebug < CryptographicException > (( طولانی ) این . GetHashCode [196590 "[FbaModule::ParseCadataCookies] دریافت استثناء رمزنگاری {0} تغییر نویسنده" ، ex8 ) ؛
}
httpApplication . پاسخ . ] AppendToLog ( "& CryptoError = PossibleSSLCertrolloverMismatch" )؛
بازگشت ؛
} گرفتن ( ) {
if ( ExTraceGlobals . VerboseTracer . IsTraceEnabled ( 1 )
ExTraceGlobals . VerboseTracer . TraceDebug < FormatException > (( طولانی این] 19659011]) GetHashCode () ، "[FbaModule::ParseCadataCookies] دریافت FormatException {0} رمزگشایی caData author " ، ex9 ) ؛
}
httpApplication . پاسخ . 19659011og ( "& DecodeError = InvalidCaDataAuthCookie" )؛
بازگشت ؛
}
رشته string = رمزگذاری یونیکد . GetString ( بایت 2 ) ؛
درخواست . سرصفحه ها [ "مجوز" ] ] = string ؛
}
}
}
لازم به ذکر است که از آنجا که IV با کلید خصوصی گواهی SSL رمزگذاری شده است ، نمی توانیم اولین مورد را بازیابی کنیم بلوک متن رمزگذاری شده تا XOR. اما هیچ مشکلی برای ما ایجاد نمی کند زیرا C# داخلی رشته ها را به صورت UTF-16 پردازش می کند ، بنابراین 12 بایت اول متن رمز باید B x00a x00s x00i x00c x00 x00
. با یک کدگذاری Base64 دیگر ، فقط 1.5 بایت اول را در قسمت نام کاربری از دست می دهیم.
(16 − 6 × 2) ÷ 2 × (3/4) = 1.5
در حال حاضر ، یک Padding Oracle که به ما امکان رمزگشایی کوکی های هر کاربر را می دهد. اما ، چگونه می توانیم کوکی های مشتری را دریافت کنیم؟ در اینجا یک آسیب پذیری دیگر برای زنجیر زدن آنها پیدا می کنیم.
XSS to Steal Client Cookies
ما یک XSS (CVE-2021-31195) را در CAS Frontend (بله ، دوباره CAS) کشف می کنیم تا با هم زنجیره شوند ، علت اصلی این XSS نسبتاً آسان است: Exchange قبل از چاپ داده ها را ضد عفونی می کند تا بتوانیم از
برای فرار از فرمت JSON و تزریق کد جاوا اسکریپت دلخواه استفاده کنیم.
https: // exchange/ owa/auth/frowny.aspx
؟ برنامه = مردم
& et = ServerError
& esrc = MasterPage
& te =
& refurl =}}}؛ هشدار (document.domain) //
اما یک س anotherال دیگر پیش می آید: همه کوکی های حساس با پرچم HttpOnly محافظت می شوند ، که باعث می شود ما نتوانیم به کوکی ها با JavaScript دسترسی پیدا کنیم. چه کار باید بکنیم؟
HttpOnly
را دور بزنیم چون می توانیم جاوا اسکریپت دلخواه را در مرورگرها اجرا کنیم ، چرا کوکی SSRF را که در ProxyLogon استفاده می کردیم ، قرار نمی دهیم؟ هنگامی که این کوکی را اضافه می کنیم و مقدار هدف Backend را به عنوان سرور مخرب خود اختصاص می دهیم ، Exchange تبدیل به یک پروکسی بین قربانیان و ما می شود. سپس می توانیم تمام منابع استاتیک HTTP مشتری را در اختیار بگیریم و کوکی های محافظت شده HttpOnly را بدست آوریم! پیوند مخرب نکته قابل توجه این است که XSS در اینجا فقط به ما در سرقت کوکی کمک می کند ، به این معنی که تمام مراحل رمزگشایی نیازی به احراز هویت و تعامل کاربر ندارند. حتی اگر کاربر مرورگر را ببندد ، بر Padding Oracle Attack ما تأثیری نخواهد گذاشت!