QueryProxy

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:

  1. Dockerfile’ı Microsoft’un ODBC sürücüsü ile sqlsrv ve pdo_sqlsrv PECL eklentileriyle genişletin.
  2. Kendi imajınızı build edin ve queryproxy/queryproxy yerine onu çalıştırın.
  3. 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 UPDATE edebilen kullanıcı, WHERE’siz bir UPDATE çalıştırabilir.
  • users tablosunu SELECT edebilen 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 bir WHERE ile (WHERE 1 = 1) yazılmış UPDATE ve DELETE reddedilir. TOP’suz üst düzey bir SELECT’e TOP (1000) eklenir, 10000’in üzerindeki TOP ise TOP 10000’e düşürülür. CTE ve küme işlemi sorgularına TOP eklenmez; onları 10000 satırlık tavan sınırlar.
  • xp_*, sp_configure, sp_oa*, sp_addlinkedserver, sp_addlinkedsrvlogin, sp_serveroption, sp_addextendedproc ve sp_execute_external_script, ister ifade olarak ister EXEC’ten sonra çağrılsın, engellenir.
  • OPENROWSET, OPENDATASOURCE, OPENQUERY ve BULK INSERT engellenir.
  • GRANT, REVOKE, DENY ve SHUTDOWN engellenir.
  • sp_prepare, sp_execute, sp_sqlexec, sp_msforeachtable ve sp_send_dbmail gibi kendilerine verilen metni çalıştıran prosedürler, argümanları ne olursa olsun engellenir.
  • THROW, RECONFIGURE, KILL ve CHECKPOINT yazma 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’siz EXEC('DELETE FROM t') engellenir ve EXEC('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 srv ve EXEC ... 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 SELECT yetkisi 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 1 yazma 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.

Gezinmek için ok tuşları, açmak için Enter.