前兩天發現的寶藏網站: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,以后明白了再補充這里。