前天在公眾號看到石大神發的一篇審計thinkphp的文章,就想寫一個分析流程,delay到了今天。昨天在先知也看到了chybeta發的一篇分析文章感覺也不錯。分析過程,我也會做thinkphp部分功能的解析。 廢話不多說,開始吧!
程序下載地址:http://www.thinkphp.cn/down/1126.html PHPstudy:Apache+php5.6+MySQL 工具:PHPstorm
hinkphpapplicationdatabase.php
hinkphpapplicationconfig.php
hinkphpapplicationindexcontrollerIndex.php
<?php namespace appindexcontroller;
class Index { public function index() { $password = input(get.password/a); db(user)->where([id=> 1])->update([password=>$password]); } }
這裡用到了thinkphp的助手函數input(),是專用來接收get,post等的值。具體可以看:https://www.kancloud.cn/manual/thinkphp5/118044
還有就是thinkphp的資料庫操作,框架本身寫好了我們調用就比較方便。所以為什麼那麼多人用框架去開發程序,快捷而且安全,不過也會有安全問題,就像今天這個sql漏洞,不過如果是新手的話總比自己寫的好對吧哈。 具體可以看鏈接:https://www.kancloud.cn/manual/thinkphp5/135178
7. 現在就可以訪問我們的payload了:
http://thinkphp.test/thinkphp/public/index.php?password[0]=inc&password[1]=updatexml(2,concat(0x7e,user()),0)&password[2]=1
然後訪問我們payload,它會跳到入口文件,我們只要分析的是sql執行的地方,所以我們直接F8跳到執行sql地方:
2. 我們繼續跟進到loader.php它會包含thinkphp的Db.php文件,
loader.php
接下還會包 hinkphplibrary hinkdbconnectorMysql.php文件,主要是連接資料庫的操作,這裡就直接跳過了。別分析分析把自己繞進去了,我只是在這裡講訴下過程,我們還是直接分析sql執行的部分吧。 3. 我們跳到update執行的部分,文件位置: hinkphplibrary hinkdbQuery.php
hinkphplibrary hinkdbconnectorMysql.php
hinkphplibrary hinkdbQuery.php
繼續往下看,這句是執行我們sql的地方:
4. 我們F7跟進去,跳到文件位置 hinkphplibrary hinkdbBuilder.php parseTable函數直接F8往下執行了,這函數是處理table分析的,主要還是parseData函數,我們繼續F7跟進
hinkphplibrary hinkdbBuilder.php
parseTable
parseData函數
5. 我們繼續往下跟進
我們看到了這裡如果傳入的值為數組形式的話,並且第一個參數為inc就執行switch所對應的的語句。
inc
可以看到這裡函數對我們傳入的值沒有做任何處理,返回內容仍然是我們的語句:
跟到後面返回的執行sql語句:
執行完,我們跟進到報錯的地方,說明我的語句執行成功:
6.到這裡就差不多結束了,有人問,為什麼要這樣給數組三個欄位? 我們可以看到我們剛才傳入數組的地方,分別有三個數組
到後面返回$result的時候就組合在一起了:
$result
下面是parseData的代碼:
parseData
protected function parseData($data, $options) { if (empty($data)) { return []; }
// 獲取綁定信息 $bind = $this->query->getFieldsBind($options[table]); if (* == $options[field]) { $fields = array_keys($bind); } else { $fields = $options[field]; }
$result = []; foreach ($data as $key => $val) { $item = $this->parseKey($key, $options); if (is_object($val) && method_exists($val, __toString)) { // 對象數據寫入 $val = $val->__toString(); } if (false === strpos($key, .) && !in_array($key, $fields, true)) { if ($options[strict]) { throw new Exception(fields not exists:[ . $key . ]); } } elseif (is_null($val)) { $result[$item] = NULL; } elseif (is_array($val) && !empty($val)) { switch ($val[0]) { case exp: $result[$item] = $val[1]; break; case inc: $result[$item] = $this->parseKey($val[1]) . + . floatval($val[2]); break; case dec: $result[$item] = $this->parseKey($val[1]) . - . floatval($val[2]); break; } } elseif (is_scalar($val)) { // 過濾非標量數據 if (0 === strpos($val, && $this->query->isBind(substr($val, 1))) { $result[$item] = $val; } else { $key = str_replace(., _, $key); $this->query->bind(data__ . $key, $val, isset($bind[$key]) ? $bind[$key] : PDO::PARAM_STR); $result[$item] = :data__ . $key; } } } return $result; }
如果看不懂的,可以先去了解一下thinkphp這個框架,其他框架大同小異。如果裡面一些PHP代碼看不懂的話,可以去複習下PHP。
https://www.kancloud.cn/manual/thinkphp5/
https://mp.weixin.qq.com/s?__biz=MzU2NzE3MTU0Mw==&mid=2247483720&idx=1&sn=973bd7daa287a9e9c0171e852db6cb6b&chksm=fca001f0cbd788e6ed3119de5d3c4bfc3325205c5dd7f296e55a2ba313f73b3808525d1022e6&mpshare=1&scene=23&srcid=04104vXPMKRNVfrVzzzg7HXg#rd
https://chybeta.github.io/2018/04/10/Thinkphp%E6%A1%86%E6%9E%B6-5-0-16-sql%E6%B3%A8%E5%85%A5%E6%BC%8F%E6%B4%9E%E5%88%86%E6%9E%90/