主页 > 网络编程 > ThinkPHP 5.1框架结合RCE漏洞的深入分析(6)

ThinkPHP 5.1框架结合RCE漏洞的深入分析(6)

返回后会调用Url类中的init方法,将$dispatch对象中的得到$this->dispatch(路由)传入parseUrl方法中,开始解析URL路由地址。

跟进parseUrl方法。

这里首先会进入parseUrlPath方法,将路由进行解析分割。

使用”/”进行分割,拿到 [模块/控制器/操作/参数/参数值]。

紧接着使用array_shift函数挨个从$path数组中取值对模块、控制器、操作、参数/参数值进行赋值。

接着将参数/参数值保存在了Request类中的Route变量中,并进行路由封装将赋值后的$module、$controller、$action存到route数组中,然后将$route返回赋值给$result变量。

new Module($this->request, $this->rule, $result),实例化Module类。

在Module类中也没有构造方法,会直接调用Dispatch父类的构造方法。

然后将传入的值都赋值给Module类对象本身$this。此时,封装好的路由$result赋值给了$this->dispatch,这么做的目的同样是为了后面在调用Module类中方法时方便调用其值。

实例化赋值后会调用Module类中的init方法,对封装后的路由(模块、控制器、操作)进行验证及格式处理。

$result = $this->dispatch,首先将封装好的路由$this->dispatch数组赋给$result,接着会从$result数组中获取到了模块$module的值并对模块进行大小写转换和html标签处理,接下来会对模块值进行检测是否合规,若不合规,则会直接HttpException报错并结束程序运行。检测合格之后,会再从$result中获取控制器、操作名并处理,同时会将处理后值再次赋值给$this(Module类对象)去替换之前的值。

Ps:从$result中获取值时,程序采用了三元运算符进行判断,如果相关值为空会一律采用默认的值index。这就是为什么我们输入http://127.0.0.1/tp5.1.20/public/index.php在不指定模块、控制器、操作值时会跳到程序默认的index模块的index控制器的index操作中去。

此时调度信息(模块、控制器、操作)都已经保存至Module类对象中,在之后的路由调度工作中会从中直接取出来用。

然后返回Module类对象$this,回到最开始的App类,赋值给$dispatch。

至此,路由解析工作结束,到此我们获得了模块、控制器、操作,这些值将用于接下来的路由调度。

接下来在路由调度前,需要另外说明一些东西:路由解析完成后,如果debug配置为True,则会对路由和请求信息进行记录,这里有个很重要的点param方法, 该方法的作用是获取变量参数。

在这里,在确定了请求方式(GET)后,会将请求的参数进行合并,分别从$_GET、$_POST(这里为空)和Request类的route变量中进行获取。然后存入Request类的param变量中,接着会对其进行过滤,但是由于没有指定过滤器,所以这里并不会进行过滤操作。

Ps:这里解释下为什么要分别从$_GET中和Request类的route变量中进行获取合并。上面我们说过传参有三种方法。

1. index/Test/hello/name/world

2. index/Test/hello&name=world

3. index/Test/hello/a/1&b=2

当我们如果选择1进行请求时,在之前的路由检测和解析时,会将参数/参数值存入Request类中的route变量中。

而当我们如果选择2进行请求时,程序会将&前面的值剔除,留下&后面的参数/参数值,保存到$_GET中。

并且因为Thinkphp很灵活,我们还可以将这两种方式结合利用,如第3个。

这就是上面所说的在请求方式不同时,程序在处理传参时也会不同。

Ps:在debug未开启时,参数并不会获得,只是保存在route变量或$_GET[]中,不过没关系,因为在后面路由调度时还会调用一次param方法。

继续调试,开始路由调度工作。

4.3.4 路由调度

这一部分将会对路由解析得到的结果(模块、控制器、操作)进行调度,得到数据结果。

说点什么吧
  • 全部评论(0
    还没有评论,快来抢沙发吧!