SQL Server erişim denetimi ve sorgu onayı
SQL Server, hangi login’lerin ve kullanıcıların hangi nesnelere erişebileceğine karar verir. Gece 3’te biri tarafından yazılan bu özel ifadenin çalışıp çalışmaması gerektiğine karar vermez. QueryProxy bu kararı ekler: geliştiriciler T-SQL gönderir, ifade kuyruğa girmeden önce parse edilip denetlenir, bir DBA onaylar ve sonuç saklanmadan önce maskelenir. SQL Server parolası QueryProxy’nin kasasında kalır ve hiçbir geliştiriciye verilmez.
Önce neyi kurmanız gerekir?
SQL Server, varsayılan imajın erişemediği tek motordur. Docker imajı pdo_pgsql,
pdo_mysql ve pdo_sqlite ile gelir. SQL Server’ı proxy’lemek için:
- Dockerfile’ı Microsoft’un ODBC sürücüsü ile
sqlsrvvepdo_sqlsrvPECL eklentileriyle genişletin. - Kendi imajınızı build edin ve
queryproxy/queryproxyyerine onu çalıştırın. - Eklentilerin, hem web sürecini hem de kuyruk işçisini çalıştıran PHP build’inde olduğundan emin olun; çünkü onaylanan sorgular işçide çalışır.
Manuel kurulumda da aynısı geçerlidir: SQL Server hedefleri için pdo_sqlsrv
bulunmalıdır. Ayrıntılar
yapılandırma rehberinde var.
Bu yapılmadan bir SQL Server bağlantısı sorgu çalıştıramaz.
Bir login’in izni neyi açık bırakır?
İzinler bir login’i veritabanlarına, şemalara ve nesnelere sınırlar ve önce onları sıkılaştırmalısınız. Yine de boşluklar bırakırlar:
- Bir tabloyu
UPDATEedebilen kullanıcı,WHERE’siz birUPDATEçalıştırabilir. userstablosunuSELECTedebilen kullanıcı, içindeki her e-posta adresini maskesiz olarak bir dizüstü bilgisayara alır.- İfade çalışmadan önce başka kimse onu görmez.
SQL Server’ın veritabanı motorunun dışına çıkan prosedürleri de vardır.
Microsoft’un dokümantasyonu,
xp_cmdshell
prosedürünün bir Windows komut kabuğu başlattığını ve komutun SQL Server servis
hesabıyla aynı haklarla çalıştığını söyler. Varsayılan olarak kapalıdır ve
sp_configure ile açılır (2026-10-13 tarihinde okundu). QueryProxy hem xp_*
ailesini hem de sp_configure’u gönderim anında engeller; yani bir talep bunları
istemeye bile kalkışamaz.
Veritabanı erişim denetiminin ne olduğu
yazısı, tek başına izinlerin bu boşlukları neden kapatmadığını açıklar.
QueryProxy SQL Server’da neyi engeller?
Her gönderim onay kuyruğuna ulaşmadan önce parse edilir ve bir guard’ı çiğneyen talep, gönderim anında açık bir mesajla reddedilir. SQL korumaları referansı kuralları dialect’e göre listeler. Burada en önemli olanlar:
WHERE’siz ya da her zaman doğru olan birWHEREile (WHERE 1 = 1) yazılmışUPDATEveDELETEreddedilir.TOP’suz üst düzey birSELECT’eTOP (1000)eklenir,10000’in üzerindekiTOPiseTOP 10000’e düşürülür. CTE ve küme işlemi sorgularınaTOPeklenmez; onları 10000 satırlık tavan sınırlar.xp_*,sp_configure,sp_oa*,sp_addlinkedserver,sp_addlinkedsrvlogin,sp_serveroption,sp_addextendedprocvesp_execute_external_script, ister ifade olarak isterEXEC’ten sonra çağrılsın, engellenir.OPENROWSET,OPENDATASOURCE,OPENQUERYveBULK INSERTengellenir.GRANT,REVOKE,DENYveSHUTDOWNengellenir.sp_prepare,sp_execute,sp_sqlexec,sp_msforeachtablevesp_send_dbmailgibi kendilerine verilen metni çalıştıran prosedürler, argümanları ne olursa olsun engellenir.THROW,RECONFIGURE,KILLveCHECKPOINTyazma olarak sınıflandırılır; böylece onaydan geçerler.
DELETE FROM orders; -- rejected at submission
DELETE FROM orders WHERE id = 42; -- allowed, still needs a DBA
EXEC xp_cmdshell 'dir'; -- rejected at submission
SELECT 'xp_cmdshell'; -- a plain read
Tablo adları örnektir; kararlar belgelenmiş kurallara göre verilir.
Dinamik SQL nasıl ele alınır?
EXEC('...') ve sp_executesql SQL’i metin olarak alır; T-SQL guard’ları genellikle
tam burada kırılır. QueryProxy okuyabildiğini değerlendirir:
WHERE’sizEXEC('DELETE FROM t')engellenir veEXEC('DELETE FROM t WHERE id = 1')yazma olarak sınıflandırılır.sp_executesql N'...', içindeki metne olağan kurallar uygulanarak değerlendirilir.EXEC(@sql),EXEC('a' + 'b'),EXEC(...) AT srvveEXEC ... AS USER, guard neyin çalışacağını bilemeyeceği için engellenir.EXEC('EXEC xp_cmdshell ''dir''')gibi iç içe bir literal engellenir.- 3 seviyeden derin iç içe geçmiş dinamik SQL engellenir.
Guard şüphede katı davranır: EXEC "quoted_name" ve WHERE exec = 1 de
engellenir.
Bir SQL Server veritabanı nasıl bağlanır?
Yukarıdaki imaj değişikliğinden sonra bir DBA, veritabanını Connections altında
SQL Server sürücüsüyle (sqlsrv) kaydeder. Varsayılan port 1433’tür
(DbDriver.php,
v0.2.5). Kimlik bilgileri AES-256 ile şifrelenerek saklanır ve geliştirici bir
bağlantıyı yalnızca bir DBA yetki verdikten sonra görür. Paylaşılan parola olmadan
üretim veritabanı erişimi
yazısı, parolanın neden QueryProxy’de kalması gerektiğini açıklar.
Salt okunur çalışan ekipler için, yalnızca SELECT izni olan bir login ile ayrı bir
bağlantı kaydedin ve mümkünse onu bir replikaya yöneltin.
Üretim güvenliği rehberi bunu önerir.
Sonuca ne olur?
Satırlar, cursor’dan sonuç dosyasına akarken maskelenir; böylece maskesiz bir
kopya diskte hiç bulunmaz. Maskeleme kuralları bir kolon adıyla (*email* gibi)
ya da bir değerin içeriğiyle eşleşir; hiçbir kuralın eşleşmediği değer olduğu
gibi döner. Dinamik veri maskeleme fikri anlatır,
veri maskeleme dokümantasyonu ise kural türlerini ve
stratejileri listeler. Gönderimden indirmeye kadar her adım değiştirilemez bir
denetim günlüğüne yazılır.
SQL Server’da sınırlar neler?
- Sürücüyü eklemek size düşer. Varsayılan imajda, yukarıda anlatıldığı gibi, SQL Server desteği yoktur.
- Yasak listesi eksiktir. Bugün bilinen tehlikeli sözdizimini adlandırır; adlandırmadığı bir yazım geçer. SQL korumaları referansı bunu kendisi söyler: bir ifadeyi yetkilendiren şey guard değil, DBA onayıdır.
EXECUTE AS USER = 'x'kapsanmaz. Guard bu konuda hiçbir şey yapmaz.- Henüz canlı sunuculara karşı çalıştırılmadı. Referans, SQL Server davranışının guard’ın unit testlerine karşı doğrulandığını ve bu dialect’in canlı bir sunucuya karşı çalıştırılmadığını belirtir.
- Veritabanı tarafında henüz salt okunur transaction ve statement timeout yok.
İkisi de v0.3.0 için planlananlar arasında listelenir. O zamana kadar okuma
bağlantıları için yalnızca
SELECTyetkisi olan bir login kullanın. - Sunucuda saklanan kod kapsanmaz. Veritabanında zaten var olan bir stored
procedure, içindekini çalıştırır.
EXEC dbo.my_proc 1yazma olarak sınıflandırılır ve onaya gider. - Maskeleme kural tabanlıdır. Hiçbir kuralın eşleşmediği değer olduğu gibi döner; bu yüzden QueryProxy tüm kişisel verileri maskelediğini iddia etmez.
QueryProxy’ye ne zaman ihtiyacınız yok?
Veritabanının sahibi tek kişiyse ve bağlanan yalnızca kendisiyse, onaylayacak ikinci bir kişi yoktur; izinler artı salt okunur bir login yeterlidir. Gerçek veri tutmayan bir geliştirme veritabanı için de aynısı geçerlidir. Ekibinizin yalnızca daha iyi bir SQL istemcisine ihtiyacı varsa QueryProxy ile DBeaver ve DataGrip karşılaştırmasına bakın. QueryProxy, insanların önemli verilere anlık erişmesi gerektiğinde ve ikinci bir çift göz ile neyin çalıştığının kaydını istediğinizde yerini hak eder.
Bir talebin nasıl ilerlediği için onay akışına bakın ya da QueryProxy’yi bir atlama sunucusuyla karşılaştırın. PostgreSQL ekipleri PostgreSQL erişim denetimi sayfasından başlayabilir.
Sık sorulanlar
- QueryProxy SQL Server'ı kutudan çıktığı gibi destekliyor mu?
- Hayır. Varsayılan Docker imajı pdo_pgsql, pdo_mysql ve pdo_sqlite ile gelir. SQL Server'ı proxy'lemek için Dockerfile'ı Microsoft'un ODBC sürücüsü ile sqlsrv ve pdo_sqlsrv PECL eklentileriyle genişletir, ardından queryproxy/queryproxy yerine kendi imajınızı çalıştırırsınız. Eklentiler, hem web sürecini hem kuyruk işçisini (worker) çalıştıran PHP build'inde bulunmalıdır.
- Sürücü neden web sürecinde olduğu kadar işçide (worker) de olmak zorunda?
- Onaylanan sorgular web sürecinde değil, kuyruk işçisinde çalışır. İşçinin PHP build'inde SQL Server eklentileri yoksa bir talep onaylanıp ardından çalışırken başarısız olabilir.
- QueryProxy xp_cmdshell'i engelliyor mu?
- Evet. İster ifade olarak ister EXEC'ten sonra çağrılsın, her xp_* prosedürü sp_configure ve sp_oa* ile birlikte gönderim anında engellenir. Yalnızca bir string literal'in içinde geçen ad, örneğin SELECT 'xp_cmdshell', düz bir okumadır.
- Bir geliştirici çalışma anında kurulmuş bir SQL string'iyle EXEC çalıştırabilir mi?
- Metin okunamıyorsa hayır. EXEC(@sql) ve EXEC('a' + 'b') engellenir. Literal bir string ile EXEC olağan kurallarla değerlendirilir; yani içindeki WHERE'siz bir DELETE engellenir, WHERE'li olan ise yazma olarak sınıflandırılır.
- Bir SQL Server SELECT kaç satır döndürür?
- TOP'suz üst düzey bir SELECT'e TOP (1000) eklenir; CTE ve küme işlemi sorguları ise bunun yerine 10000 satırlık tavanla sınırlanır. 10000'in üzerindeki TOP, TOP 10000'e düşürülür. TOP (@v) ya da TOP 10 PERCENT gibi guard'ın hesaplayamadığı biçimler engellenir.