PHP sunucu davranışlarını SQL enjeksiyon güvenlik açığından koruyun

Son güncelleme: 27 Nis 2021

Sorun

Bazı veritabanları, tek bir sorguda birden fazla SQL ifadesi göndermenize olanak tanır. Bu nedenle, dinamik olarak oluşturulan veritabanı sorgusuna sorgu dizesinde parametreler aktarırken potansiyel güvenlik riskleri oluşur.Saldırganlar mevcut parametrelere kötü amaçlı SQL deyimleri ekleyerek dinamik sorgudaki URL veya form değişkenlerini değiştirmeye çalışabilir. Buna genellikle SQL ekleme saldırısı denir. Dreamweaver tarafından oluşturulan sunucu davranış kodlarının bazıları, SQL ekleme saldırıları riskini azaltmak için değiştirilmelidir. SQL ekleme hakkında daha fazla bilgi için bu Wikipedia makalesine bakabilirsiniz. (Ref. 201713)

Not: Bu TechNote'ta açıklanan sorun Dreamweaver 8.0.2 Güncelleyici'de düzeltilmiştir.

Bu TechNote, Dreamweaver'ın PHP sunucu davranışlarını kapsar. ColdFusion, ASP VBScript, ASP JavaScript ve JSP sunucu davranışları için ayrı TechNote'lar bulunmaktadır. ASP.NET sunucu davranışları etkilenmez.

Çözüm

Bir sorgu dizisinin bir parametreyi aktarmasına izin verirseniz, yalnızca beklenen bilgilerin aktarıldığından emin olun. Adobe, SQL enjeksiyon saldırıları riskini azaltan bir Dreamweaver 8.0.2 Güncelleyici oluşturmuştur.Bu düzeltmeler Dreamweaver'ın gelecekteki tüm sürümlerine dahil edilecektir. Dreamweaver 8'i güncelledikten sonra, sunucu davranışlarını kullanan sayfalara yeniden uygulamanız ve bu sayfaları sunucunuza yeniden dağıtmanız gerekecektir.

Bu TechNote'un geri kalanı, PHP sunucu modeliyle SQL enjeksiyon saldırılarını önlemek için Dreamweaver MX 2004 kodunun elle nasıl düzenleneceğini belgeler. Bu saldırılara açık sunucu davranışları, düzeltmeleriyle birlikte aşağıda listelenmiştir:

Filtreli Kayıt Kümesi

Filtrelenmemiş kayıt kümelerinin değiştirilmesi gerekmez ancak filtrelenmiş kayıt kümelerinin değiştirilmesi gerekir. Aşağıdaki örnekte, "rs_byDate" adlı Dreamweaver MX 2004 kayıt kümesi, URL parametresinden aktarılan tarih değeri ile filtrelenmektedir. Aşağıda vurgulanan kod, değiştirilmesi gereken kısımdır:

<?php $colname_rs_byDate = &quot;1&quot;; if (isset($_GET[&apos;relDate&apos;])) { $colname_rs_byDate = (get_magic_quotes_gpc()) ? $_GET['relDate'] : addslashes($_GET['relDate']); } mysql_select_db($database_dreamqa2, $dreamqa2); $query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = '%s'", $colname_rs_byDate); $rs_byDate = mysql_query($query_rs_byDate, $dreamqa2) or die(mysql_error()); $row_rs_byDate = mysql_fetch_assoc($rs_byDate); $totalRows_rs_byDate = mysql_num_rows($rs_byDate); ?>

Kayıt kümesini SQL enjeksiyon saldırılarından korumak için sayfanın üst kısmına özel bir GetSQLValueString() işlevi oluşturulmalıdır. Bu işlev sorgu parametresinin veri türünü doğrular. İşlev oluşturulduktan sonra, GetSQLValueString() işlevini kullanmak için kayıt kümesi kodunu güncelleyin.

Kod görünümünde ikinci satıra, bağlantı için dahil edilen dosyadan hemen sonra gidin ve GetSQLValueString() işlevini kodun başına aşağıdaki şekilde ekleyin:

<?php if (!function_exists("GetSQLValueString")) { function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") { $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue; $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue); switch ($theType) { case "text": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "long": case "int": $theValue = ($theValue != "") ? intval($theValue) : "NULL"; break; case "double": $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL"; break; case "date": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "defined": $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue; break; } return $theValue; } } ?>

Magic quotes kodunu kaldırın; böylece PHP sunucusunda magic quotes kapalıyken GET ve POST verilerine yanlış bir şekilde ters eğik çizgiler eklenmez.

Orijinal kod:

$colname_rs_byDate = (get_magic_quotes_gpc()) ? $_GET['relDate'] : addslashes($_GET['relDate']);

Değiştirilmiş kod:

$colname_rs_byDate = $_GET['relDate'];



Yukarıda oluşturulan GetSQLValueString() işlevini kullanarak SQL dizesi oluşturmak için kayıt kümesi kodunu güncelleyin. $query_rs_byDate değişkeninin değerini güncelleyin:

Orijinal kod:

$query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = '%s'", $colname_rs_byDate);

Değiştirilmiş güvenli kod:

$query_rs_byDate = sprintf("SELECT * FROM albums WHERE relDate = %s", GetSQLValueString($colname_rs_byDate, "date"));

Kayıt Ekleme, Güncelleme ve Silme sunucu davranışları ile Kayıt Ekleme Formu sihirbazı

Kayıt Ekleme, Güncelleme ve Silme sunucu davranışları ile Kayıt Ekleme Formu sihirbazı zaten GetSQLValueString() işlevini kullanıyor, bu nedenle SQL enjeksiyonlarını önlemek için iyileştirilmeleri gerekiyor. Gereken tek değişiklik GetSQLValueString() işlevindedir.

İşte orijinal kod. Değiştirilecek satır sarı renkle vurgulanmıştır:

if (!function_exists("GetSQLValueString")) { function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") {$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue; switch ($theType) { case "text": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "long": case "int": $theValue = ($theValue != "") ? intval($theValue) : "NULL"; break; case "double": $theValue = ($theValue != "") ? "'" . doubleval($theValue) . "'" : "NULL"; break; case "date": $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL"; break; case "defined": $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue; break; } return $theValue; } }

$theValue değişkeninin tanımını güncelleyin:

Orijinal kod:

$theValue = (!get_magic_quotes_gpc()) ? addslashes($theValue) : $theValue;

Değiştirilmiş güvenli kod:

$theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue; $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

Oturum Aç Kullanıcısı sunucu davranışı

Log In User sunucu davranışını düzeltmek için izlenecek adımlar:

Filtreli kayıt kümesi bölümünde açıklandığı şekilde bir GetSQLValueString() işlevi oluşturun.

Giriş SQL sorgusunu oluşturan kodu değiştirin.



Orijinal kod:

$LoginRS__query=sprintf("SELECT username, password FROM login WHERE username='%s' AND password='%s'", get_magic_quotes_gpc() ? $loginUsername : addslashes($loginUsername), get_magic_quotes_gpc() ? $password : addslashes($password));

Değiştirilmiş güvenli kod:

$LoginRS__query=sprintf("SELECT username, password FROM login WHERE username=%s AND password=%s", GetSQLValueString($loginUsername, "text"), GetSQLValueString($password, "text"));

Yeni Kullanıcı Adını Denetle sunucu davranışı

Yeni Kullanıcı Adını Denetle sunucu davranışı, öncelikle sayfaya bir Kayıt Ekleme sunucu davranışı eklenmesini gerektirir. GetSQLValuesString() işlevi, Kayıt Ekleme sunucu davranışına dahildir.Yapılması gereken tek şey, SQL Enjeksiyonunu daha iyi işleyecek şekilde GetSQLValuesString()'i güncellemek ve parametre geçirildiğinde bu işlevi kullanmak için Yeni Kullanıcı Kontrol Et sunucu davranışını güncellemektir.

$theValue değişkeninin tanımını güncelleme bölümünde açıklandığı şekilde GetSQLValuesString() işlevini güncellemek için işlevdeki ilk satırı değiştirin.

Parametreleri geçirmek için GetSQLValuesString()'i kullanacak şekilde giriş SQL sorgusunu oluşturan kodu değiştirin. Sayfanın üst kısmında, // *** Redirect if username exists.
ile başlayan bölümdeki kodu bulun


Orijinal kod:

$LoginRS__query = "SELECT username FROM login WHERE username='" . $loginUsername . "'"



Değiştirilmiş güvenli kod:

$LoginRS__query = sprintf("SELECT username FROM login WHERE username=%s", GetSQLValueString($loginUsername, "text"));

Kalıp Ayrıntı Sayfası Kümesi

Kalıp Ayrıntı Sayfası Kümesi uygulama nesnesi için değişiklikler çoğunlukla Dreamweaver'ın Ayrıntı Sayfası için oluşturduğu kayıt kümesindedir. Kalıp Sayfası'nda filtrelenmiş bir kayıt kümesi yoksa o zaman Kalıp Sayfası'nda bir değişiklik yapılmasına gerek yoktur. Filtreli bir kayıt kümeniz varsa, kayıt kümesi kodunu güncellemek için filtreli kayıt kümesi bölümüne bakın.

Dreamweaver Ayrıntı Sayfasında filtreli kayıt kümesi oluşturur, bu nedenle kayıt kümesi kodunun parametreleri geçirmek için GetSQLValueString() işlevini ve SQL dizesini oluşturmak için sprintf()'i kullanacak şekilde güncellenmesi gerekir.

Yukarıda Filtreli kayıt kümesi bölümünde açıklandığı şekilde GetSQLValueString() işlevini oluşturun.

Değişken bildirim kodunu güncelleyin ve GetSQLValuesString() işlevini kullanarak SQL sorgusunu oluşturun.



Orijinal kod:

$recordID = $_GET['recordID']; $query_DetailRS1 = "SELECT * FROM albums WHERE ID = $recordID";



Değiştirilmiş güvenli kod:

$colname_DetailRS1 = "-1"; if (isset($_GET['recordID'])) { $colname_DetailRS1 = (get_magic_quotes_gpc()) ? $_GET['recordID'] : addslashes($_GET['recordID']); } $query_DetailRS1 = sprintf("SELECT * FROM albums WHERE ID = %s", GetSQLValueString($colname_DetailRS1, "int"));

Kayıt Güncelleme Formu sihirbazı

Kayıt Ekleme, Güncelleme ve Silme sunucu davranışları ve Kayıt Ekleme Formu sihirbazı bölümünde açıklandığı şekilde $theValue değişkeninin tanımını güncelleyin.
Kayıt Güncelleme Formu için gerekli olan Recordset kodunu 2. adım Filtreli Recordset bölümünde açıklandığı şekilde güncelleyin.

Ek Bilgiler

SQL injection hakkında daha fazla bilgi için lütfen şu makaleye başvurun: SQL injection hakkında Wikipedia makalesi.

Adobe Güvenlik Bülteni: APSB 06-07 Dreamweaver Server Behavior SQL Injection güvenlik açığı.