SSRF ME
hint:flag is in ./flag.txt
访问靶机,拿到题目源码
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110 |
#! /usr/bin/env python#encoding=utf-8from flask import Flaskfrom flask import requestimport socketimport hashlibimport urllibimport sysimport osimport jsonreload(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.def geneSign(): param = urllib.unquote(request.args.get("param", "")) action = "scan" return getSign(action, param)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())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 Falseif __name__ == '__main__': app.debug = False app.run(host='0.0.0.0',port=80) |
回显flag的地方应该是Exec函数,然后要先过一个判断self.checkSign()
定位到checkSign函数又是一个判断 if(getSign(self.action, self.param) == self.sign)
在定位到getSign函数 return hashlib.md5(secert_key + param + action).hexdigest()
这里会把key,param,action串起来然后md5加密,self.sign是cookie里的,这个可以造,再说,然后是
123456789101112131415161718192021 |
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 |
要求scan在action里面,这样子他会创建一个文件,在scan一个{$param}文件,定位到scan函数,
return urllib.urlopen(param).read()[:50],他会打开一个{$param}文件并且只取前50位,所以就打开flag.txt咯,
patam=flag.txt,然后他会把flag.txt的内容写进那个result文件。接着如果read在action里面,他就会打开result文件,并把内容赋值给result,然后输出(就是给你看啦)。
那么目的明确了,往前推就是,action=readscan,然后param=flag.txt,那么为了过检查,sign=MD5(flag.txtreadscan),怎么获得这个呢,有getsign这个函数。怎么回显sign呢?有geneSign()这个函数,geneSign这个函数里的action赋值为scan了,所以我们只需要让param=flag.txtrread,就可以获得MD5(flag.txtreadscan)了。okay,万事俱备。那怎么执行到Exec()函数呢,在/De1ta里的challenge()函数,param可以get。action和sign都是cookie里的。
所以总的步骤:
- 访问/geneSign?param=flag.txtread 得到$sign
- 访问/De1ta?param=flag.txt 抓包,写入sign=$sign和action=readscan
get flag。
XORZ
加密源码
123456789101112 |
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 |
解题思路:
加密脚本是salt^key^plain=output
所以逆过来,salt^output=key^plain
已知len(key)<38,
所以先爆破长度,
只要备选的key不是空集即可,
得到可能的长度只有30
然后就可以列出key的每一位的可能值
先随便选一组key异或,然后得到原文是莎翁14行诗
根据原文调整key即可。
脚本如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
from itertools import *import reps='1234567890qwertyuiopasdfghjklxcvbnmQWERTYUIOPSDFGHJKLZXCVBNM\'` ;,.'ks='1234567890qwertyuiopasdfghjklxcvbnmQWERTYUIOPSDFGHJKLZXCVBNM'res='1e5d4c055104471c6f234f5501555b5a014e5d001c2a54470555064c443e235b4c0e590356542a130a4242335a47551a590a136f1d5d4d440b0956773613180b5f184015210e4f541c075a47064e5f001e2a4f711844430c473e2413011a100556153d1e4f45061441151901470a196f035b0c4443185b322e130806431d5a072a46385901555c5b550a541c1a2600564d5f054c453e32444c0a434d43182a0b1c540a55415a550a5e1b0f613a5c1f10021e56773a5a0206100852063c4a18581a1d15411d17111b052113460850104c472239564c0755015a13271e0a55553b5a47551a54010e2a06130b5506005a393013180c100f52072a4a1b5e1b165d50064e411d0521111f235f114c47362447094f10035c066f19025402191915110b4206182a544702100109133e394505175509671b6f0b01484e06505b061b50034a2911521e44431b5a233f13180b5508131523050154403740415503484f0c2602564d470a18407b775d031110004a54290319544e06505b060b424f092e1a770443101952333213030d554d551b2006064206555d50141c454f0c3d1b5e4d43061e453e39544c17580856581802001102105443101d111a043c03521455074c473f3213000a5b085d113c194f5e08555415180f5f433e270d131d420c1957773f560d11440d40543c060e470b55545b114e470e193c155f4d47110947343f13180c100f565a000403484e184c15050250081f2a54470545104c5536251325435302461a3b4a02484e12545c1b4265070b3b5440055543185b36231301025b084054220f4f42071b1554020f430b196f19564d4002055d79'#res=salt^outputtrlen= int(len(res)/2)list1=[]for i in range(0,len(res),2): list1.append(res[i:i+2])list2=[] #列出key全集for j in range(0,trlen): list3=[] for i in ks: if (chr(ord(i)^int(list1[j],16))in ps): list3.append(i) list2.append(list3) for length in range(1,38): #根据key[0]不为空集来爆length x=set(list2[0]) for j in range(0,trlen,length): x &= set(list2[j]) if len(x)!=0: print(length)y = []for z in range(30): #爆key候选集 x=set(list2[z]) for j in range(z,trlen,30): x &= set(list2[j]) if len(x)!=0: y.append(x)print(str(y).replace("},","},\n"))key='W3lc0m3tOjo1nu55un1ojOt3m0cl3W'ki=cycle(key) #看结果str1=''for each in list1: str1+=chr(ord(next(ki))^int(each,16))print(str1) |
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可联系QQ 643713081,也可以邮件至 [email protected] - source:Van1sh的小屋
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论