[NISACTF 2022]babyupload

[NISACTF 2022]babyupload wp

信息搜集

进入页面:

在这里插入图片描述

尝试文件上传,但是各种后缀名我都试过了,过不去。

在源码中发现提示,存在 ./source 路径:

在这里插入图片描述

访问该路径得到源码:

from flask import Flask, request, redirect, g, send_from_directory
import sqlite3
import os
import uuidapp = Flask(__name__)SCHEMA = """CREATE TABLE files (
id text primary key,
path text
);
"""def db():g_db = getattr(g, '_database', None)if g_db is None:g_db = g._database = sqlite3.connect("database.db")return g_db@app.before_first_request
def setup():os.remove("database.db")cur = db().cursor()cur.executescript(SCHEMA)@app.route('/')
def hello_world():return """<!DOCTYPE html>
<html>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">Select image to upload:<input type="file" name="file"><input type="submit" value="Upload File" name="submit">
</form>
<!-- /source -->
</body>
</html>"""@app.route('/source')
def source():return send_from_directory(directory="/var/www/html/", path="www.zip", as_attachment=True)@app.route('/upload', methods=['POST'])
def upload():if 'file' not in request.files:return redirect('/')file = request.files['file']if "." in file.filename:return "Bad filename!", 403conn = db()cur = conn.cursor()uid = uuid.uuid4().hextry:cur.execute("insert into files (id, path) values (?, ?)", (uid, file.filename,))except sqlite3.IntegrityError:return "Duplicate file"conn.commit()file.save('uploads/' + file.filename)return redirect('/file/' + uid)@app.route('/file/<id>')
def file(id):conn = db()cur = conn.cursor()cur.execute("select path from files where id=?", (id,))res = cur.fetchone()if res is None:return "File not found", 404# print(res[0])with open(os.path.join("uploads/", res[0]), "r") as f:return f.read()if __name__ == '__main__':app.run(host='0.0.0.0', port=80)

这道题的要求就两个:看懂 python 代码;os.path.join 绝对路径拼接。

加强 python 基础

为了能更好的看懂本次 python 代码,我推荐以下文章:

python 连接数据库

Python getattr() 函数

关于python中的查询数据库内容中用到的fetchone()函数

request.files 介绍

在 Flask 框架中,request.files 是一个代表上传文件的特殊字典对象。它允许您访问用户通过 HTTP 请求上传的文件。具体来说,在 Flask 中,当您的应用程序收到一个带有文件上传的 POST 请求时,可以使用 request.files 来获取上传文件的信息。

request.files 是一个字典,它的键是文件域( input 标签的 name 属性值),而值是一个 FileStorage 对象,该对象提供了访问和操作上传文件的方法和属性。

例如,假设您的 HTML 表单中有一个文件上传域,其 name 属性为 "file"

<form action="/upload" method="post" enctype="multipart/form-data">Select image to upload:<input type="file" name="file"><input type="submit" value="Upload File" name="submit">
</form>

那么您可以通过以下方式访问上传文件:

file = request.files['file']

上面的代码将返回上传文件的 FileStorage 对象,您可以使用该对象的方法和属性来获取文件的详细信息,如文件名、内容类型、保存文件等:

filename = file.filename          # 获取上传文件的文件名
file.save('/path/to/save/file')   # 将上传文件保存到指定路径

通过 request.files,您可以轻松地处理和管理用户上传的文件数据。注意,为了使用 request.files,您的请求必须使用 enctype="multipart/form-data" 编码类型,这是用于文件上传的标准编码类型。

关于 python 的 flask 框架,在学 SSTI 模板注入时有所学习。

源码分析

# 设置了一个路由,当以 POST 方式访问 ./upload 页面时,就会触发 upload() 函数
@app.route('/upload', methods=['POST'])
def upload():if 'file' not in request.files:return redirect('/')
# 从 HTML 表单中获取 file 对象,即用户上传的文件file = request.files['file']
# 文件名中不能有小数点if "." in file.filename:return "Bad filename!", 403
# 调用 db() 函数连接数据库conn = db()cur = conn.cursor()
# 调用 uuid 模块以某种方式生成文件的 uiduid = uuid.uuid4().hextry:cur.execute("insert into files (id, path) values (?, ?)", (uid, file.filename,))except sqlite3.IntegrityError:return "Duplicate file"conn.commit()
# 将文件保存到 ./uploads/ 路径下file.save('uploads/' + file.filename)
# 返回最终保存的文件路径return redirect('/file/' + uid)

不过在此段代码中 file.save('uploads/' + file.filename) 并没有起到作用,推测原因是 uploads/ 路径不存在。

下面来看这段代码:

# 设定路由,当访问 /file/<id> 路径时触发 file 函数,其中 <id> 为用户输入的任意值,该值会被作为 file 函数的参数值
@app.route('/file/<id>')
def file(id):
# 连接数据库conn = db()cur = conn.cursor()
# 执行 SQL 语句,根据 id 查找 pathcur.execute("select path from files where id=?", (id,))
# fetchone 函数的作用在上面的博客中已提到,执行该语句后,res[0] 就是 SQL 语句查询到的 path ,根据源代码,path 就是传入的文件名res = cur.fetchone()if res is None:return "File not found", 404# print(res[0])
# os.path.join 函数拼接路径,再 open 打开文件with open(os.path.join("uploads/", res[0]), "r") as f:return f.read()

os.path.join 绝对路径拼接

os.path.join(path, *paths) 函数用于将多个文件路径连接成一个组合的路径。第一个参数通常包含了基础路径,而之后的每个参数都被当做组件拼接到基础路径后。

但是该函数有个特性:如果拼接的某个路径以 / 开头,那么包括基础路径在内的所有前缀路径都将被删除,该路径将被视为绝对路径。下面的示例揭示了开发者可能遇到的这个陷阱。

比如,上述代码中,若 res[0] 以 / 开头,则前面的 uploads/ 将被抹去,最后拼接的结果只有 res[0] 。

漏洞利用

据此,我们可以传入一个名为 “/flag” 的文件,那么最后经过路径拼接抹去前面的 uploads/ 路径,就会直接打开根目录下的 flag 文件。

当然,这种方法存在猜测性,前提是根目录下确实有一个 flag 文件。

文件名为 /flag ,文件内容任意:

在这里插入图片描述

返回结果中给出了路径:/file/de087626346e4fc390a272957aa5b88e ,那么直接访问:

在这里插入图片描述

拿到 flag 。

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

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

相关文章

【Leetcode】1154. 一年中的第几天

文章目录 题目思路代码 题目 1154. 一年中的第几天链接 思路 题目要求是给定一个字符串 date&#xff0c;它代表一个日期&#xff0c;采用标准的 YYYY-MM-DD 格式。需要计算这个日期是当年的第几天。 首先&#xff0c;我们可以通过字符串的索引来提取年、月和日的数值&…

基于YOLOv5+Deepsort 的PCB缺陷检测及计数系统

背景&#xff1a; PCB&#xff08;Printed Circuit Board&#xff0c;印刷电路板&#xff09;是电子产品中至关重要的组成部分&#xff0c;它承载着电子元器件并提供电气连接。在PCB制造过程中&#xff0c;由于工艺、材料或设备等因素的影响&#xff0c;可能会引入各种缺陷&am…

P1019 [NOIP2000 提高组] 单词接龙 刷题笔记

P1019 [NOIP2000 提高组] 单词接龙 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 思路来自 大佬 Chardo 的个人中心 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 匹配 &#xff1a; 将 第一个字符串末尾 和第二个字符串第一个开始匹配 如果 j<i这段走完了 flag还没…

Apollo自动驾驶系统:实现城市可持续交通的迈向

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 ChatGPT体验地址 文章目录 前言引言&#xff1a;1. 什么是微服务架构&#xff1f;2. 微服务架构的组成要素3. 微服务架构的挑战和解决方案4. 微服务架构的可扩展性和弹性 第二部分&#x…

两种方法求解平方根 -- 牛顿法、二分法

Leetcode相关题目&#xff1a; 69. x 的平方根 牛顿法 迭代公式&#xff1a; 以求解 a a a 的平方根为例&#xff0c;可转换为求解方程 f ( x ) f(x) f(x)的根。 f ( x ) x 2 − a f(x)x^2-a f(x)x2−a 迭代公式如下&#xff1a; x n 1 x n − f ( x n ) f ′ ( x n )…

关键字:try-catch关键字

在 Java 中&#xff0c;try-catch关键字用于异常处理。它们允许编写代码来捕获和处理异常&#xff0c;以确保程序能够在出现问题时合理地处理它们而不会崩溃。 以下是try-catch关键字的基本语法&#xff1a; 在try块中编写可能会抛出异常的代码。如果在try块中的任何代码抛出…

el-date-picker周选择器获取选择的日期范围

<el-date-pickerv-model"formData.date"type"week"format"yyyy 第 WW 周"placeholder"选择周"change"weekChange"> </el-date-picker>// 方法一&#xff1a;weekChange(val) {let startTime new Date(val.getT…

GPT3.5 改用 GPT4 价格翻了30倍 如何破局? GPT 对话成本推演

场景介绍 假设你搭建了一个平台&#xff0c;提供 ChatGPT 3.5 的聊天服务。目前已经有一批用户的使用数据&#xff0c;想要测算一下如果更换 GPT 4.0 服务需要多少成本&#xff1f; 方案阐述 如果是全切&#xff0c;最简单粗暴的方案就是根据提供 ChatGPT 3.5 消费的金额乘…

Kafka安装及简单使用介绍

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

深入解析泛型

一、泛型的诞生 在C#1 中我们还没有泛型的时候我们收集数据通常需要使用到数组&#xff0c;或者使用封装好的数组集合Hashtable ArrayList。 举个例子&#xff1a; 我们在读取文件的时候就会需要一个数组来储存读取的数据的内容 但我们并不知数据的具体长度也就无法在声明的…

对I2C总线上挂接多个AT24C02的读写操作

#include <reg51.h> // 包含51单片机寄存器定义的头文件 #include <intrins.h> //包含_nop_()函数定义的头文件 #define OP_READ1 0xa1 // 器件1地址以及读取操作,0xa1即为1010 0001B #define OP_WRITE1 0xa0 // 器件1地址以…

数据结构 模拟实现LinkedList单向不循环链表

目录 一、链表的简单介绍 二、链表的接口 三、链表的方法实现 &#xff08;1&#xff09;display方法 &#xff08;2&#xff09;size得到单链表的长度方法 &#xff08;3&#xff09;addFirst头插方法 &#xff08;4&#xff09;addLast尾插方法 &#xff08;5&#xf…