Atak XSS oraz przejęcie sesji admina – Skrypt Boost Masterservera

Podczas testów korzystałem z wersji ściągniętej z http://playboard.eu/threads/master-server-boost-webstats.141/ Kilka przykładów stron korzystających z tego skryptu http://playboard.eu/boost/ http://plsetti.pl/boost/ W pliku cron.php skrypt pobiera informacje o serwerach przy pomocy
$data = $newServer->serverInfo($row['address']);
Sama metoda nie jest szczególnie interesująca , jedyne co nas interesuje to to że informacje czyli hostname i mapa są zwracane bez żadnej filtracji.
static function serverInfo($server) {
list($ip,$port) = explode(":", $server);
$fp = @fsockopen('udp://'.$ip, $port);
if($fp) {
stream_set_timeout($fp, 2);
fwrite($fp,"\xFF\xFF\xFF\xFFTSource Engine Query\0\r");
$temp = fread($fp, 4);
$status = socket_get_status($fp);
if($status['unread_bytes']>0) {
$temp = fread($fp, $status['unread_bytes']);
$version = ord(self::getChar($temp));
$array = array();
$array['status'] = "1";
if($version == 109) {
$array['ip'] = self::getString($temp);
$temp = substr($temp, 1);
$array['hostname'] = self::getString($temp);
$temp = substr($temp, 1);
$array['mapname'] = self::getString($temp);
$temp = substr($temp, 1);
self::getString($temp);
$temp = substr($temp, 1);
self::getString($temp);
$temp = substr($temp, 1);
$array['players'] = ord(self::getChar($temp));
$array['maxplayers'] = ord(self::getChar($temp));
} elseif($version == 73) {
self::getChar($temp);
$array['hostname'] = self::getString($temp);
$temp = substr($temp, 1);
$array['mapname'] = self::getString($temp);
$temp = substr($temp, 1);
self::getString($temp);
$temp = substr($temp, 1);
self::getString($temp);
$temp = substr($temp, 3);
$array['players'] = ord(self::getChar($temp));
$array['maxplayers'] = ord(self::getChar($temp));
}
} else {
$array['hostname'] = 'Brak nazwy serwera';
$array['mapname'] = '-';
$array['players'] = '0';
$array['maxplayers'] = '0';
$array['status'] = '0';
}
}
return $array;
}
W kolejnej linii wrzucamy dane do mysql
mysql_query("UPDATE `servers` SET `hostname` = '".mysql_real_escape_string($data['hostname'])."', `players` = '".mysql_real_escape_string($data['players'])."', `maxplayers` = '".mysql_real_escape_string($data['maxplayers'])."', `map` = '".mysql_real_escape_string($data['mapname'])."', `status` = '".intval($data['status'])."' WHERE `id` = {$row['id']}");
dane są filtrowane poprzez mysql_real_escape_string wiec nie możemy używać znaków \x00, \n, \r, \, ’, ” i \x1a. Przy wyświetlaniu dane ponownie nie są filtrowane.
echo '

'.$num.'
'.$row['hostname'].'
'.$row['address'].'
'.$row['map'].'
'.$newMain->showbar($row['players'], $row['maxplayers']).'
'.$thisdate.'
'.$row['rounds'].'
';
Dzięki temu wszystkiemu jeśli w nazwie serwera lub w nazwie mapy wrzucimy odpowiedni kod zostanie on zinterpretowany przez przeglądarke i wykonany. np.
pomimo pominięcia ” w nazwie pliku ( tego znaku nie możemy używać ) plik zostanie poprawnie wczytany a kod w nim wykonany Co dalej ? Warto przyjrzeć się jak jest sprawdzane logowanie do panelu admina
if(isset($_COOKIE["adminhash"]) AND $_COOKIE["adminhash"] != $auth[2] OR !isset($_COOKIE["adminhash"])) {
require_once "include/admin/admin_auth.php";
}
całość opiera się na pliku cookies z hashem. Ustawianie cookies odbywa się bardzo prosto
if(!empty($_POST['login']) AND !empty($_POST['password'])) {
if($_POST['login'] == $auth[0] AND md5($_POST['password']) == $auth[1]) {
setcookie("adminhash", $auth[2], time()+2592000, "/");
header("Location: admin.php");
} else {
$showmsg = $newMess->into_msg("2", "Nieprawidłowy login lub hasło!", "2");
}

}
widać tutaj że w cookie adminhash ustawiamy wartość hashu sprawdzaną podczas logowania się do panelu. W kodzie wyżej jest jeden błąd pozwalający na wykradnięcie hashu i wykorzystanie go do zalogowania się do panelu admina bez znajomości hasła czy loginu. Jak te błędy poprawić ? W sumie jest to bardzo proste. Aby załatać 1 błąd wystarczy podczas wyświetlania danych użyć htmlentities np.
echo '

'.$num.'
'.htmlentities( $row['hostname'] ).'
'.$row['address'].'
'.htmlentities( $row['map'] ).'
'.$newMain->showbar($row['players'], $row['maxplayers']).'
'.$thisdate.'
'.$row['rounds'].'
';
drugi błąd polega na tym że na cookies nie jest ustawiana flaga httponly dzięki czemu javascript ma do nich dostęp wystarczy zamiast
setcookie("adminhash", $auth[2], time()+2592000, "/");
użyć
setcookie("adminhash", $auth[2], time()+2592000, "/", null, null, true );

12 komentarzy o “Atak XSS oraz przejęcie sesji admina – Skrypt Boost Masterservera

  1. A co z cssetti.pl, csadv.pl, cs-boost.pl?
    I jak sprawdzić czy dana strona ma ten „bug”?

  2. Podobno playboard twierdzi że tego buga nie ma i zamawiane przez nich instalacje są na nowym skrypcie ma ktoś do niego download?

  3. Właściciel plsetti.pl/boost i bodajże csadv twierdzą że nie ma już tego bugu, mógłbyś sprawdzić lub pokazać mniej więcej jak zobaczyć czy to działa?

  4. Naturalne jest że po opublikowaniu tego instalka została poprawiona wiadomo też że niektóre serwisy były zabezpieczone wcześniej

Dodaj komentarz

Witryna wykorzystuje Akismet, aby ograniczyć spam. Dowiedz się więcej jak przetwarzane są dane komentarzy.