in che modo un ritorno al sistema consente a un utente malintenzionato di eludere uno stack non eseguibile?

4

Sto imparando sul ritorno agli attacchi di chiamata di sistema per una classe di sicurezza. Capisco che in questo tipo di attacco, gli attaccanti sostituiscono il valore di ritorno standard per uno stack frame con l'indirizzo di una funzione di libreria. Le diapositive della classe dicono che questo è un modo per eludere uno stack non eseguibile. Come mai? L'idea che la funzione della libreria è stata manomessa e quindi quando il frame restituisce va al codice della libreria malevola? Un ritorno all'attacco di chiamata di sistema è utile solo se la funzione di libreria è già stata danneggiata?

    
posta bernie2436 23.02.2013 - 21:04
fonte

1 risposta

4

Quando una funzione termina, l'esecuzione salta all'indirizzo che è stato salvato nello stack. Gli exploit "classici" di un buffer overflow alterano quell'indirizzo salvato in modo tale da puntare, appunto, sul contenuto del buffer dello stack che era appena sorvolato. Ciò presuppone che l'attaccante possa scegliere il contenuto del buffer e inserisce lì il codice che desidera venga eseguito.

Quando lo stack non è eseguibile, il classico exploit non funziona più. Tuttavia, il buffer può ancora essere riempito e traboccare sul resto dello stack, che include l'indirizzo di ritorno, ma anche altre cose. Considera che lo stack assomiglia a questo:

address     contents
0x07fff8c8  ...
0x07fff8c4  ...
0x07fff8c0  ...
0x07fff8bc  ...
0x07fff8b8  ...
0x07fff8b4  return address
0x07fff8b0  ...
0x07fff8ac  ...
0x07fff8a8  buffer
0x07fff8a4  buffer
0x07fff8a0  buffer
(...)
0x07fff858  buffer
0x07fff854  buffer

In questo diagramma approssimativo, lo stack cresce verso il basso (come accade nella maggior parte delle architetture); gli indirizzi sono fittizi ma realistici per un'architettura little-endian a 32 bit su un sistema simile a Unix. L'utente malintenzionato proverà, inserendo dati malintenzionati nel buffer, per ottenere questa situazione:

address     contents
0x07fff8c8  ...
0x07fff8c4  0
0x07fff8c0  0x07fff854
0x07fff8bc  0x07fff854
0x07fff8b8  ... 
0x07fff8b4  address of execlp()
0x07fff8b0  ...
0x07fff8ac  ...
0x07fff8a8  buffer
0x07fff8a4  buffer
0x07fff8a0  buffer
(...)
0x07fff858  0x0068732f
0x07fff854  0x6e69622f

Se l'attaccante può ottenere questo, quindi, quando la funzione attaccata ritorna, il puntatore dello stack è impostato su 0x07fff8b4, quindi una parola viene estratta dallo stack e interpretata come "indirizzo di ritorno", cioè il punto in cui l'esecuzione deve essere eseguita Continua. In questo caso, la CPU passa alla funzione di libreria standard execlp() (che è una funzione Unix). Questa funzione è, per definizione, situata in un'area di RAM che è suscettibile di esecuzione.

Il codice di execlp() si aspetta di trovare lo stack compilato in questo modo:

address     contents
0x07fff8c8  ...
0x07fff8c4  arg2
0x07fff8c0  arg1
0x07fff8bc  arg0
0x07fff8b8  address of calling code 

execlp() interpreterà arg0 come puntatore a una stringa di caratteri a terminazione zero che è il percorso di un file eseguibile, che verrà eseguito con execlp() . arg1 , arg2 ... devono essere puntatori ad altre stringhe che sono gli argomenti da passare al file eseguibile.

Nella nostra situazione, execlp() non ha idea di come sia stato "chiamato"; tutto ciò che sa è che ora la CPU sta entrando in esso. Trova come arg0 il valore 0x07fff854 che l'attaccante ha disposto a mettere in questo posto nello stack, con il suo buffer overflow. Quel valore, 0x07fff854 , sembra essere un puntatore all'area della RAM che in precedenza conteneva il buffer e contiene ancora i dati che l'utente malintenzionato ha inserito in essa perché mentre questa area è "libera", lo stack non è ancora stato reinserito esso. All'indirizzo 0x07ff854 , l'autore dell'attacco ha inserito le due parole a 32 bit 0x6e69622f e 0x0068732f , che è la codifica della stringa ASCII "/bin/sh" (con uno 0 terminante).

Pertanto, execlp() trova argomenti correttamente formati che lo istruiscono a eseguire una shell, e così fa.

Riepilogo: un buffer overflow che supera l'indirizzo di ritorno viene utilizzato per far saltare il codice attaccato a un posto arbitrario. L'attaccante vuole che la CPU esegua del codice che dia qualche vantaggio all'attaccante (ad esempio il codice che esegue una shell). Poiché lo stack non è eseguibile, l'attaccante non può mettere il suo codice nella pila. Ma la libreria standard è una raccolta di funzioni che sono, per loro natura, eseguibili, e alcune possono fare proprio quello che l'attaccante desidera ottenere. Quindi è sufficiente che l'attaccante renda il punto di riferimento dell'indirizzo alla funzione della libreria che corrisponde all'effetto desiderato, e lo stesso overflow del buffer può essere fatto per mettere in pila gli "argomenti" che la funzione della libreria utilizzerà, proprio al punto posto dove si aspetta quella funzione. Poiché nessuno di questi utilizza l'area dello stack come codice , solo come data , la proprietà non eseguibile dello stack non ha importanza.

Note:

  • Non è necessario passare a start di una funzione di libreria. Funziona anche il salto a metà di una funzione. Le possibilità sono quasi infinite.

  • Le cose funzionano in modo simile per gli overflow che sostituiscono i puntatori alle funzioni, ad es. vtables per oggetti C ++ nell'heap. Ciò che importa è che il codice della libreria di destinazione trovi nello stack ciò che si aspetta come argomenti.

  • Le architetture non-x86 rendono le cose un po 'più complesse perché le convenzioni di chiamata per la maggior parte delle architetture RISC (ARM, Sparc, PowerPC, Mips ...) definiscono che i primi argomenti sono presi dai registri convenzionali, non letti da lo stack. Il principio di base rimane valido, tuttavia, ma significa che è più difficile creare un codice di exploit one-size-fits-all. L'attaccante deve mettere a punto più dettagli per quanto riguarda l'applicazione esatta che attacca.

  • L'attaccante deve essere in grado di prevedere, con buona probabilità, dove verrà caricato il codice della libreria nello spazio di indirizzamento dell'applicazione. ASLR è una funzionalità di sicurezza che sceglie l'indirizzo di caricamento più o meno a caso, proprio per rendere tali giochi più difficili per l'attaccante.

risposta data 23.02.2013 - 21:51
fonte

Leggi altre domande sui tag