SQL Enjeksiyonu, saldırganların kullanıcı girişi yoluyla zararlı SQL kodu yerleştirdiği web uygulamalarındaki bir güvenlik açığıdır. Bu onların hassas veri değişikliği veritabanı içeriklerine erişmelerine ve hatta sistemin kontrolünü ele geçirmelerine olanak tanıyabilir. Web uygulamalarını güvende tutmak için SQL Enjeksiyonu hakkında bilgi sahibi olmak önemlidir.
SQL Enjeksiyonu (SQLi), bir saldırganın kullanıcı giriş alanlarına kötü amaçlı SQL kodu yerleştirerek bir web uygulamasının veritabanı sorgularını değiştirebildiği zaman ortaya çıkan bir güvenlik açığıdır. Bu enjekte edilen sorgular, hassas verileri değiştirmek veya silmek için temeldeki veritabanını değiştirebilir. Bazı durumlarda saldırganlar, veritabanı veya sunucu üzerinde tam kontrol elde ederek ayrıcalıkları bile yükseltebilir.

Gerçek Dünya Örneği:
2019'da Capital One Veri İhlali, bir saldırganın SQL enjeksiyon güvenlik açığından yararlanmasına izin veren yanlış yapılandırılmış bir web uygulaması nedeniyle meydana geldi. Bu, ad adresleri ve kredi puanları da dahil olmak üzere 100 milyondan fazla müşterinin kişisel verilerinin sızdırılmasına neden oldu.
SQL Enjeksiyon Güvenlik Düzeyi
DVWA, öğrencilerin farklı korumaların saldırıları nasıl etkilediğini görmelerine yardımcı olmak amacıyla SQL Enjeksiyonu için dört güvenlik düzeyi sağlar:
1. Düşük Güvenlik
Uygulama girişinizi alır ve hiçbir filtreleme olmadan doğrudan SQL sorgusuna koyar.
$id = $_GET['id'];$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';- Giriliyor
':Sorguyu bozar ve veritabanının savunmasız olduğunu ortaya koyan bir hata atmasına neden olur. - Giriliyor
1' OR '1'='1:Tüm kullanıcıların döndürülmesi için sorguyu her zaman doğru olacak şekilde kandırır. - Giriliyor
1' UNION SELECT user password FROM users--:Kullanıcı adları ve şifreler gibi gizli verileri getirmek için başka bir sorguya katılır.
2. Orta Güvenlik
Uygulama, aşağıdaki gibi işlevleri kullanarak temel giriş temizleme işlemini uygular:addslashes()kaçmak'.
$id = addslashes($_GET['id']);$query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';';Saldırı nasıl olabilir:
Basit'enjeksiyon artık işe yaramayacak (çünkü').
Ancak saldırganlar yine de sayısal eklemeyi kullanarak atlayabilirler (çünkü sayıların tırnak içine alınmasına gerek yoktur).
Örnek:
karakter.java'yı karşılaştır
1 OR 1=1Bu yine de tüm kayıtları döndürür.
3. Yüksek Güvenlik
Uygulama, kullanıcı girişini güvenli bir şekilde işlemek için hazırlanmış ifadeleri (parametreli sorgular) kullanır.
$stmt = $pdo->prepare('SELECT first_name last_name FROM users WHERE user_id = ?');$stmt->execute([$id]);Saldırı:
Şunun gibi girişimler:' OR 1=1veyaUNION SELECTartık çalışmıyor.
Sorgu tüm girdileri SQL kodu olarak değil veri olarak ele alır.
SQL Enjeksiyon Türleri
Farklı SQL Enjeksiyon türleri vardır
1. Hata Tabanlı SQL Enjeksiyonu
Hata tabanlı SQL enjeksiyonu, bir saldırganın kasıtlı olarak veritabanının bir hata mesajı oluşturmasına neden olduğu bir bant içi SQL enjeksiyonu türüdür. Saldırgan daha sonra bu hata mesajını analiz ederek veritabanının yapısı hakkında tablo adları ve sütun adları gibi daha kesin saldırılar gerçekleştirmek için kullanılabilecek değerli bilgiler elde eder.
Nasıl Çalışır?
Bu saldırı, genel mesajlar göstermek yerine ham veritabanı hatalarını ortaya çıkaran uygulamaları hedef alır. Saldırganlar, SQL sözdizimini bozan kötü amaçlı girdiler enjekte ederek bu hataları tetikler ve veritabanı yapısı hakkında değerli ipuçları elde ederler.
dize biçimlendirme java
- Savunmasız Bir Girişi Belirleyin: Saldırgan, uygun giriş temizliği yapılmadan, veritabanıyla doğrudan etkileşime giren bir arama çubuğu veya URL parametresi gibi bir giriş alanı bulur.
- Kötü Amaçlı Bir Yükü Enjekte Etme: Saldırgan özel bir karakter enjekte eder (tek bir alıntı gibi)
') veya veritabanı hatasına neden olduğu bilinen bir işlev. - Hatayı Analiz Edin: Yanlış biçimlendirilmiş sorguyu işleyemeyen veritabanı, ayrıntılı bir hata mesajı döndürür. Bu mesaj aşağıdakiler gibi önemli bilgileri ortaya çıkarabilir:
- Veritabanı sistemi (örneğin MySQL Oracle SQL Server).
- Veritabanının sürümü.
- Yürütülen SQL sorgusunun tamamı.
- Tablo veya sütun adlarını anlamak için kullanılabilecek belirli sözdizimi hataları.
- Saldırıyı İyileştir: Saldırgan, hata mesajından toplanan bilgileri kullanarak, kullanıcı adları ve şifreler gibi daha fazla veri elde etmek için yükünü hassaslaştırabilir.
Örnek:
1. Adım: Ortamınızı Kurun
- DVWA'yı başlatın. Genellikle aşağıdaki gibi bir URL'ye gidilerek erişilir:
http://localhost/dvwatarayıcınızda.
- Varsayılan kimlik bilgileriyle DVWA'da oturum açın:
admin/password.
- DVWA Güvenliği sekmesine gidin ve güvenlik düzeyini düşük olarak ayarlayın. Bu, güvenlik açıklarından yararlanmanın kolay olmasını sağlayacaktır.
Adım 2: Güvenlik Açığı Tanımlayın
SQL Enjeksiyon sayfasında kullanıcı kimliğini girebileceğiniz basit bir giriş kutusu bulunur. Arka uç sorgusu muhtemelen şöyle bir şeydir:SELECT * FROM users WHERE id = 'user_input'
- Gibi geçerli bir kimlik girin
1giriş kutusuna girin ve 'Gönder'i tıklayın. ID 1'e sahip kullanıcının ayrıntılarını görmelisiniz.
SQL Enjeksiyon Kaynağı
PHP $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( ''
. ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ode ?> - Şimdi sorguyu kırmayı deneyin. Tek bir teklif girin
'giriş kutusuna girin ve gönderin.
Sorgu şu şekilde olur:
SELECT * FROM users WHERE id = ''';Burada veritabanı fazladan bir teklif görüyor ve sorguyu nasıl tamamlayacağını bilmiyor.
Şehzad poonawala
Uygulama size kullanıcı ayrıntılarını göstermek yerine bir SQL hatası döndürecektir ('SQL sözdiziminizde bir hata var…' gibi bir şey)
Buna Hata Tabanlı SQL Enjeksiyonu denir çünkü:
- Saldırgan geçersiz girdi gönderiyor (
') - Veritabanı hata veriyor
- Bu hata, veritabanı hakkında yararlı bilgiler sızdırıyor (DB türü, sütun sayısı, yapı vb. gibi)
2. Birlik Tabanlı SQL Enjeksiyonu
Union tabanlı SQL Enjeksiyonu, saldırganların kullandığı bir tekniktir.UNIONiki veya daha fazlasının sonuçlarını birleştiren operatörSELECTifadeleri tek bir sonuç kümesine dönüştürür. Bu, veritabanındaki diğer tablolardan bilgi çıkarmalarına olanak tanıyabilir.UNIONoperatörü yalnızca şu durumlarda kullanılabilir:
- Her iki sorgu da aynı sayıda sütuna sahip
- Sütunlar benzer veri türlerine sahip
- Sütunlar aynı sırada
BİRLİK Operatörü :UNIONoperatörü iki veya daha fazla sonuç kümesini birleştirmek için kullanılırSELECTifadeler.
- Her biri
SELECTiçindeki beyanUNIONaynı sayıda sütuna sahip olmalıdır - Sütunların benzer veri türlerine sahip olması gerekir
- Sütunlar aynı sırada olmalıdır
SELECT column_name(s) FROM table1UNIONSELECT column_name(s) FROM table2Örnek:
1. Adım: UNION tabanlı SQL Enjeksiyonunu enjekte etmek için öncelikle web sitesindeki mevcut tablonun sütun sayısını bulmalıyız:
SQL Enjeksiyon sayfasında kullanıcı kimliğini girebileceğiniz basit bir giriş kutusu bulunur. Arka uç sorgusu muhtemelen şöyle bir şeydir:
SELECT * FROM users WHERE id = 'user_input'Şimdi sorguyu kırmayı deneyin. Tek bir teklif girin'giriş kutusuna girin ve gönderin.
Uygulamanın güvenlik açığı varsa ayrıntılı bir hata mesajı alırsınız. Şöyle bir şeye benzeyebilir:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''' at line 1
Adım 2: Şunu kullanın:UNIONSütun Sayısını Keşfedecek Anahtar Kelime
Kullanmak içinUNIONanahtar kelime (ortak bir sonraki adım) orijinal sorgudaki sütun sayısını bilmeniz gerekir. Bunu kullanarak öğrenebilirsiniz.ORDER BYmadde
arp-a komutu
- Sonuçları sütuna göre sıralamayı deneyin
1:1 ORDER BY 1.
- Göndermek. İşe yaramalı.
SQL Enjeksiyon Kaynağı
PHP if( isset( $_REQUEST[ 'Submit' ] ) ) { // Get input $id = $_REQUEST[ 'id' ]; switch ($_DVWA['SQLI_DB']) { case MYSQL: // Check database $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; $result = mysqli_query($GLOBALS['___mysqli_ston'] $query ) or die( ''
. ((is_object($GLOBALS['___mysqli_ston'])) ? mysqli_error($GLOBALS['___mysqli_ston']) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '' ); // Get results while( $row = mysqli_fetch_assoc( $result ) ) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } mysqli_close($GLOBALS['___mysqli_ston']); break; case SQLITE: global $sqlite_db_connection; #$sqlite_db_connection = new SQLite3($_DVWA['SQLITE_DB']); #$sqlite_db_connection->enableExceptions(true); $query = 'SELECT first_name last_name FROM users WHERE user_id = '$id';'; #print $query; try { $results = $sqlite_db_connection->query($query); } catch (Exception $e) { echo 'Caught exception: ' . $e->getMessage(); exit(); } if ($results) { while ($row = $results->fetchArray()) { // Get values $first = $row['first_name']; $last = $row['last_name']; // Feedback for end user echo 'ID:
{$id}
First name: {$first}
Surname: {$last}'; } } else { echo 'Error in fetch '.$sqlite_db->lastErrorMsg(); } break; } } ?> - Sayıyı artırın:
1 ORDER BY 2. Göndermek. İşe yaramalı.
- Hata alana kadar artırmaya devam edin. Örneğin
1 ORDER BY 4sana verebilir:Unknown column '4' in 'order clause' - Bu, sorgunun 3 sütuna sahip olduğu anlamına gelir.
3. Kör Tabanlı SQL Enjeksiyonu
Kör SQL Enjeksiyonu Saldırganlar sorgu sonuçlarını doğrudan web sayfasında göremediğinde ortaya çıkar. Bunun yerine uygulamanın davranışındaki veya yanıt süresindeki ince değişikliklerden bilgi çıkarırlar. Klasik SQLi'ye göre daha yavaş ve sıkıcı olmasına rağmen aynı derecede etkili olabilir.
Saldırgan, verileri geri almak yerine web sayfasının davranışını gözlemleyerek bilgi çıkarır. Bu genellikle iki yoldan biriyle yapılır:
- Boolean Tabanlı Kör SQLi: Saldırgan bir SQL sorgusu enjekte eder ve bu sorgu doğru veya YANLIŞ sonuç. Web uygulamasının yanıtı, sorgunun doğru veya yanlış olmasına göre değişir. Örneğin sayfa farklı bir mesaj gösterebilir veya farklı bir düzen oluşturabilir.
- Zamana Dayalı Kör SQLi: Saldırgan, veritabanının zaman alıcı bir eylem (örneğin,
SLEEP()fonksiyonu) eğer bir koşul karşılanırsa. Saldırgan, enjekte edilen koşulun doğru mu yanlış mı olduğunu belirlemek için sayfanın yüklenmesi için geçen süreyi gözlemler.
Örnek:
Kullanıcı adınızı ve şifrenizi girdiğiniz bir giriş sayfası hayal edin. Uygulama şuna benzer bir SQL sorgusu oluşturur:
SELECT * FROM users WHERE username = 'user_input' AND password = 'password_input'Kör bir SQL enjeksiyonu,user_inputVeritabanına bir soru sormak için alan.
Saldırgan doğrudan yanıt almak yerine şöyle bir şey deneyebilir:
user_input = 'admin' AND 1=1; --Sayfa normal şekilde yüklenirse saldırgan bunu bilir1=1bir doğru ifade.
Onlar şarkıcılar
user_input = 'admin' AND 1=2; --Sayfa bir hata gösteriyorsa veya farklı davranıyorsa saldırgan bunu bilir.1=2bir YANLIŞ ifade.
Saldırgan, bu doğru/yanlış sorularından oluşan bir diziyi kullanarak, her seferinde bir karakter olmak üzere sistematik olarak tahminde bulunabilir ve bilgiyi çıkarabilir. İşlem, tablo adlarından kullanıcı şifrelerine kadar her şeyi tahmin edecek şekilde otomatikleştirilebilir.
SQL Enjeksiyon Saldırılarının Etkisi
- Hassas verilere yetkisiz erişim : Saldırganlar veritabanında saklanan kişisel mali veya gizli bilgileri ele geçirebilir.
- Veri bütünlüğü sorunları : Saldırganlar, uygulamanın işlevselliğini etkileyen kritik verileri değiştirebilir veya silebilir.
- Ayrıcalık artışı : Saldırganlar kimlik doğrulama mekanizmalarını atlayabilir ve yönetici ayrıcalıkları elde edebilir.
- Hizmet kesintisi : SQL enjeksiyonu sunucuyu aşırı yükleyerek performansın düşmesine veya sistemin çökmesine neden olabilir.
- İtibar hasarı : Başarılı bir saldırı, bir kuruluşun itibarına ciddi şekilde zarar vererek müşteri güveninin kaybolmasına neden olabilir.
SQL Enjeksiyon Saldırılarını Önleme
SQL enjeksiyon saldırılarını önlemek için birkaç en iyi uygulama vardır:
1. Hazırlanmış İfadeleri ve Parametreli Sorguları Kullanın
Hazırlanan ifadeler ve parametreli sorgular, kullanıcı girişlerinin SQL sorgusunun bir parçası yerine veri olarak değerlendirilmesini sağlar. Bu yaklaşım SQL enjeksiyonu riskini ortadan kaldırır.
PHP'deki örnek (MySQLi kullanarak):
$stmt = $conn->prepare('SELECT * FROM users WHERE username = ? AND password = ?'); $stmt->bind_param('ss' $username $password); $stmt->execute();2. Saklı Prosedürleri Kullanın
Saklı prosedürler, veritabanında saklanan önceden tanımlanmış SQL sorgularıdır. Bu prosedürler, dinamik olarak SQL sorguları oluşturmadıkları için SQL enjeksiyonunun önlenmesine yardımcı olabilir.
Örnek:
CREATE PROCEDURE GetUserByUsername (IN username VARCHAR(50)) BEGIN SELECT * FROM users WHERE username = username; END;3. Beyaz Liste Giriş Doğrulaması
Kullanıcı girişlerinin SQL sorgularında kullanılmadan önce doğrulandığından emin olun. Kullanıcı adları veya e-posta adresleri gibi alanlar için yalnızca alfasayısal giriş gibi belirli karakterlere ve kalıplara izin verin.
4. ORM Çerçevelerini Kullanın
Nesne-İlişkisel Haritalama (ORM) çerçeveleri Hazırda bekletme veya Varlık Çerçevesi dinamik sorgu oluşturmayı önleyerek sorgu oluşturma işlemini otomatik olarak gerçekleştirerek SQL enjeksiyonunun önlenmesine yardımcı olabilir.
5. Veritabanı Ayrıcalıklarını Kısıtlayın
Kullanıcılara gereken minimum veritabanı izinlerini verin. Uygulamaların yalnızca gerekli eylemleri (ör. SELECT INSERT) gerçekleştirebildiğinden emin olun ve DROP TABLE veya ALTER gibi izinleri kısıtlayın.
6. Hata İşleme
Veritabanını ve uygulamayı kullanıcıya ayrıntılı hata mesajları göstermeyecek şekilde yapılandırın. Bunun yerine hataları dahili olarak günlüğe kaydedin ve son kullanıcılara genel hata mesajları görüntüleyin.