版本: v5.0.22 问题: 命令执行

image.png

分析

1. 倒着看

首先,找到”万恶之源”:
在Request类下的 filterValue:
image.png
我们来打印一下$value:
image.png

果然是他。我们看到这里其实运行了system('whoami').
其中$filter = ‘system’, $value = ‘whoami’;

image.png

image.png

这玩意儿被掉了四次,只在第四次炸了。
image.png
回到App, 看这货的入口, 我把它分成列两段,第一段new Request已经把恶意命令注入了,第二部分$req->param()触发。

image.png
image.png

我们倒着看: 假设我们成功的污染了Request对象的get和filter,他怎么执行的。
上头我们看到了,要执行,关键是要污染:array_walk_recursive($data, [$this, ‘filterValue’], $filter);
其中,$data应为$get, $filter就为filter。

Request->filter = “System”
Request->get = “Whoami”

image.png

image.png

好了,filter知道了, 那么$data是怎么拿到$get的呢?

image.png


看到没,正是第四次,$data是一个数组中包含”whoami”时,搞的事情。

我们下了一个断点:
image.png
看到打印了三次:
image.png

image.png

第四次就是你了。
image.png

2.正着看

首先,我们再来看看payload:
url: http://127.0.0.1:8088/public/index.php?s=captcha
post data: _method=__construct&filter[]=system&method=get&get[]=whoami
奇奇怪怪的东西有s和_method,
看配置文件:
image.png

那么他们是肿么用的呢?
收看我们来看s:
啥是兼容模式呢?来看tp5的url设计:
https://www.kancloud.cn/manual/thinkphp5/118012
image.png
所谓普通模式就是: m=module&c=controller&action=action 来获得dispatch
path_info模式:module/controller/action
而所谓的兼容模式不过是给tp一个var_pathinfo来。
我们来看这个怎么用:

  1. /**
  2. * 获取当前请求URL的pathinfo信息(含URL后缀)
  3. * @access public
  4. * @return string
  5. */
  6. public function pathinfo()
  7. {
  8. if (is_null($this->pathinfo)) {
  9. if (isset($_GET[Config::get('var_pathinfo')])) {
  10. // 判断URL里面是否有兼容模式参数
  11. $_SERVER['PATH_INFO'] = $_GET[Config::get('var_pathinfo')]; //s
  12. unset($_GET[Config::get('var_pathinfo')]);
  13. } elseif (IS_CLI) {
  14. // CLI模式下 index.php module/controller/action/params/...
  15. $_SERVER['PATH_INFO'] = isset($_SERVER['argv'][1]) ? $_SERVER['argv'][1] : '';
  16. }
  17. // 分析PATHINFO信息
  18. if (!isset($_SERVER['PATH_INFO'])) {
  19. foreach (Config::get('pathinfo_fetch') as $type) {
  20. if (!empty($_SERVER[$type])) {
  21. $_SERVER['PATH_INFO'] = (0 === strpos($_SERVER[$type], $_SERVER['SCRIPT_NAME'])) ?
  22. substr($_SERVER[$type], strlen($_SERVER['SCRIPT_NAME'])) : $_SERVER[$type];
  23. break;
  24. }
  25. }
  26. }
  27. $this->pathinfo = empty($_SERVER['PATH_INFO']) ? '/' : ltrim($_SERVER['PATH_INFO'], '/');
  28. }
  29. return $this->pathinfo;
  30. }

现在我们的url中没有pathinfo信息且有Config::get(‘var_pathinfo’), 即s。那么我们的$_SERVER[‘PATH_INFO’]就会被赋值为s参数的内容。($_SERVER[‘PATH_INFO’] = $_GET[Config::_get(‘varpathinfo’)];
即所谓的兼容模式(其实就是不写pathinfo时,看看参数里有没有var_pathinfo, 有的话把他的值当作pathinfo)

现在我们的pathinfo就是一个captcha了。那么为啥时captcha不是娃哈哈呢?接着往下看。

参考:

[1] https://xz.aliyun.com/t/3845