1. 程式人生 > >Thinkphp 5.1.7 parseData缺陷導致insert/update注入 分析

Thinkphp 5.1.7 parseData缺陷導致insert/update注入 分析

目錄

  • 環境搭建
  • 分析
  • 參考

環境搭建

$ composer create-project topthink/think thinkphp-5.1.7

修改composer.json 5.1.* => 5.1.7

$ composer update

分析

這個注入點與5.0.15的注入點位置都在parseData裡,都是在解析set-data時直接將使用者完全控制的data拼接到SQL語句中。

下面來看漏洞點,首先根據Github的commit記錄進行定位

可以看到這裡直接刪除了default語句塊,並直接刪除了parseArrayData方法。

我們下面通過搭建5.1.7環境,來看一下被刪掉的語句在原版本中會有怎樣的影響。首先看一下控制器

這裡獲取一個username陣列get變數,傳給$username,然後作為欄位'name'的值,插入test表。

我們先請求一條測試url:

127.0.0.1/thinkphp/thinkphp_5.1.7/public/index.php/index/index/sqli?username[0]=aaa&username[1]=bbb

可以看到此時$username的值為{"aaa","bbb"}。

下面在commit刪除的部分下個斷點,由於這個斷點位於parseData()處,所以我們先從parseData開始跟。

可以看到,這裡將$data解析成鍵值對,由於$val是陣列且不為空,進入了switch-default語句塊,然後以使用者可控的$val作為引數傳入parseArrayData方法中。然後將獲得的返回值放到$result陣列中,最終返回$result陣列。我們先跟進一下parseArrayData

這裡先把$data的前兩個元素賦值給$type和$value。不過由於我們這個的第一個元素是aaa,因此沒有進入第一個case。通過分析第一個case可以發現,這裡直接將$value(即$data[1])、$data[2]、$data[3]拼接到了返回值$result中,因此我們把我們的username[0]的值改為point,然後再加一個username[2]。

測試url:

127.0.0.1/thinkphp/thinkphp_5.1.7/public/index.php/index/index/sqli?username[0]=point&username[1]=bbb&username[2]=ccc

除錯一下:

可以看到這裡直接將引數拼接進來。繼續除錯,看看最終形成的sql語句:

返回頁面:

試一下報錯注入payload:

http://127.0.0.1/thinkphp/thinkphp_5.1.7/public/index.php/index/index/sqli?username[0]=point&username[1]=bbbb&username[2]=updatexml(1,concat(0x7e,user(),0x7e),1))--%20

參考

https://mochazz.github.io/2019/03/21/ThinkPHP5%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90%E4%B9%8BSQL%E6%B3%A8%E5%85%A52/#%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9