Facebook Oyun Odasına Saldırgan Tersine Mühendislik Uygulamak


Geçen yılın sonlarında, canlı bilgisayar korsanlığı bölümü içeren, yalnızca davetiyeyle katılılabilen bir uygulama güvenliği konferansı olan Facebook’un Bountycon etkinliğine davet edildim. Katılımcılar herhangi bir Facebook varlığına ilişkin güvenlik açıklarını bildirebilse de, Facebook bizi Facebook Gaming’e odaklanmaya davet etti. Daha önce Facebook’un varlıklarını test ettiğimden bunun zorlu bir mücadele olacağını biliyordum. Güvenlik kontrolleri yıllar geçtikçe daha da zorlaştı; siteler arası komut dosyası çalıştırma gibi basit güvenlik açıklarına bile ulaşmak zor; bu yüzden bunlara çok fazla para ödüyorlar. Bu nedenle üst düzey beyaz şapkalı bilgisayar korsanları, Facebook’a Orange Tsai’nin iyi bilinen MobileIron MDM açıkları gibi üçüncü taraf yazılım açısından yaklaşma eğilimindedir.

Sınırlı zamanım göz önüne alındığında (ayrıca idari bir sorun nedeniyle geç başladım), tam ölçekli güvenlik açığı araştırmalarından uzak durmaya karar verdim ve Facebook Gaming’in erişim kontrollerinin basit denetimlerine odaklandım. Ancak beklendiği gibi hem mobil hem de web uygulamaları iyi korunuyordu. Biraz araştırdıktan sonra, Facebook oyunlarını oynamak için Windows’ta yerleşik bir istemci olan Facebook Gameroom’a rastladım. Yerel bir masaüstü uygulamasına saldırgan tersine mühendislik uygulama konusunda aydınlatıcı bir yolculuğa çıktım.

Facebook Gameroom’u duymadıysanız muhtemelen yalnız değilsiniz. Kasım 2016’da piyasaya sürülen Gameroom, Unity, Flash ve son zamanlarda HTML5 oyunlarını destekleyen bir Steam rakibi olarak lanse edildi. Ancak son yıllarda Facebook, özellikle yayın akışının artmasıyla birlikte dikkatini mobil ve web platformlarına çevirdi. Aslında Gameroom’un bu yıl haziran ayında hizmet dışı bırakılması planlanıyor. Şans eseri benim için olay sırasında hala hayattaydı ve tekme atıyordu.

Facebook Oyun Odası

İlk fark ettiğim şey Gameroom’un kurulum için herhangi bir yükseltilmiş izne ihtiyaç duymamasıydı. Minimal bir yükleyicinin, monolitik bir yükleyici yerine web’den ek dosyalar çektiği aşamalı bir yükleyici gibi görünüyordu. Aslında, kurulum dizinini hızlı bir şekilde buldum. C:\Users\\AppData\Local\Facebook\Gamesçünkü kullanıcı düzeyindeki uygulamaların çoğu C:\Users\\AppData dosya. Klasörde çok sayıda şey vardı .dll dosyaların yanı sıra birkaç yürütülebilir dosya. Gözüme çarpan birkaç şey vardı:

  1. Gameroom kendi paketlenmiş 7zip çalıştırılabilir dosyasıyla birlikte geldi (7z.exe Ve 7z.dll), muhtemelen modası geçmiş ve savunmasızdı.
  2. Oyun odası kullanıcı oturumu verilerini depoladı Cookies Saldırganlar için cazip bir hedef sunan SQLite veritabanı.
  3. Oyun odası CefSharp kütüphanesini içeriyordu (CefSharp.dll), daha fazla araştırma sonrasında bunun C# için yerleşik bir Chromium tabanlı tarayıcı olduğu ortaya çıktı.

Üçüncü nokta bana Gameroom’un .NET çerçevesinde yazıldığını hatırlattı. .NET çerçevesi, programların makine kodu yerine Ortak Dil Çalışma Zamanı uygulaması sanal makinesinde çalışabilen Ortak Ara Dil (CIL) kodunda derlenmesine olanak tanır. Bunun, .NET uygulamalarının daha fazla birlikte çalışabilirliği ve taşınabilirliği de dahil olmak üzere çeşitli faydaları vardır. Ancak bu uygulamaları, saf makine kodu yerine CIL olarak derlendiklerinden kaynak koda yakın koda dönüştürmek de çok daha kolaydır.

.NET derlemeleri için DNSpy fiili standarttır. Tersine mühendisler, DNSpy ile .NET uygulamalarının hatalarını kolayca ayıklayabilir ve analiz edebilir, bunlara canlı yama uygulamak da dahildir. patladım FacebookGameroom.exe DNSpy’a girdim ve işe koyuldum.

Güvenli olmayan seri durumdan çıkarma gibi savunmasız veya tehlikeli işlevleri arayarak başladım. Saldırgan Güvenlik Gelişmiş Web Saldırıları ve Suistimal kursunu tamamladıysanız, seri durumdan çıkarma saldırılarına çok yakından aşina olursunuz. Burada onlar hakkında ayrıntıya girmeyeceğim, ancak bunun veri türlerini kolayca taşınabilir formatlara dönüştürmeyi içerdiğini ve bunun kötü kullanıldığında kritik güvenlik açıklarına yol açabileceğini bilin. Örneğin Microsoft, kod kalitesi analizcisinde BinaryFormatter’ın kullanılmasına karşı oldukça sert bir uyarıda bulunuyor BinaryFormatter is insecure and can't be made secure.

Ne yazık ki, “Serialize” dizesini aradığımda BinaryFormatter ortaya çıktı.

İkili Biçimlendirici

Ancak güvenlik açığı bulunan kod yolunu bulmam gerekiyordu. Arama sonucuna sağ tıkladım, “Analiz Et”i seçtim, ardından Gameroom’un kullandığı yeri bulmak için “Kullanan” zincirini aradım. BinaryFormatter.Deserialize.

Zincir Tarafından Kullanılan

Sonunda bu beni şu noktaya götürdü: System.Configuration.ApplicationSettingsBase.GetPreviousVersion(string) Ve System.Configuration.ApplicationSettingsBase.GetPropertyValue(string) işlevler. Gameroom, başlangıçta uygulama ayarlarını geri almak için seri durumdan çıkarma işlevini kullandı – peki nereden? Kurulum klasörüne tekrar baktığımda şunu buldum: fbgames.settingsbunun serileştirilmiş bir blob olduğu ortaya çıktı. Dolayısıyla, bu dosyaya kötü amaçlı bir seri durumdan çıkarma verisi enjekte edersem, kod yürütmeyi elde edebilirim. Ancak ondan önce seri durumdan çıkarma aygıtı bulmam gerekiyordu. Bilinen seri durumdan çıkarma araçlarının listesine dayanarak biraz daha arama yaptığımda Gameroom’un şunu kullandığını keşfettim: WindowsIdentity sınıf.

Bununla birlikte, bir kod yürütme kavram kanıtı hazırladım:

  1. kullanarak ysoserial seri durumdan çıkarma saldırı aracıyla kod yürütme yükümü oluşturdum ysoserial.exe -f BinaryFormatter -g WindowsIdentity -o raw -c "calc" -t > fbgames.settings.
  2. Daha sonra kopyaladım fbgames.settings ile C:\Users\\AppData\Local\Facebook ve orijinal dosyayı değiştirdim. Bir kullanıcı dizininde bulunduğu için yönetici ayrıcalıklarına gerek yoktu.
  3. Sonunda Facebook Gameroom’u açtım ve hesap makinesi çıktı!

Kodun çalıştırılması heyecan verici olsa da, Facebook ekibiyle daha fazla tartıştıktan sonra bunun onların tehdit modeline uymadığı konusunda anlaştık. Gameroom kullanıcı düzeyinde uygulamalar olarak çalıştığından ayrıcalıkları yükseltme fırsatı yoktur. Ayrıca, dosyanın üzerine yazmak bir düzeyde erişim gerektirdiğinden (örneğin, herkese açık olarak listelenmesi için onay gerektiren kötü amaçlı bir Facebook oyunu aracılığıyla), geçerli bir uzaktan saldırı vektörü yoktu.

Yerel uygulamaların oluşturduğu farklı tehdit ortamıyla ilgili önemli bir ders aldım: kod düzeyindeki güvenlik açıklarına dalmadan önce ilk olarak uygulanabilir bir uzaktan saldırı vektörü arayın.

Hiç bir e-postadaki bağlantıya tıklayıp sihirli bir şekilde Zoom’u başlattınız mı? Perde arkasında tam olarak ne oldu? Web’deki herhangi bir bağlantı gibi uygulamaları açmanıza olanak tanıyan özel bir URI şeması kullandınız. Örneğin Zoom şunları kaydeder: zoommtg: URI şeması ve aşağıdaki gibi bağlantıları ayrıştırır zoommtg:zoom.us/join?confno=123456789&pwd=xxxx&zc=0&browser=chrome&uname=Betty .

Benzer şekilde Gameroom’un, web tarayıcısındaki bir bağlantıya tıkladıktan sonra Gameroom’u otomatik olarak açmak için özel bir URI şeması kullandığını fark ettim. Kodu araştırdıktan sonra Gameroom’un kontrol ettiğini fark ettim. fbgames: URI şeması FacebookGames\Program.cs:

private static void OnInstanceAlreadyRunning()
{
    Uri uri = ArgumentHelper.GetLaunchScheme() ?? new Uri("fbgames://");
    if (SchemeHelper.GetSchemeType(uri) == SchemeHelper.SchemeType.WindowsStartup)
    {
        return;
    }
    NativeHelpers.BroadcastArcadeScheme(uri);
}

Oyun Odası şu şekilde açılsaydı fbgames:// URI, onu ayrıştırmaya devam edecek SchemeHelper sınıf:

public static SchemeHelper.SchemeType GetSchemeType(Uri uri)
{
if (uri == (Uri) null)
return SchemeHelper.SchemeType.None;
string host = uri.Host;
if (host == "gameid")
return SchemeHelper.SchemeType.Game;
if (host == "launch_local")
return SchemeHelper.SchemeType.LaunchLocal;
return host == "windows_startup" ? SchemeHelper.SchemeType.WindowsStartup : SchemeHelper.SchemeType.None;
}

public static string GetGameSchemeId(Uri uri)
{
if (SchemeHelper.GetSchemeType(uri) != SchemeHelper.SchemeType.Game)
return (string) null;
string str = uri.AbsolutePath.Substring(1);
int num = str.IndexOf('/');
int length = num == -1 ? str.Length : num;
return str.Substring(0, length);
}

URI’de şu özellik olsaydı gameid ana bilgisayar, onu ayrıştırırdı SchemeHelper.SchemeType.Game. Eğer kullanmışsa launch_local ana bilgisayar, onu ayrıştırırdı SchemeHelper.SchemeType.LaunchLocal. Umut verici bir şekilde başladım launch_local yolu takip ederek FacebookGames.SchemeHelper.GenLocalLaunchFile(Uri):

public static async Task<string> GenLocalLaunchFile(Uri uri)
{
    string result;
    if (SchemeHelper.GetSchemeType(uri) != SchemeHelper.SchemeType.LaunchLocal || uri.LocalPath.Length <= 1)
    {
        result = null;
    }
    else if (!(await new XGameroomCanUserUseLocalLaunchController().GenResponse()).CanUse)
    {
        result = null;
    }
    else
    {
        string text = uri.LocalPath.Substring(1);
        result = ((MessageBox.Show(string.Format("Are you sure you want to run file\n\"{0}\"?", text), "Confirm File Launch", MessageBoxButtons.YesNo) == DialogResult.Yes) ? text : null);
    }
    return result;
}

Ne yazık ki, sistemde herhangi bir rastgele dosyayı şuna benzer bir URI aracılığıyla başlatabildiğim ortaya çıktı: fbgames://launch_local/C:/evilapp.exe (Facebook tarafından belgelendiği gibi), bu bir onay iletişim kutusu tarafından engellenecektir. Bu iletişim kutusunu biçim dizeleri ve standart olmayan girişlerle atlamayı denedim, ancak bunu aşmanın bir yolunu bulamadım.

geri döndüm gameid URI’deki oyun kimliğine göre bir Facebook URL’si açan yol. Örneğin, Words With Friends’i Oyun Odası’nda başlatmak istiyorsanız şu adresi ziyaret edersiniz: fbgame://gameid/168378113211268 bir tarayıcıda Oyun Odası açılır https://apps.facebook.com/168378113211268 yerel uygulama penceresinde.

Ancak şunu fark ettim GetGameSchemeIdeklenecek URI’den kimliği çıkaran apps.facebook.com URL aslında bilginin geçerli bir kimlik olduğunu doğrulamadı. Bu nedenle bir saldırgan, yerel uygulama penceresini Facebook’taki herhangi bir başka sayfaya yönlendirebilir.

public static string GetGameSchemeId(Uri uri)
{
if (SchemeHelper.GetSchemeType(uri) != SchemeHelper.SchemeType.Game)
return (string) null;
string str = uri.AbsolutePath.Substring(1);
int num = str.IndexOf('/');
int length = num == -1 ? str.Length : num;
return str.Substring(0, length);
}

Örneğin, fbgame://gameid/evilPage Oyun Odası penceresini şuraya yönlendirir: https://apps.facebook.com/evilPage.

Peki Gameroom’da saldırgan tarafından kontrol edilen koda nasıl yönlendirebilirim? Açık yönlendirmeyi kötüye kullanmak da dahil olmak üzere birkaç seçenek vardı. apps.facebook.com. Ne yazık ki o sırada elimde bir tane yoktu. Başka bir yol da, özel kodlu gömülü iframe’lere izin veren bir Facebook Sayfasına veya reklama yönlendirmekti.

Bu noktada bir barikatla karşılaştım. Kodun yeniden gözden geçirilmesi GetGameSchemeIdURI yolundaki yalnızca ilk sümüklüböcek aldı, dolayısıyla fbgame://gameid/evilPage/app/123456 yerel uygulama penceresini şuraya yönlendirir: https://apps.facebook.com/evilPage ve at /app/123456.

Neyse ki kullanabileceğim ek kod araçları vardı. Gameroom’da kullanılan Chrome sürümü gerçekten eskiydi: 63.0.3239.132 – o zamanki mevcut sürüm 86.0.4240.75. Bu nedenle Facebook Sayfalarının yeni sürümünü desteklemiyordu. Klasik Facebook Sayfaları sürümü, sk öyle bir parametre ki https://apps.facebook.com/evilPage?sk=app_123456 saldırgan tarafından kontrol edilen kodun bulunduğu özel sekmeye yönlendirildi https://apps.facebook.com/evilPage/app/123456!

Ancak ek sorgu parametresini özel düzenime nasıl enjekte edebilirim? Gameroom’un, sorgu parametreleri de dahil olmak üzere ilk URL bilgisinden sonraki her şeyi attığını unutmayın. Yoksa öyle mi? Geriye dönüp baktığımda FacebookGames/SchemeHelper.csbuldum GetCanvasParamsFromQuery:

public static IDictionary<string, string> GetCanvasParamsFromQuery(Uri uri)
{
if (uri == (Uri) null)
return (IDictionary<string, string>) null;
string stringToUnescape;
if (!UriHelper.GetUrlParamsFromQuery(uri.ToString()).TryGetValue("canvas_params", out stringToUnescape))
return (IDictionary<string, string>) null;
string str = Uri.UnescapeDataString(stringToUnescape);
try
{
return JsonConvert.DeserializeObjectstring, string>>(str);
}
catch
{
return (IDictionary<string, string>) null;
}
}

Özel URI’yi aktarmadan önce, GetCanvasParamsFromQuery arardım canvas_params sorgu parametresini kullanın, bunu bir JSON sözlüğü olarak serileştirin ve sorgu parametreleri olarak yeni URL’ye dönüştürün.

Bu beni son yük planıma götürdü. fbgames://gameid/evilPage?canvas_params={"sk":"app_123456"} Gameroom tarafından ayrıştırılacak https://apps.facebook.com/evilPage/app/123456 yerel uygulama tarayıcı penceresinde, bu daha sonra özel JavaScript kodumu çalıştıracaktır.

Daha önce de belirtildiği gibi, yerel bir uygulamanın tehdit ortamı bir web uygulamasından çok farklıdır. Bir saldırgan, yerleşik Chrome yerel penceresini saldırgan tarafından kontrol edilen Javascript’e yeniden yönlendirerek, 3 yıllık yerleşik Chromium tarayıcısında bilinen güvenlik açıklarını gerçekleştirmeye devam edebilir. Tam bir istismar kamuya açıklanmamış olmasına rağmen, bir tür karışıklığı güvenlik açığı nedeniyle Chrome motorunu çökertmek için CVE-2018-6056 kavram kanıtlama kodundan yararlanabildim.

Alternatif olarak, bir saldırgan, kimlik avı saldırıları gerçekleştirmek için esasen meşru yerel Mesaj Kutuları olan açılır kutular oluşturabilir veya önbelleğe alınmış kimlik bilgileri dosyasını okumaya çalışabilir. Neyse ki, Node.JS API’lerini entegre eden Electron uygulamalarının aksine, CefSharp API erişimini sınırlar. Ancak yine de Chromium ve üçüncü taraf kitaplıklardaki güvenlik açıklarına karşı savunmasız olmaya devam ediyor.

Facebook bunu Yüksek olarak ödüllendirdi ve ardından güvenlik açığını düzelterek beni Bountycon’un ilk 10 liderlik sıralamasına soktu. Her ne kadar Gameroom yakında kapatılacak olsa da, bana kesinlikle temel hücum tersine mühendislik konusunda güzel anılar (ve pratik) bıraktı. Uygulama tersine mühendisliğine yeni başlayanlar için Electron, CefSharp ve diğer tarayıcı tabanlı çerçeveler, yalnızca masaüstü kod yürütme vektörlerinden yararlanırken siteler arası komut dosyası oluşturma ve açık yönlendirmeler gibi web’e bitişik zayıflıkları test etmek için iyi bir başlangıç ​​noktasıdır.



Source link