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:
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“:
Per ogni programma in esecuzione, viene creata in “/proc” una cartella chiamata con il nome del PID (processID):
Per analizzare la memoria di un processo in esecuzione, dobbiamo leggere le informazioni presenti negli indirizzi di memoria specificati nel file “/proc/[pid]/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:
Utilizzando il debugger “gdb“, 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”):
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.
Una risposta