De1CTF-2019部分wp
目錄
- Misc1——We1come
- Misc2——Mine Sweeping
- Web1——SSRF Me
- Crypto1——xorz
去De1CTF劃了劃水,發(fā)現(xiàn)自己是真的菜━┳━ ━┳━
Misc1——We1come
https://t.me/De1CTF ,需要加Telegram群,需要VPN,群里有發(fā)簽到的flag
Misc2——Mine Sweeping
下載下來是一個掃雷游戲
在沒有雷的地方組成的其實是一個二維碼,因為踩雷后不會重置雷的位置,所以爆破每一個點是否有雷就可以了。表示此生不再想玩掃雷了。
最后得到了大概是這樣的布局
寫個腳本畫出來
最后掃碼得到網(wǎng)址,訪問即可得到flag
Web1——SSRF Me
SSRF(Server-Side Request Forgery:服務(wù)器端請求偽造) 是一種由攻擊者構(gòu)造形成由服務(wù)端發(fā)起請求的一個安全漏洞。一般情況下,SSRF是要目標(biāo)網(wǎng)站的內(nèi)部系統(tǒng)。(因為他是從內(nèi)部系統(tǒng)訪問的,所有可以通過它攻擊外網(wǎng)無法訪問的內(nèi)部系統(tǒng),也就是把目標(biāo)網(wǎng)站當(dāng)中間人)
源碼如下
#! /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 = actionself.param = paramself.sign = signself.sandbox = md5(ip)if(not os.path.exists(self.sandbox)): #SandBox For Remote_Addros.mkdir(self.sandbox)def Exec(self):result = {}result['code'] = 500if (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'] = respelse:print resptmpfile.write(resp)tmpfile.close()result['code'] = 200if "read" in self.action:f = open("./%s/result.txt" % self.sandbox, 'r')result['code'] = 200result['data'] = f.read()if result['code'] == 500:result['data'] = "Action Error"else:result['code'] = 500result['msg'] = "Sign Error"return resultdef checkSign(self):if (getSign(self.action, self.param) == self.sign):return Trueelse: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_addrif(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 Trueelse:return Falseif __name__ == '__main__':app.debug = Falseapp.run(host='0.0.0.0',port=80)說實話題目不是很難,就是代碼有點長,要好好分析下代碼邏輯。
首先可以知道,這段代碼的主要的一個入口是在這里
@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_addrif(waf(param)):return "No Hacker!!!!"task = Task(action, param, sign, ip)return json.dumps(task.Exec())通過訪問/De1ta,會去獲取cookie中的action和sign兩個參數(shù),同時還會獲得一個url傳參param。然后會去初始化一個Task對象,并且執(zhí)行Task對象的Exec方法
然后執(zhí)行Exec方法就看到調(diào)用了checkSign這個方法
def checkSign(self):if (getSign(self.action, self.param) == self.sign):return Trueelse:return False他會去將我們傳入的sign和getSign(self.action, self.param)比較,相等才能執(zhí)行后面的關(guān)鍵代碼
def getSign(action, param):return hashlib.md5(secert_key + param + action).hexdigest()這個sign我們還有一個入口是可以獲取的
@app.route("/geneSign", methods=['GET', 'POST']) def geneSign():param = urllib.unquote(request.args.get("param", ""))action = "scan"return getSign(action, param)所以其實我們只要之后傳入的param和這個/geneSign傳入的param一樣,然后action也等于scan,然后拿這邊返回給我們的sign是肯定可以通過checkSign的
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'] = respelse:print resptmpfile.write(resp)tmpfile.close()result['code'] = 200if "read" in self.action:f = open("./%s/result.txt" % self.sandbox, 'r')result['code'] = 200result['data'] = f.read()if result['code'] == 500:result['data'] = "Action Error"但是我們現(xiàn)在是要令scan和read都是action內(nèi)容的一部分,才可以成功讀到那邊寫入的數(shù)據(jù)。
def scan(param):socket.setdefaulttimeout(1)try:return urllib.urlopen(param).read()[:50]except:return "Connection Timeout"scan()這個方法就是訪問param這個地址,將內(nèi)容的前50讀取出來
所以我們可以利用這個來讀服務(wù)器內(nèi)部的flag.txt文件
現(xiàn)在就是要令param等于”flag.txt”,action等于”readscan”,就可以獲得flag。
所以我們需要知道的是
hashlib.md5(secert_key +”flag.txtreadscan”).hexdigest()
這個的返回值。
通過/geneSign可以構(gòu)建,令param等于flag.txtread,然后action是scan,這樣我們就能獲得正確的sign
Crypto1——xorz
題目如下
from itertools import * from data import flag,plainkey=flag.strip("de1ctf{").strip("}") assert(len(key<38)) salt="WeAreDe1taTeam" ki=cycle(key) si=cycle(salt) cipher = ''.join([hex(ord(p) ^ ord(next(ki)) ^ ord(next(si)))[2:].zfill(2) for p in plain]) print cipher # output: # 49380d773440222d1b421b3060380c3f403c3844791b202651306721135b6229294a3c3222357e766b2f15561b35305e3c3b670e49382c295c6c170553577d3a2b791470406318315d753f03637f2b614a4f2e1c4f21027e227a4122757b446037786a7b0e37635024246d60136f7802543e4d36265c3e035a725c6322700d626b345d1d6464283a016f35714d434124281b607d315f66212d671428026a4f4f79657e34153f3467097e4e135f187a21767f02125b375563517a3742597b6c394e78742c4a725069606576777c314429264f6e330d7530453f22537f5e3034560d22146831456b1b72725f30676d0d5c71617d48753e26667e2f7a334c731c22630a242c7140457a42324629064441036c7e646208630e745531436b7c51743a36674c4f352a5575407b767a5c747176016c0676386e403a2b42356a727a04662b4446375f36265f3f124b724c6e346544706277641025063420016629225b43432428036f29341a2338627c47650b264c477c653a67043e6766152a485c7f33617264780656537e5468143f305f4537722352303c3d4379043d69797e6f3922527b24536e310d653d4c33696c635474637d0326516f745e610d773340306621105a7361654e3e392970687c2e335f3015677d4b3a724a4659767c2f5b7c16055a126820306c14315d6b59224a27311f747f336f4d5974321a22507b22705a226c6d446a37375761423a2b5c29247163046d7e47032244377508300751727126326f117f7a38670c2b23203d4f27046a5c5e1532601126292f577776606f0c6d0126474b2a73737a41316362146e581d7c1228717664091c給出腳本
import string from binascii import unhexlify, hexlify from itertools import *def bxor(a, b): # xor two byte strings of different lengthsif len(a) > len(b):return bytes([x ^ y for x, y in zip(a[:len(b)], b)])else:return bytes([x ^ y for x, y in zip(a, b[:len(a)])])def hamming_distance(b1, b2):differing_bits = 0for byte in bxor(b1, b2):differing_bits += bin(byte).count("1")return differing_bitsdef break_single_key_xor(text):key = 0possible_space = 0max_possible = 0letters = string.ascii_letters.encode('ascii')for a in range(0, len(text)):maxpossible = 0for b in range(0, len(text)):if(a == b):continuec = text[a] ^ text[b]if c not in letters and c != 0:continuemaxpossible += 1if maxpossible > max_possible:max_possible = maxpossiblepossible_space = akey = text[possible_space] ^ 0x20return chr(key)salt = "WeAreDe1taTeam" si = cycle(salt) b = unhexlify(b'49380d773440222d1b421b3060380c3f403c3844791b202651306721135b6229294a3c3222357e766b2f15561b35305e3c3b670e49382c295c6c170553577d3a2b791470406318315d753f03637f2b614a4f2e1c4f21027e227a4122757b446037786a7b0e37635024246d60136f7802543e4d36265c3e035a725c6322700d626b345d1d6464283a016f35714d434124281b607d315f66212d671428026a4f4f79657e34153f3467097e4e135f187a21767f02125b375563517a3742597b6c394e78742c4a725069606576777c314429264f6e330d7530453f22537f5e3034560d22146831456b1b72725f30676d0d5c71617d48753e26667e2f7a334c731c22630a242c7140457a42324629064441036c7e646208630e745531436b7c51743a36674c4f352a5575407b767a5c747176016c0676386e403a2b42356a727a04662b4446375f36265f3f124b724c6e346544706277641025063420016629225b43432428036f29341a2338627c47650b264c477c653a67043e6766152a485c7f33617264780656537e5468143f305f4537722352303c3d4379043d69797e6f3922527b24536e310d653d4c33696c635474637d0326516f745e610d773340306621105a7361654e3e392970687c2e335f3015677d4b3a724a4659767c2f5b7c16055a126820306c14315d6b59224a27311f747f336f4d5974321a22507b22705a226c6d446a37375761423a2b5c29247163046d7e47032244377508300751727126326f117f7a38670c2b23203d4f27046a5c5e1532601126292f577776606f0c6d0126474b2a73737a41316362146e581d7c1228717664091c') plain = ''.join([hex(ord(c) ^ ord(next(si)))[2:].zfill(2) for c in b.decode()]) b = unhexlify(plain) print(plain)normalized_distances = []for KEYSIZE in range(2, 40):# 我們?nèi)∑渲星?段計算平局漢明距離b1 = b[: KEYSIZE]b2 = b[KEYSIZE: KEYSIZE * 2]b3 = b[KEYSIZE * 2: KEYSIZE * 3]b4 = b[KEYSIZE * 3: KEYSIZE * 4]b5 = b[KEYSIZE * 4: KEYSIZE * 5]b6 = b[KEYSIZE * 5: KEYSIZE * 6]normalized_distance = float(hamming_distance(b1, b2) +hamming_distance(b2, b3) +hamming_distance(b3, b4) +hamming_distance(b4, b5) +hamming_distance(b5, b6)) / (KEYSIZE * 5)normalized_distances.append((KEYSIZE, normalized_distance)) normalized_distances = sorted(normalized_distances, key=lambda x: x[1])for KEYSIZE, _ in normalized_distances[:5]:block_bytes = [[] for _ in range(KEYSIZE)]for i, byte in enumerate(b):block_bytes[i % KEYSIZE].append(byte)keys = ''try:for bbytes in block_bytes:keys += break_single_key_xor(bbytes)key = bytearray(keys * len(b), "utf-8")plaintext = bxor(b, key)print("keysize:", KEYSIZE)print("key is:", keys, "n")s = bytes.decode(plaintext)print(s)except Exception:continue總結(jié)
以上是生活随笔為你收集整理的De1CTF-2019部分wp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BUUCTF的Web真题学习整理(一)
- 下一篇: SQLi-LABS(1~10关详解)