Linux: memoria e analisi a run-time

In tutte quelle circostanze in cui è necessario preservare la quantità di RAM disponibile in un sistema, è fondamentale sapere come identificare quali sono i processi che la stanno utilizzando, e quindi, cosa stanno memorizzando al suo interno.

 
Chiunque amministra un sistema, avrà inoltre dovuto affrontare situazioni in cui determinate applicazioni, allocando quantità smisurate di memoria, hanno causato rallentamenti lato server o addirittura blocchi a causa di una condizione di tipo Out-Of-Memory:

memory_oom

Ogni qualvolta viene avviato un programma, Linux crea un’area di memoria e l’assegna al processo che la utilizza.

In questa sezione, vengono salvate diverse istruzioni (come quelle relative al processo di linking e degli instruction codes), i dati che gestisce l’applicazione (nella sezione .bss quelli non inizializzati ed in .data tutti quelli che hanno pre-configurato un valore), quindi lo stack, l’heap, ecc.

Tutte queste informazioni, insieme ad altri elementi, come i descrittori dei file che stà utilizzando quel determinato processo, e gli indirizzi delle areee di memoria mappate, vengono esposte all’utente tramite lo pseudo-filesystem “proc“:

memory_proc

Per ogni programma in esecuzione, viene creata in “/proc” una cartella chiamata con il nome del PID (processID):

memory_ps_proc
Per analizzare la memoria di un processo in esecuzione, dobbiamo leggere le informazioni presenti negli indirizzi di memoria specificati nel file “/proc/[pid]/maps“:

memory_maps

Facendo particolarmente attenzione a tutto ciò viene scritto nell’heap e nello stack, poichè in essi sono contenuti gli elementi dati utilizzati dall’applicazione.

Ecco quindi un esempio pratico, dove per capire il motivo per cui un processo PHP stà utilizzando circa 200Mb di memoria “privata”, analizzerermo le stringhe che ha allocato in memoria.

Collegandoci via SSH al server ed utilizzando l’applicazione “ps”, identifichiamo il processo:

memory_processo

Utilizzando il debuggergdb“, dopo esserci “agganciati” al processo con il comando:

gdb --pid [PID]

potremo fare un dump di tutte le locazioni di memoria presenti nel file “/proc/[pid]/maps”, eseguendo questa istruzione per ciascun indirizzo:

dump binary memory /tmp/file_da_salvare start_addr end_addr

Nel caso in cui “gdb” non fosse presente sul sistema, potete installarlo in questo modo:

Per distribuzioni basate su Debian GNU/Linux (come Ubuntu, Kali, ecc.)

sudo apt-get update
sudo apt-get install gdb

Nel caso in cui state operando in ambienti basati su RedHat (quindi CentOS, Fedora, ecc.)

yum install gdb

Per velocizzare l’operazione, potete utilizzare questo bash script, che esegue in automatico tutti i dump necessari, memorizzandoli in una cartella chiamata con il nome del PID del processo:

#!/bin/bash

mkdir $1
cd $1
grep rw-p /proc/$1/maps  \
| awk '{print $1}' \
| sed 's/-/ /' \
| while read mem_start mem_end; do gdb --pid $1 --batch-silent -ex "dump memory $mem_start-$mem_end.dump 0x$mem_start 0x$mem_end"; done

Nel nostro caso, per cui, basterà digitare come utente “root”:

./memory_dump.sh PID

Ad esecuzione terminata, troveremo tutti i dump pronti per essere analizzati.

E’ opportuno iniziare da quelli che occupano maggiore spazio disco, e per farlo possiamo utilizzare l’applicazione “strings” (dal pacchetto “binutils”):

memory_strings

L’obiettivo è cercare stringhe ricorrenti, quindi URL che si ripetono centinaia di volte, percorsi di cartelle, ecc.

Applicando questa tecnica, determineremo in maniera estremamente semplice, che la memoria contiene perlopiù queste stringhe, che occupano centinaia di MB di RAM:

_site_transient_timeout_brute_loginable_71a723f1c67a9bd7d0e5408d
1433526978
ansient_`+
_site_transient_brute_loginable_71a723f1c67a9bd7d0e5408d8afe4082
a:4:{s:6:"status";s:7:"blocked";s:3:"msg";s:43:"This IP is currently blocked (**.59.110.68)";s:17:"seconds_remaining";i:2100;s:6:"expire";i:1433526978;}
tly bl
.68)";s:p,
_site_transient_timeout_brute_loginable_fb3b10dabb9a627412b43fa5
1433526978
ansient_
_site_transient_brute_loginable_fb3b10dabb9a627412b43fa5a03b4351
a:4:{s:6:"status";s:7:"blocked";s:3:"msg";s:43:"This IP is currently blocked (**.59.110.68)";s:17:"seconds_remaining";i:2096;s:6:"expire";i:1433526978;}
tly blP.
.68)";s:
_site_transient_timeout_brute_loginable_981e14ce1f40050e6a7a4a3c
1433526978
ansient_
_site_transient_brute_loginable_981e14ce1f40050e6a7a4a3c98724616
a:4:{s:6:"status";s:7:"blocked";s:3:"msg";s:43:"This IP is currently blocked (**.59.110.68)";s:17:"seconds_remaining";i:2092;s:6:"expire";i:1433526978;}
tly bl
.68)";s:
_site_transient_timeout_brute_loginable_11622be1cacb9e14a61e7561
1433526978
ansient_
_site_transient_brute_loginable_11622be1cacb9e14a61e756145e56ad3
a:4:{s:6:"status";s:7:"blocked";s:3:"msg";s:43:"This IP is currently blocked (**.59.110.68)";s:17:"seconds_remaining";i:2088;s:6:"expire";i:1433526978;}
tly blp1
.68)";s: 1
_site_transient_timeout_brute_loginable_96493ea8186961f811572b06
1433526978
ansient_

In questo caso, il problema è stato generato da un attacco di tipo brute-force verso un dominio su cui è attivo il CMS WordPress, ed in cui è attivo il plugin “BruteProtect”.

 
In memoria c’è scritto anche l’indirizzo IP dell’attacker, e controllando i log degli accessi del servizio web, individueremo il sito responsabile.

1 Comment

Post a Comment

56 − 49 =

*

Accedi

Password dimenticata?