Yaklaşık bir güvenlik açığı...

Yaklaşık bir güvenlik açığı...

Bir yıl önce, 21 Mart 2019, hata ödül programı Mail.Ru HackerOne'a çok iyi bir tanesi geldi hata raporu itibaren maksimum. Bir HTTP yönlendirmesi döndüren web postası API isteklerinden birinin POST parametresine sıfır bayt (ASCII 0) eklenirken, yönlendirme verilerinde GET parametrelerinden parçaların ve diğer isteklerin başlıklarının bulunduğu, başlatılmamış bellek parçaları görüldü. aynı sunucu.

Bu kritik bir güvenlik açığı çünkü... istekler aynı zamanda oturum çerezlerini de içerir. Birkaç saat sonra, sıfır baytı filtreleyen geçici bir düzeltme yapıldı (daha sonra ortaya çıktığı gibi, bu yeterli değildi, çünkü hala başlıkları değiştirmenize izin veren CRLF / ASCII 13, 10'u enjekte etme olasılığı vardı ve HTTP yanıtının verileri, bu daha az kritiktir ancak yine de rahatsız edicidir). Aynı zamanda sorun, hatanın nedenlerini bulup ortadan kaldırmak için güvenlik analistlerine ve geliştiricilere aktarıldı.

Mail.ru mail çok karmaşık bir uygulamadır; hem açık kaynaklı (tüm özgür yazılım geliştiricilere çok teşekkürler) hem de şirket içi geliştirilen çok sayıda farklı ön uç/arka uç bileşeni yanıtın oluşturulmasına dahil edilebilir. Nginx ve openresty dışındaki tüm bileşenleri hariç tutmayı ve aramadan önce sorunun yerini belirlemeyi başardık ngx.req.set_uri() beklendiği gibi davranmayan bir OpenResty betiğinde (belgelere göre kullanılan ve görünüşe göre tam olarak aynı şekilde çalışması gereken ngx_http_rewrite_module'de yeniden yazma ile GET parametreleri aracılığıyla boş bir bayt veya satır besleme eklemek) çalışmıyor). Olası sonuçlar ortadan kaldırıldı, filtreleme mümkün olduğunca sıkı bir şekilde eklendi ve filtrelemenin tüm olası vektörleri ortadan kaldıracağı doğrulandı. Ancak hafıza içeriğinin sızmasına yol açan mekanizma bir sır olarak kaldı. Bir ay sonra hata raporu çözüldüğü için kapatıldı ve hatanın nedenlerinin analizi daha iyi zamanlara ertelendi.

OpenResty, nginx içinde Lua komut dosyaları yazmanıza olanak tanıyan çok popüler bir eklentidir ve birkaç Mail.ru projesinde kullanıldığı için sorun çözülmüş sayılmamıştır. Ve bir süre sonra, gerçek nedenleri, olası sonuçları anlamak ve geliştiricilere önerilerde bulunmak için nihayet ona geri döndüler. Kaynak kodunun kazısına katıldı Denis Denisov и Nikolay Ermişkin. Şu ortaya çıktı:

  • Nginx'te, kullanıcı verileriyle yeniden yazma kullanıldığında, bazı yapılandırmalarda dizin geçişi (ve muhtemelen SSRF) olasılığı vardır, ancak bu bilinen bir gerçektir ve statik yapılandırma çözümleyicileri tarafından tespit edilmelidir. Nginx'i Güçlendirin и sarhoş Yandex'den (evet, onu da kullanıyoruz, teşekkürler). OpenResty kullanırken bu özelliğin gözden kaçırılması kolaydır ancak bu, yapılandırmamızı etkilemedi.

    konfigürasyon örneği:

    location ~ /rewrite {
        rewrite ^.*$ $arg_x;
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    sonuç

    curl localhost:8337/rewrite?x=/../../../../../../../etc/passwd
    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    ...

  • Nginx'te, yeniden yazma satırı boş bir bayt içeriyorsa belleğin sızmasına neden olan bir hata var. Bir yönlendirme yapıldığında, nginx, satırın tam uzunluğuna karşılık gelen yeni bir bellek arabelleği tahsis eder, ancak sıfır baytın bir satır sonlandırıcı olduğu bir satır işlevi aracılığıyla satırı buraya kopyalar, böylece satır yalnızca sıfıra kadar kopyalanır. bayt; arabelleğin geri kalanı başlatılmamış veriler içerir. Detaylı bir analiz bulunabilir burada.

    konfigürasyon örneği (^@ sıfır bayt)

    
    location ~ /memleak {
        rewrite ^.*$ "^@asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdasdf";
    }
    
    location / {
        root html;
        index index.html index.htm;
    }

    sonuç
    curl localhost:8337/secret -vv
    ...
    curl localhost:8337/memleak -vv
    ...
    Location: http://localhost:8337/secret
    ...

  • Nginx, GET parametrelerini servis karakterlerinin enjeksiyonundan korur ve yeniden yazma sırasında yalnızca GET parametrelerinin kullanılmasını mümkün kılar. Bu nedenle, nginx'te kullanıcı tarafından kontrol edilen parametreler aracılığıyla enjeksiyondan yararlanmak mümkün değildir. POST parametreleri korunmaz. OpenResty, hem GET hem de POST parametreleriyle çalışmanıza olanak tanır; böylece POST parametrelerini OpenResty aracılığıyla kullanırken özel karakterler eklemek mümkün hale gelir.

    konfigürasyon örneği:

    location ~ /memleak {
        rewrite_by_lua_block {
            ngx.req.read_body();
            local args, err = ngx.req.get_post_args();
            ngx.req.set_uri( args["url"], true );
        }
    }
    
    location / {
        root html;
        index index.html index.htm;
    }
    

    sonuç:

    curl localhost:8337 -d "url=secret" -vv
    ...
    curl localhost:8337 -d "url=%00asdfasdfasdfasdfasdfasdfasdfasdf" -vv
    ...
    Location: http://localhost:8337/{...может содержать secret...}
    ...

Daha fazla reaksiyon

Sorun nginx ve OpenResty geliştiricilerine bildirildi, geliştiriciler sorunu nginx'te bir güvenlik hatası olarak görmüyorlar çünkü nginx'in kendisinde, özel karakterlerin eklenmesi yoluyla hatadan yararlanmanın bir yolu yoktur, düzeltme hafıza açıklaması 16 Aralık'ta yayınlandı. Rapordan bu yana geçen 4 ay içinde OpenResty'de herhangi bir değişiklik yapılmadı, ancak ngx.req.set_uri() işlevinin güvenli bir sürümünün gerekli olduğu konusunda bir anlayış vardı. 18 Mart 2020'de bilgi yayınladık, 21 Mart'ta OpenResty yayınlandı sürüm 1.15.8.3URI doğrulaması ekleyen.

Portswigger yazdı iyi bir makale ve OpenResty ve Nginx'ten yorumlar aldım (her ne kadar belleğin yalnızca küçük bir bölümünün açığa çıktığı yorumu yanlış ve yanıltıcı olsa da, bu, boş baytı takip eden satırın uzunluğuna göre belirlenir ve açık kısıtlamaların yokluğunda) uzunluk saldırgan tarafından kontrol edilebilir).

Peki hata neydi ve bunu önlemek için ne yapılabilir?

Nginx'te bir hata mı vardı? Evet öyleydi çünkü bellek içeriğinin sızdırılması her halükarda bir hatadır.

OpenResty'de bir hata mı vardı? Evet, en azından OpenResty'nin sunduğu işlevselliğin güvenliği konusu araştırılmamış ve belgelenmemiştir.

OpenResty'de bir yapılandırma/kullanım hatası mı vardı? Evet, çünkü açık bir ifade bulunmadığından, kullanılan işlevselliğin güvenliği konusunda doğrulanmamış bir varsayımda bulunulmuştur.

Bu hatalardan hangisi 10000$ ödüllü bir güvenlik açığıdır? Bizim için bu genellikle önemli değildir. Herhangi bir yazılımda, özellikle çeşitli bileşenlerin kesişiminde, özellikle de farklı projeler ve geliştiriciler tarafından sağlananlarda, hiç kimse çalışmalarının tüm özelliklerinin bilindiğini, belgelendiğini ve hiçbir hata olmadığını garanti edemez. Bu nedenle herhangi bir güvenlik açığı tam olarak güvenliği etkilediği yerde ortaya çıkar.

Her durumda, açık talimatlar olmadığı ve bunun gerekli olmadığına dair net bir anlayış olmadığı sürece, herhangi bir harici modüle/API'ye giren giriş verilerini mümkün olduğunca normalleştirmek veya sınırlamak/filtrelemek iyi bir uygulamadır.

baskı hatası

deneyime göre önceki makaleDilin saflığını korumak adına:

hata ödülü - böcek avlama yarışması
hata raporu - hata bildirimi
yönlendirmek - yönlendirme
açık kaynak - açık kaynak
yanlış - hatalar üzerinde çalışın

Kaynak: habr.com

Yorum ekle