蹭熱度分享一份寫配置漏洞案例

0x00 前言

今天奇安信ATEAM團隊分享一篇深度好文這是一篇“不一樣”的真實滲透測試案例分析文章引爆朋友圈多次轉發分享,Phith0n 師傅也專門寫了一篇經典寫配置漏洞與幾種變形的總結,看了P神師傅文章想起我之前也挖到過一個類似漏洞,這裏我把中間思路和部分代碼貼出來分享一份。

0x01 分析

漏洞代碼還是出在一個寫配置文件的函數當中,代碼如下(大部分代碼刪去,只留核心部分):

public function input($c)
    {
     ///...........省略大部分代碼..........
            if ($_POST['name_list']) {
                $name_list = explode("/", $_POST['name_list']);
                foreach ($name_list as $v) {
                    if (substr($v, 0, 6) == "_scfg_") {
                        $name = substr($v, 6);
                    } else {
                        $name = $v;
                    }
                    if ($name) {
                        { if (is_array($_POST[$v])) {
                            $input[$name] = implode("|@|", $_POST[$v]);
                        } else {
                            $input[$name] = $_POST[$v];
                        }}
                    }
                }
            }
            
            $filename = $newsid.".php";
            $res = write_config_file($this->lib_path."../data/".$dir."/", $filename, "_scfg_var", $input, false, false);
            
            if ($all_input) {
                $is_one_fail = false;
                if ($ares = mysql_query("select * from ".$this->table_name." where cate1='$vars[cate1]' and cate2='$vars[cate2]' and cate3 ='$vars[cate3]' and skin ='$vars[skin]' ", $this->link_id)) {
                    while ($arow = mysql_fetch_assoc($ares)) {
                        if ($arow['id'] != $newid) {
                            $_scfg_var = array();
                            $filename = $arow['newsid'].".php";
                            @include($this->lib_path."../data/".$dir."/".$filename);
                            foreach ($_scfg_var as $k => $v) {
                                $_scfg_var[$k] = addslashes($v);
                            }
                          
                            }
                            $res = write_config_file($this->lib_path."../data/".$dir."/", $filename, "_scfg_var", $_scfg_var, false, false);
                       ///...........省略大部分代碼..........    
        return $newsid;
    }

這裏通過POST獲取name_list參數值,然後將值按“/” 分割存入數組input,然後將數組傳輸write_config_file函數,繼續跟進write_config_file

#! /lib/cfg/cfglib.php

function write_config_file($path, $file, $name, $input, $is_serial = true, $is_alert = true, $chmod = 0707)
{
	global $_NL;
	$conf_file = $path.$file;
	$tmp_file = ereg_replace("(\.[^.]+)$","_tmp\\1",$conf_file); 
	$tmp_file2 = ereg_replace("(\.[^.]+)$","_tmp_\\1",$conf_file); 
	$name = "$".$name;
	if( !$is_serial )
	{
		$output =  "<?".$_NL;
		foreach($input as $key => $val )
		{
			$key = str_replace("'", '\'', $key);
			if( is_array( $val ) )
			{
				foreach($val as $key1 => $val1 )
				{
					$key1 = str_replace("'", '\'', $key1);
					$output .= $name."['".$key."']['".$key1."'] = '".str_replace('\"', '"', $val1)."';".$_NL;;
					//$output .= $name."['".$key."']['".$key1."'] = \"".str_replace("\'", "'", $val1)."\";".$_NL;
				}				
				
			}
			else $output .= $name."['".$key."'] = '".str_replace('\"', '"', $val)."';".$_NL;;
			
		}
    	
		$output .=  "?>";
	}
	// ..................省略寫文件部分代碼................
	
}

這裏$key1 = str_replace("'", '\'', $key1);程序員明明是想過濾掉寫key值的,但是我估計轉義符和單雙引號已經把他搞糊塗了,這裏這個轉移根本就沒起到作用。由此可見控制input即可控制寫入文件的內容,如下圖:
在這裏插入圖片描述
但受到整體參數過濾影響,所有POST的單引號都會被轉義爲"\’",一般情況下若提交單引號將會得到如下結果:
在這裏插入圖片描述
但在繼續跟進input函數後半部分代碼時候發現在$all_inputtrue的情況下,會從數據庫中查詢相同的內容,並定包含該文件,將$_scfg_var值從新寫入到文件,代碼如下:

if ($all_input) {
                $is_one_fail = false;
                if ($ares = mysql_query("select * from ".$this->table_name." where cate1='$vars[cate1]' and cate2='$vars[cate2]' and cate3 ='$vars[cate3]' and skin ='$vars[skin]' ", $this->link_id)) {
                    while ($arow = mysql_fetch_assoc($ares)) {
                        if ($arow['id'] != $newid) {
                            $_scfg_var = array();
                            $filename = $arow['newsid'].".php";
                            @include($this->lib_path."../data/".$dir."/".$filename);
                            foreach ($_scfg_var as $k => $v) {
                                $_scfg_var[$k] = addslashes($v);
                            }
                          
                            }
                            $res = write_config_file($this->lib_path."../data/".$dir."/", $filename, "_scfg_var", $_scfg_var, false, false);

這裏就必要有意思了,這了會include剛纔寫入的文件,然後將值取出再次寫入。這裏$_scfg_var[$k] = addslashes($v);程序員值對值進行addslashes操作,而鍵名爲做任何處理,在include包含執行該文件後此處的$_scfg_var[$k] = addslashes($v);中的$k值就有了正常的單引號“’”了,後續再將$_scfg_var傳入write_config_file中後單引號未得到過濾,最終寫入文件後便成了如下:
在這裏插入圖片描述

0x02 利用

這裏只需要向目標二次提交代碼即可逃逸了,例如target.php?name_list=testsssssss'];phpinfo();#/bbb&test=testskin_file 第一次提交代碼被magic_gpc轉義後寫入文件,第二次提交時候因第一次生成了文件,所以這裏程序邏輯條到後半部分,include第一次寫入的文件,然後再將數組二次寫,代碼成功執行!

0x03 結語

此文由大佬們的深度好文有感而發,有不到之處多指教。漏洞原理和成因也比較簡單,但當時還是讀了許久代碼才發現問題,主要是代碼寫得太亂。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章