HTB_Dog
linux(Eazy)
总结
user.txt
.git泄露->敏感凭证泄露->1.27.1-RCE->www-data-shelll->密码重用
root.txt
sudo提权+工具代码执行
git的其它用法,比如
git log#历史coommit记录git grep -i "xxx"#git中全局查找某字段
https://github.com/backdrop/backdrop/tree/1.27.x
1.27.1-RCE,似乎是上传压缩包,自动提取到 /modules
目录中, 没有校验,导致了恶意文件上传
每一个模块都要有.info和.php,但是仅看代码对我而言也很难把握其中细节,所以尝试动态调试。本来想要VScode搭建环境然后下断点的,搜索了下相关知识,发现可以用Xdebug远程调试,
https://github.com/backdrop/backdrop/blob/1.27.x/core/modules/installer/installer.module
$items['admin/installer/manual'] = array('page callback' => 'backdrop_get_form','page arguments' => array('installer_manager_install_form'),'access callback' => 'installer_install_access','access arguments' => array(),'weight' => 25,'type' => MENU_CALLBACK,'file' => 'installer.manager.inc', );
这个表单应该就是当时上传tar.gz的入口,提交之后会上传到 /system/ajax
接口中间经过对压缩包的提取什么的
再重定向到 /core/authorize.php?batch=1&op=start&id=17
https://github.com/backdrop/backdrop/blob/1.27.x/core/modules/installer/installer.manager.inc
/** * Downloads a project given a project url. * * Either downloads the file specified in the URL to a temporary cache, or * uploads the file attached to the form, then attempts to extract the archive * into a temporary location and verify it. Instantiate the appropriate * Updater class for this project and make sure it is not already installed in * the live webroot. If everything is successful, setup an operation to run * via authorize.php which will copy the extracted files from the temporary * location into the live site. * * @param string $is_installer * Whether the project is being installed via the Project Installer UI. * * @return array * An associative array with keys: * - 'success': whether the update was successful * - 'message': an error or success message. * * @see installer_manager_install_form_validate() * @see installer_authorize_run_install() * @see system_authorized_init() * @see system_authorized_get_url() */functioninstaller_manager_download_project($url, $is_installer = FALSE) {if ($url) {$local_cache = installer_manager_file_get($url);if (!$local_cache) {returnarray('success' => FALSE,'message' => t('Unable to retrieve Backdrop project from %url.', array('%url' => $url)), ); } }elseif ($_FILES['files']['name']['project_upload']) {$validators = array('file_validate_extensions' => array(archiver_get_extensions()));$field = 'project_upload';if (!($file_info = file_save_upload($field, $validators, NULL, FILE_EXISTS_REPLACE))) {// Failed to upload the file. file_save_upload() calls form_set_error() on// failure.returnarray('success' => FALSE,'message' => t('Unable to save downloaded project into the temporary directory.'), ); }$local_cache = $file_info->uri; }else {$local_cache = NULL; }// Try to extract it.$directory = _installer_manager_extract_directory();try {$archive = installer_manager_archive_extract($local_cache, $directory); }catch (Exception$e) {returnarray('success' => FALSE,'message' => $e->getMessage(), ); }$files = $archive->listContents();if (!$files) {returnarray('success' => FALSE,'message' => t('Provided archive contains no files.'), ); }// Unfortunately, we can only use the directory name to determine the project// name. Some archivers list the first file as the directory (i.e., MODULE/)// and others list an actual file (i.e., MODULE/README.MD).$project = strtok($files[0], '/\');$archive_errors = installer_manager_archive_verify($project, $local_cache, $directory);if (!empty($archive_errors)) {returnarray('success' => FALSE,'message' => array_shift($archive_errors), ); }// Make sure the Updater registry is loaded.backdrop_get_updaters();$project_location = $directory . '/' . $project;try {$updater = Updater::factory($project_location); }catch (Exception$e) {returnarray('success' => FALSE,'message' => $e->getMessage(), ); }try {$project_title = Updater::getProjectTitle($project_location); }catch (Exception$e) {returnarray('success' => FALSE,'message' => $e->getMessage(), ); }if (!$project_title) {returnarray('success' => FALSE,'message' => t('Unable to determine %project name.', array('%project' => $project)), ); }if ($updater->isInstalled()) {returnarray('success' => FALSE,'message' => t('%project is already installed.', array('%project' => $project_title)), ); }$project_realpath = backdrop_realpath($project_location);$updater_name = get_class($updater);// If the permissions of the downloaded file match those of the settings.php// directory, go ahead and install the module directly.if (fileowner($project_realpath) == fileowner(conf_path()) || filegroup($project_realpath) == filegroup(conf_path())) {module_load_include('inc', 'installer', 'installer.authorize');$filetransfer = newFileTransferLocal(BACKDROP_ROOT);if ($is_installer) {// Initialize some variables in the Batch API $context array./* @var Updater $updater */$updater = new$updater_name($project_realpath);try {if ($updater->isInstalled()) {// This is an update.$updater->update($filetransfer); }else {$updater->install($filetransfer); } }catch (UpdaterException $e) {returnarray('success' => FALSE,'message' => t('Error installing / updating. Error: @error', array('@error' => $e->getMessage())), ); } }else {// Start the batch process to install the module but suppress redirecting// to authorize.php, return the redirect instead.$redirect_callback = backdrop_is_ajax() ? FALSE : 'backdrop_goto';installer_authorize_run_install($filetransfer, $project, $updater_name, $project_realpath, $redirect_callback);// Assemble the authorize.php path and go to it to complete the batch.$batch = &batch_get();returnarray('success' => TRUE,'redirect' => array($batch['url'], array('query' => array('op' => 'start', 'id' => $batch['id']))), ); } }// If permissions differ, redirect to authorize.php to copy the file as a// different system user.else {if ($is_installer) {returnarray('success' => FALSE,'message' => t('Permissions are not set up properly.'), ); }else {$path = backdrop_get_path('module', 'installer') . '/installer.authorize.inc';system_authorized_init('installer_authorize_run_install', $path, array($project, $updater_name, $project_realpath), t('Update manager'));returnarray('success' => TRUE,'redirect' => system_authorized_get_url(), ); } }returnarray('success' => TRUE, );}
https://github.com/backdrop/backdrop/blob/1.27.x/core/authorize.php
https://github.com/backdrop/backdrop/blob/1.27.x/core/includes/batch.inc
https://github.com/backdrop/backdrop/blob/1.27.x/core/modules/installer/installer.authorize.inc
参考
wp:
https://4xura.com/ctf/htb/htb-writeup-dog
git-dumper
https://github.com/arthaud/git-dumper
Backdrop CMS 1.27.1:Authenticated-RCE
https://www.exploit-db.com/exploits/52021
php项目本地调试环境搭建
环境准备:
php项目
phpstudy提供环境(之前用来做过pikachu靶场)apache+php7.3.4nts
chrome/firefox扩展插件xdebug helper
vscode
phpstudy用来运行php项目,并在php.ini中加载xdebug,vhosts用来设置程序通信响应时间
vscode用来对代码下断点,搭建debug配置,并动态调试
chrome用来访问项目网址,做正常的网页端操作,如上传文件等,并启动xdebug helper
一、项目运行
先根据官方文档
https://docs.backdropcms.org/documentation/installation-instructions
先运行起来php项目
1.将项目根目录放入phpstudy运行目录下
WWWxxx
2.配置settings.php
$database = 'mysql://root:123456@localhost/root';$database_prefix = '';
3.访问install.php
http://localhost:83/backdrop/backdrop/core/install.php
设置好账号密码就成功了
刚好浏览器下载一个扩展插件xdebug helper,保持启用状态即可
二、php_xdebug配置
如果phpstudy自带XDebug组件的话,参考
https://blog.csdn.net/hawkczj/article/details/127601733
或者去官网 https://xdebug.org/ 下载,是一个dll文件,也就改一下php.ini配置而已
1.配置xdebug
去phpstudy的对应php版本(我的是7.3.4nts)的php.ini配置如下:
[Xdebug]zend_extension="D:phpstudy_prophp_xdebug-3.1.2-7.3-vc15-nts-x86_64.dll" ; Windows 下一般为这个,确保路径正确xdebug.mode=debugxdebug.start_with_request=yesxdebug.discover_client_host=1xdebug.client_port=9003 ; 默认是9003(VSCode使用的端口)xdebug.client_host=127.0.0.1 ; 可选,建议设置为你电脑的IP或127.0.0.1
重启apache服务
2.vscode配置php debug
ctrl+shift+d选择创建launch.json->选择php即可,修改如下:
"configurations":[{// "name": "Listen for Xdebug",// "type": "php",// "request": "launch",// "port": 9003"name":"远程调试","type":"php","log":true,"request":"launch","port":9003,"pathMappings":{"D:/phpstudy_pro/WWW/backdrop/backdrop":"${workspaceFolder}/"},// "hostname": "192.168.1.10"},
pathMappings,左边是phpstudy项目目录,右边是Vscode的工作目录
因为我的工作目录就是那个项目目录,所以不用变
之后vscode下断点后,调试时点击左上角的Listen for Xdebug
最后的最后,不需要开启系统代理走9003,因为它从PHP走,通过socks去连接,开系统代理反而会冲突
每次对php.ini操作后,记得重启apache
xdebug.dll一定要下载统一版本的
localhost还是127.0.0.1访问,无所谓的啊,不用纠结,原配置里的也不用更改(如果是本地调试的话)
PS:
但是会存在一个问题,那就是由于长时间不操作,它会断开连接的
浏览器会显示500,vscode这边会显示connection 78: read ECONNRESET
,php.ini添加下处理深度和时间,记得重启apache
xdebug.max_nesting_level=500xdebug.remote_timeout=300xdebug.remote_connect_back=1
但是尝试了之后,好像并不是给很长时间,所以我想到快速过一遍,日志记录下
顺便保留调用堆栈信息
xdebug.log="D:/phpstudy_pro/1.log.txt" ; Xdebug 调试日志路径xdebug.log_level=10 ; 设置日志等级为详细(包含堆栈信息)//下面这个不管用//xdebug.remote_log = "D:/phpstudy_pro/htdocs/xdebug_remote.log" ; 输出 Xdebug 远程调试日志
好像不管用,后来参照了下
https://blog.csdn.net/m0_48108919/article/details/120585277
对于vhosts.com配置文件配置
</Directory> FcgidIOTimeout 3000 #程序响应超时时间 FcgidConnectTimeout 3000 #与程序通讯的最长时间 ... ErrorDocument 510 /error/510.html</VirtualHost>
重启apache
但是后面的话,mysql也有话讲,说来说去就是session过期了
那只能把前面的日志解决了,发现是文件目录权限的问题,导致写不进去文件,所以提前创建好,设置好目录/文件权限即可
流程探究?
只需要对authorize.php、update.php下断点即可,因为其它的inc后缀的也下不了,先不开调试,等登录后,上传文件的时候再开。
如果是实时看的话,断点的问题是一个痛点,它并不能快速定位到其它有用的地方,比如.inc
初步来看是
由authrize.php->module.inc,它中间还额外检查了session是否变动,然后调试就断开了。。。
(用 .php 做后缀可以用web服务器解释从而避免将 .inc 文件直接在浏览器中显示出来,提高安全性 )
生成的日志调用文件懒得看了,突然也没那么想探究了/(ㄒoㄒ)/~~
等到gpt冷却好了,喂给它帮忙分析下吧,╮(╯▽╰)╭
参考
vscode+xdebug+phpstudy调试环境搭建:
https://blog.csdn.net/hawkczj/article/details/127601733
https://juejin.cn/post/7201509055713493049#heading-4
https://xdebug.org/
原文始发于微信公众号(羽泪云小栈):HTB_Dog(思路)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论