原文地址:http://blog.adm1nkyj.kr
譯者:歐巴@知道創宇404實驗室
簡介
Gnuboard是韓國Sir公司開發一套PHP+Mysql CMS程序。 本身數據結構簡單,可擴展性能強,程序運行代碼與皮膚文件分離,可擴展數據字段多,可以進行多種功能轉變,簡單安裝就可以作為BBS告示板使用,也可以下載皮膚插件變成 綜合網站,地方信息,購物,人才市場,物品交易網站。
Gnuboard stored xss
之前記錄的一個漏洞,漏洞觸發點比較有趣,而且威脅也大,所以就發到博客。
首先看一下 index.php代碼
<div style="float:left;<?php echo $lt_style ?>">
<?php
// ? ??? ?? ???? ???? ??? ???.
// ???? : latest(??, ??????, ????, ???);
// ??? ??? ????? theme/basic ? ?? ??
echo latest("basic", $row['bo_table'], 5, 25);
?>
</div>
用latest過濾之后echo輸出,如果是以前,就會跳過這個漏洞點,但是因為缺錢,所以跟了一下代碼。
跟一下lib/latest.lib.php文件
if(G5_USE_CACHE) {
$cache_file = G5_DATA_PATH."/cache/latest-{$bo_table}-{$skin_dir}-{$rows}-{$subject_len}.php";
if(!file_exists($cache_file)) {
$cache_fwrite = true;
} else {
if($cache_time > 0) {
$filetime = filemtime($cache_file);
if($filetime && $filetime < (G5_SERVER_TIME - 3600 * $cache_time)) {
@unlink($cache_file);
$cache_fwrite = true;
}
}
if(!$cache_fwrite)
include($cache_file);
}
}
if(!G5_USE_CACHE || $cache_fwrite) {
$list = array();
$sql = " select * from {$g5['board_table']} where bo_table = '{$bo_table}' ";
$board = sql_fetch($sql);
$bo_subject = get_text($board['bo_subject']);
$tmp_write_table = $g5['write_prefix'] . $bo_table; // ??? ??? ????
$sql = " select * from {$tmp_write_table} where wr_is_comment = 0 order by wr_num limit 0, {$rows} ";
$result = sql_query($sql);
for ($i=0; $row = sql_fetch_array($result); $i++) {
$list[$i] = get_list($row, $board, $latest_skin_url, $subject_len);
}
if($cache_fwrite) {
$handle = fopen($cache_file, 'w');
$cache_content = "<?php\nif (!defined('_GNUBOARD_')) exit;\n\$bo_subject='".sql_escape_string($bo_subject)."';\n\$list=".var_export($list, true)."?>";
fwrite($handle, $cache_content);
fclose($handle);
}
}
ob_start();
include $latest_skin_path.'/latest.skin.php';
$content = ob_get_contents();
ob_end_clean();
return $content;
看代碼能發現,如果存在緩存文件,那就直接包含已存在的緩存,如果沒有那就生成一個緩存文件之后,再調用緩存。
生成緩存的時候會傳入$latest_skin_url函數,$latest_skin_url函數會包含G5_SKIN_URL的值。G5_SKIN_URL的值在 common.php文件的g5_path()的函數中會包含 host頭的值,導致xss漏洞。
漏洞復現:
為了初始化緩存,先發一篇文章,然后跳轉到index.php的時候 修改host值為
"><img src=1 onerror="alert('XSS');">

PoC :
import requests
from urllib import quote
header = {"Host":"\"><img src=1 onerror=\"alert('XSS');\">"}
url = "site_url"
r = requests.get(url, headers=header)
print r.text
Gnuboard open redirect & password leak
為了參加 hacking camp的演講,準備open redirect漏洞的案例的時候,想起之前朋友挖過的gnuboard的漏洞,然后現在看了一下,雖然有補丁但是還是存在漏洞。
在 skin/member/basic/member_confirm_skin.php文件。
<form name="fmemberconfirm" action="<?php echo $url ?>" onsubmit="return fmemberconfirm_submit(this);" method="post">
<input type="hidden" name="mb_id" value="<?php echo $member['mb_id'] ?>">
<input type="hidden" name="w" value="u">
<fieldset>
?????
<span id="mb_confirm_id"><?php echo $member['mb_id'] ?></span>
<label for="confirm_mb_password">????<strong class="sound_only">??</strong></label>
<input type="password" name="mb_password" id="confirm_mb_password" required class="required frm_input" size="15" maxLength="20">
<input type="submit" value="??" id="btn_submit" class="btn_submit">
</fieldset>
</form>
可以看到在form表單里 輸出了 url,如果url改成 http://hacker.com,黑客會截取form表單里的所有的值。從上述代碼可以看到,form表單里包含了 password的值。
接著我們繼續查找從哪個文件調用了上述的member_confirm_skin.php文件。我們發現在bbs/member_confirm.php文件中調用了。
$url = clean_xss_tags($_GET['url']);
// url ??
check_url_host($url);
$url = get_text($url);
include_once($member_skin_path.'/member_confirm.skin.php');
include_once('./_tail.sub.php');
?>
但是這里看到對 url參數進行了過濾,繼續跟蹤看看check_url_host,函數是如何進行過濾的。
function check_url_host($url, $msg='', $return_url=G5_URL)
{
if(!$msg)
$msg = 'url? ? ???? ??? ? ????.';
$p = @parse_url($url);
$host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
if(stripos($url, 'http:') !== false) {
if(!isset($p['scheme']) || !$p['scheme'] || !isset($p['host']) || !$p['host'])
alert('url ??? ???? ????.', $return_url);
}
if ((isset($p['scheme']) && $p['scheme']) || (isset($p['host']) && $p['host']) || $is_host_check) {
//if ($p['host'].(isset($p['port']) ? ':'.$p['port'] : '') != $_SERVER['HTTP_HOST']) {
if ( ($p['host'] != $host) || $is_host_check ) {
echo '<script>'.PHP_EOL;
echo 'alert("url? ? ???? ??? ? ????.");'.PHP_EOL;
echo 'document.location.href = "'.$return_url.'";'.PHP_EOL;
echo '</script>'.PHP_EOL;
echo '<noscript>'.PHP_EOL;
echo '<p>'.$msg.'</p>'.PHP_EOL;
echo '<p><a href="'.$return_url.'">????</a></p>'.PHP_EOL;
echo '</noscript>'.PHP_EOL;
exit;
}
}
}
看到這里發現之前多慮了,因為發現parse_url函數基本沒有過濾。繞過方法參見下圖。

如果用這種方式構造url后,發送鏈接給會員輸入密碼,那么密碼會發送到攻擊者指定的服務器中(因為網址和實際網址一樣,所以成功欺騙的概率會更高一些)

本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/463/
暫無評論