前兩天發現的寶藏網站:https://php.mengsec.com/
在github上面找到了源代碼:https://github.com/Xyntax/1000php,可以在自己的服務器上面搭建
跟數據結構學習一樣,每天跟着上面前輩們的案例進行審計,打基礎+學習思路
1,BlueCMS v1.6 sp1 ad_js.php SQL注入漏洞
使用seay自動審計工具

可以看到第一條可能出現的漏洞點就是ad_js.php
我們跟進去看,

經過getone函數在數據庫里面查詢出結果並賦值給$ad變量,同時可以看到$ad_id沒有包裹引號

getone函數是在數據庫里面進行查詢的函數
mysqli_fetch_array() 函數從結果集中取得一行作為關聯數組,或數字數組,或二者兼有。也就是從數據庫中查詢。
我們往上看$ad_id變量的輸入位置是否有過濾。

可以看到對於GET方法輸入的ad_id變量僅僅是使用trim函數去除了輸入值兩邊的空格,此外就沒有另外的過濾了,所以該點確實存在SQL注入漏洞。
真實環境下利用很簡單,使用union聯合注入即可出數據
修復方法:$ad_id = !empty($_GET['ad_id']) ? intval($_GET['ad_id']) : '';
將輸入的數據強行轉換成整型
2,Discuz!7.2/X1 第三方插件SQL注入及持久型XSS漏洞
這里分析SQL注入漏洞,插件是由Discuz!認證的(http://addons.discuz.com/workroom.php)第三方開發團隊“潮流少年工作室 Teen Studio”出品的心情牆插件(http://www.discuz.net/forum.php?mod=viewthread&tid=1632898)
因為去找漏洞插件太麻煩了,我這里直接貼上漏洞源代碼吧
elseif($action == 'edit_mood' && moodid) {
//moodid未初始化,直接代入sql查詢
$check = $db->result_first("SELECT * FROM {$tablepre}moodwall WHERE id='$moodid' AND uid='$discuz_uid'");
if(!$check || !$moodid) {
showmessage('moodwall:moodwall_inc_php_2', 'plugin.php?id=moodwall&action=user_mood');
}
$sql = "SELECT * FROM {$tablepre}moodwall WHERE id='$moodid'";
$query = $db->query($sql);
$moodlist_edit = array();
while($mood_edit = $db->fetch_array($query)) {
$moodlist_edit[] = $mood_edit;
}
可以看到$moodid變量在單引號包裹下代入$sql語句進行查詢
$sql = "SELECT * FROM {$tablepre}moodwall WHERE id='$moodid'";
但是在這里漏洞的發現者也說了,需要網站magic_quotes_gpc=off,在magic_quotes_gpc=On的情況下,如果輸入的數據有單引號(’)、雙引號(”)、反斜線()與 NULL(NULL 字符)等字符都會被加上反斜線。
不過實際上還可以有寬字節注入等特殊情況對網站進行注入
3,ecshop SQL注射漏洞
因為沒有詳細的ecshop版本信息,所以同樣不進行源碼的下載,在wooyun大大的基礎上直接進行分析
在include_libcommon.php中存在如下函數,get_package_info函數
function get_package_info($id)
{
global $ecs, $db,$_CFG;
$now = gmtime();
$sql = "SELECT act_id AS id, act_name AS package_name, goods_id , goods_name, start_time, end_time, act_desc, ext_info".
" FROM " . $GLOBALS['ecs']->table('goods_activity') .
" WHERE act_id='$id' AND act_type = " . GAT_PACKAGE;
$package = $db->GetRow($sql);
/* 將時間轉成可閱讀格式 */
if ($package['start_time'] <= $now && $package['end_time'] >= $now)
{
$package['is_on_sale'] = "1";
}
else
{
$package['is_on_sale'] = "0";
}
$package['start_time'] = local_date('Y-m-d H:i', $package['start_time']);
$package['end_time'] = local_date('Y-m-d H:i', $package['end_time']);
$row = unserialize($package['ext_info']);
unset($package['ext_info']);
if ($row)
{
foreach ($row as $key=>$val)
{
$package[$key] = $val;
}
}
$sql = "SELECT pg.package_id, pg.goods_id, pg.goods_number, pg.admin_id, ".
" g.goods_sn, g.goods_name, g.market_price, g.goods_thumb, g.is_real, ".
" IFNULL(mp.user_price, g.shop_price * '$_SESSION[discount]') AS rank_price " .
" FROM " . $GLOBALS['ecs']->table('package_goods') . " AS pg ".
" LEFT JOIN ". $GLOBALS['ecs']->table('goods') . " AS g ".
" ON g.goods_id = pg.goods_id ".
" LEFT JOIN " . $GLOBALS['ecs']->table('member_price') . " AS mp ".
"ON mp.goods_id = g.goods_id AND mp.user_rank = '$_SESSION[user_rank]' ".
" WHERE pg.package_id = " . $id. " ".
" ORDER BY pg.package_id, pg.goods_id";
$goods_res = $GLOBALS['db']->getAll($sql);
$market_price = 0;
可以看到$sql語句里面代入了輸入的$id,我們再定位誰調用了get_package_info函數,在系統的lib_order.php中。
function add_package_to_cart($package_id, $num = 1)
{
$GLOBALS['err']->clean();
/* 取得禮包信息 */
$package = get_package_info($package_id);
if (empty($package))
{
$GLOBALS['err']->add($GLOBALS['_LANG']['goods_not_exists'], ERR_NOT_EXISTS);
return false;
}
可以看到調用get_package_info函數賦值給了$package變量,而$package_id變量是傳遞給add_package_to_cart函數的,在該函數中也沒有看到有對變量的過濾,尋找調用add_package_to_cart函數的文件
在flow.php中存在可控的輸入源
$package = $json->decode($_POST['package_info']);
/* 如果是一步購物,先清空購物車 */
if ($_CFG['one_step_buy'] == '1')
{
clear_cart();
}
/* 商品數量是否合法 */
if (!is_numeric($package->number) || intval($package->number) <= 0)
{
$result['error'] = 1;
$result['message'] = $_LANG['invalid_number'];
}
else
{
/* 添加到購物車 */
if (add_package_to_cart($package->package_id, $package->number))
{
if ($_CFG['cart_confirm'] > 2)
而在這里$package->package_id是我們可以控制的輸入源,根據剛才函數調用的過程,對於我們的這個輸入並沒有其余的過濾,可知存在SQL注入漏洞
4,Discuz!漫游插件API本地包含漏洞
先上代碼 manyou/api/class/MyBase.php
128: function parseRequest() {
131: $request = $_POST;
132: $module = $request['module'];
133: $method = $request['method'];
...
174: return $this->callback($module, $method, $params);
175: }
177: function callback($module, $method, $params) {
...
191: @include_once DISCUZ_ROOT.'./manyou/api/class/'.$module.'.php';
在parseRequest函數里面,可以看到最后return調用了callback函數,並且傳入的三個參數都是我們可以控制的輸入,而callback函數里面使用include_once函數包含了當前路徑下的傳遞的$module.php文件
PHP中文件包含函數有以下四種:
require()
require_once()
include()
include_once()
include和require的區別在於include在包含的時候出現錯誤的時候,會拋出一個警告,然后程序繼續運行,而require函數在出現錯誤的時候,會直接報錯並且退出程序的執行
require_once和include_once這兩個函數與前兩個不同的地方在於,這兩個函數只包含一次,適合於腳本執行期間同一個文件可能被包括一次以上的情況時,你想確保它只包含一次以避免函數重定義,變量重新賦值等問題
參考自:https://www.freebuf.com/articles/web/182280.html
在這里我們可以控制$module變量,但是這里是有限制的文件包含,因為在后面加上了.php的后綴,當我們想包含當前文件夾任意文件的時候,如果magic_quotes_gpc = Off php版本<5.3.4,我們可以使用%00截斷的方式,當然還有其他很多的方式可以繞過這個限制,如果在這里還存在目錄穿越漏洞的話,我們就可以包含服務器任意文件了,而不是限制在這個文件夾下。
5,PHPCMS通殺XSS
這里是一個反射型XSS漏洞,在我要報錯功能頁下,過濾不嚴格
http://**.**.**.**/error_report/error_report.php?title=1&contentid=1"><script>alert(/xss/)</script>
反射型XSS漏洞比較容易通過掃描器黑盒直接發現,只需要將尖括號,單雙引號等提交到web服務器,檢查返回的HTML頁面里面有沒有保留原來的特殊字符即可判斷。
在白盒審計中,我們只需要尋找帶有參數輸出函數,然后根據輸出函數對輸出內容回溯輸入參數,觀察有沒有進行經過過濾
6,phpcms 2008 sp4 爆路徑及任意文件刪除漏洞
漏洞文件是corpandresize/config.inc.php
$tmp = $_COOKIE['tmp'];
define("TMP_PATH", $tmp);
在cookie參數中獲取tmp,同時定義TMP_PATH等於變量tmp的值
使用到TMP_PATH的位置是corpandresize/process.php
@unlink(TMP_PATH.'/'.$thumbfile);
這里使用unlink函數刪除文件,我們可以使用%00截斷刪除我們想要刪除的任意文件
如在cookie中添加tmp=../index.php%00,按照上面的分析過程,就可以刪除首頁文件
7,phpcms2008本地文件包括及利用(執行任意SQL腳本)
漏洞文件存在於wap/index.php
代碼如下:
<?php
include '../include/common.inc.php';
include './include/global.func.php';
$lang = include './include/lang.inc.php';
if(preg_match('/(mozilla|m3gate|winwap|openwave)/i', $_SERVER['HTTP_USER_AGENT']))
{
header('location:../');
}
wmlHeader($PHPCMS['sitename']);
$action = isset($action) && !empty($action) ? $action : 'index';
if($action)
{
include './include/'.$action.'.inc.php';
}
$html = CHARSET != 'utf-8' ? iconv(CHARSET, 'utf-8', $html) : $html;
echo str_replace('<br/>', "<br/>\n", $html);
wmlFooter();
?>
可以看到在這一段代碼里有:
$action = isset($action) && !empty($action) ? $action : 'index';
if($action)
{
include './include/'.$action.'.inc.php';
}
isset() 函數用於檢測變量是否已設置並且非 NULL。在這里即檢測$action是否設置,同時檢測$action是否為空,空的話就賦值為index,非空即傳入值,接着就是包含傳入的$action.inc.php文件,對於輸入的$action沒有進行過多的檢測
可以包含存在sql語句的php文件,執行任意sql語句來對漏洞進行利用
例如包含目錄include\fields\areaid 下任一文件,執行任意SQL腳本。
比如field_add.inc.php文件,我們只需要傳入的$action=fields/areaid/field_add,field_add.inc.php文件代碼為:
<?php if(!$maxlength) $maxlength = 255; $maxlength = min($maxlength, 255); $sql = "ALTER TABLE `$tablename` ADD `$field` VARCHAR( $maxlength ) NOT NULL DEFAULT '$defaultvalue'"; $db->query($sql); ?>
在這里我們只需要傳入$tablename變量就可以執行$sql語句進行查詢
最后的payload為:http://www.phpcms.cn/wap/index.php?action=../../include/fields/areaid/field_add&tablename=xx
8,Ecshop2.7.2持久型XSS(可獲得管理員帳號)

可以看到當POST傳輸的數據extend_field_index沒有任何的過濾就進入數據庫進行更新了。
這里的輸入是密碼保護問題這一項,我們可以在密碼保護問題里輸入XSS,但是后台查看會員資料是不顯示密碼保護問題的,所以這里必須要網站后台添加了新的 “會員注冊項”時,后台查看資料就會顯示了,顯示了之后就可以進行XSS攻擊了。
這里不懂的地方是原漏洞作者導入外部js的時候,js文件里面的內容是Ajax:
Ajax.call('privilege.php?act=update','id=1&user_name=heihei&email=10001@**.**.**.**','',"POST","JSON");


而不是寫入外部js盜取管理員cookie,以后明白了再補充這里。
