0x00 背景
來公司差不多一年了,然而我卻依舊沒有轉正。約莫着轉正也要到九月了,去年九月來的,實習,轉正用了一年。2333
廢話不多說了,最近有其他的事要忙,很久沒有代碼審計了。難的挖不了,淺的沒意思。那就隨便選吧。
在A5找了套源碼,找找感覺。花了十來分鍾審了一下,發現了個未授權任意文件上傳。
0x01 總體了解
版本: v 1.1.3
框架: tp 5.0
目錄如下:
挺標准的tp二次開發目錄,直接看application目錄下的。
外面的幾個php文件就不解釋了。粗略的看了一下配置文件和路由。
全局過濾用了strip_sql加htmlspecialchars,tp5默認是走pdo的。除非不是故意留的坑,都不太可能會出現比較容易利用的注入點。
application里面有多個模塊。主要是admin,api,common,home四個。
admin 顧名思義是后台處理的
api 是一些接口
common 是基礎類。
home 是前端
0x02 發現任意文件上傳的接口
看了一下common和api兩個模塊,在api里面發現了這么一個接口。
看到文件application\api\Uploadify.php
public function preview(){ // 此頁面用來協助 IE6/7 預覽圖片,因為 IE 6/7 不支持 base64 $DIR = 'preview'; // Create target dir if (!file_exists($DIR)) { @mkdir($DIR); } $cleanupTargetDir = true; // Remove old files $maxFileAge = 5 * 3600; // Temp file age in seconds if ($cleanupTargetDir) { if (!is_dir($DIR) || !$dir = opendir($DIR)) { die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}'); } while (($file = readdir($dir)) !== false) { $tmpfilePath = $DIR . DIRECTORY_SEPARATOR . $file; // Remove temp file if it is older than the max age and is not the current file if (@filemtime($tmpfilePath) < getTime() - $maxFileAge) { @unlink($tmpfilePath); } } closedir($dir); } //前面的一大串,不用關注,看下面的就行了 $src = file_get_contents('php://input'); if (preg_match("#^data:image/(\w+);base64,(.*)$#", $src, $matches)) { $previewUrl = sprintf( "%s://%s%s", isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ? 'https' : 'http', $_SERVER['HTTP_HOST'],$_SERVER['REQUEST_URI'] ); $previewUrl = str_replace("preview.php", "", $previewUrl); $base64 = $matches[2]; $type = $matches[1]; if ($type === 'jpeg') { $type = 'jpg'; } $filename = md5($base64).".$type"; $filePath = $DIR.DIRECTORY_SEPARATOR.$filename; if (file_exists($filePath)) { die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}'); } else { $data = base64_decode($base64); file_put_contents($filePath, $data); die('{"jsonrpc" : "2.0", "result" : "'.$previewUrl.'preview/'.$filename.'", "id" : "id"}'); } } else { die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "un recoginized source"}}'); } }
這是一個圖片預覽的接口,通過php://input接收圖片base64編碼數據,然后解碼,寫入文件。返回圖片路徑。
正則獲取了圖片的后綴之后,簡單判斷了一下就沒有下文了。然后將獲取到的文件后綴,與base64文件數據的md5值拼接成為文件名。最后解碼數據,寫入。返回路徑
追溯一下這個api是否需要登錄?(=>等於extends)
app\api\controller\Uploadify =>app\api\controller\Base => app\common\controller\Common =>think\Controller
看了一下沒有發現有判斷權限或認證的代碼,在 app\api\controller\Base 類里面看到似乎是權限判斷的代碼:
但這里的代碼都是空的。。。
那么,整個漏洞的利用邏輯就是往http://www.example.com/index.php/api/Uploadify/preview 打一個base64的post數據包。
漏洞原理很簡單。我想這里會出現這么一個問題,大概是作者認為data:image/ 這樣的數據,只能是圖片?
0x03 漏洞影響
在官網下了一個1.0版本的,對比了一下發現,1.0版本也是存在該漏洞。左1.1.3 ,右1.0
這里的差異只是我添加的一個備注。
昨晚用fofa跑了一下,發現存在該漏洞的網站有50%以上。
0x04 漏洞修復建議
使用白名單判斷文件后綴名。
在Uploadify.php中213行到214行的代碼修改為如下:
if ($type !== 'jpeg' || $type !=='png' || $type !=='gif' || $type!=='jpg') { exit(); } if ($type === 'jpeg') { $type = 'jpg'; }
0x05 總結
搜了一下這個CMS的歷史漏洞,發現只有seebug上面的一個后台任意文件讀取漏洞。這個洞藏了很久啊。。
整個漏洞很簡單,寫篇文章記錄一下,除除博客上面的草。
之后想總結一下tp框架二次開發CMS的奇葩漏洞,不知道什么時候能總結出來。。
聲明:本文章只用於學習研究之用,禁止用於違法犯罪。