昨天看了一下题,大概有些简单的思路,BUU上了复现环境,今天及时来复现一下,顺便学一些新的知识
[HFCTF2020]EasyLogin
打开靶机,一个登录界面
查看页面源代码,看到 app.js 中有以下注释
猜测有任意文件读取,经过队内师傅提醒,有一个 controllers/api.js 尤其重要
读一下代码逻辑
我们发现传入 username 和 password,先判断 username 不为 admin,然后生成一个 秘钥 ,生成一个 jwt 令牌
登录页面中进行JWT的验证,如果通过就登录
flag中,如果登录的用户名是admin,就输出flag
所以我们的思路是---构造用户名为admin拿到flag
JSNOTE也是一门弱语言,根据之前PHP和JWT的经验
如果我们设置secretid为数组,加密算法为空
<span class="hljs-keyword">const</span> jwt=<span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> secretid=[];
<span class="hljs-keyword">const</span> username=<span class="hljs-string">'admin'</span>;
<span class="hljs-keyword">const</span> password=<span class="hljs-string">'123456'</span>;
<span class="hljs-built_in">console</span>.log(jwt.sign({secretid,username,password}, <span class="hljs-literal">null</span>, {<span class="hljs-attr">algorithm</span>: <span class="hljs-string">'none'</span>});
能不能绕过呢
再试亿次
尝试过以后发现我们需要先随意注册一个用户,在登录的时候将username和password设置成jwt中的数据,更改Authorization为我们伪造的jwt,forward到本地,即可登录
然后访问一下flag地址即可获得flag
[HFCTF2020]JustEscape
打开靶机
随意fuzz一下(fuzz一天),发现是一个notejs的代码
传入var err = new Error();err.stack;出现错误信息
Error at vm.js:1:11 at Script.runInContext (vm.js:131:20) at VM.run (/app/node_modules/vm2/lib/main.js:219:62) at /app/server.js:51:33 at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) at next (/app/node_modules/express/lib/router/route.js:137:13) at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3) at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5) at /app/node_modules/express/lib/router/index.js:281:22 at Function.process_params (/app/node_modules/express/lib/router/index.js:335:12)
发现一个VM2,需要沙盒逃逸
到github找一下VM2逃逸的payload
https://github.com/patriksimek/vm2/issues/225
代码复制过来
过滤了部分字符。用数组就可以绕过
发现还过滤了return
执行命令就行了
在guoke师傅的WP中还写道
js中. 可以用[]代替.
TypeError.prototype==TypeError[\xxx\xxx\xxx\xxx
]
``反引号代替双引号
所以在VM2的那个github中
这个也可以代替使用,
在赵师傅的博客中使用了占位符来拼接字符串
比如这里 prototype 被过滤了,我们可以这样书写<code>${
${prototyp
}e}
https://www.zhaoj.in/read-6512.html
[HFCTF2020]BabyUpload
这题是最难的了,当时是完全不会,赛后看着WP复现下
咕咕咕来了
给了源码
<?php
error_reporting(0);
session_save_path("/var/babyctf/");
session_start();
require_once "/flag";
highlight_file(__FILE__);
if($_SESSION['username'] ==='admin') {
$filename='/var/babyctf/success.txt';
if(file_exists($filename)){
safe_delete($filename); die($flag);
}
}
else{
$_SESSION['username'] ='guest';
}
$direction = filter_input(INPUT_POST, 'direction');
$attr = filter_input(INPUT_POST, 'attr');
$dir_path = "/var/babyctf/".$attr;
if($attr==="private"){
$dir_path .= "/".$_SESSION['username'];
}
if($direction === "upload"){
try{
if(!is_uploaded_file($_FILES['up_file']['tmp_name'])){
throw new RuntimeException('invalid upload');
}
$file_path = $dir_path."/".$_FILES['up_file']['name'];
$file_path .= "_".hash_file("sha256",$_FILES['up_file']['tmp_name']);
if(preg_match('/(\.\.\/|\.\.\\\\)/', $file_path)){
throw new RuntimeException('invalid file path');
}
@mkdir($dir_path, 0700, TRUE);
if(move_uploaded_file($_FILES['up_file']['tmp_name'],$file_path)){
$upload_result = "uploaded";
}else{
throw new RuntimeException('error while saving');
}
} catch (RuntimeException $e) {
$upload_result = $e->getMessage();
}
} elseif ($direction === "download") {
try{
$filename = basename(filter_input(INPUT_POST, 'filename'));
$file_path = $dir_path."/".$filename;
if(preg_match('/(\.\.\/|\.\.\\\\)/', $file_path)){
throw new RuntimeException('invalid file path');
}
if(!file_exists($file_path)) {
throw new RuntimeException('file not exist');
}
header('Content-Type: application/force-download');
header('Content-Length: '.filesize($file_path));
header('Content-Disposition: attachment; filename="'.substr($filename, 0, -65).'"');
if(readfile($file_path)){
$download_result = "downloaded";
}else{
throw new RuntimeException('error while saving');
}
} catch (RuntimeException $e) {
$download_result = $e->getMessage();
}
exit;
}
很明显发现直接给了源码。代码审结
很明显发现了
如果$_SESSION['usernmae']==='admin' 并且检测var/babyctf/success.txt是否存在
如果存在删除该文件并直接输出flag
然后的代码我就看不懂了