PicoCTF write up (一)

如果你是第一次接觸 CTF ,或者是想從零開學接觸 CTF,我會推薦 PicoCTF,這裡我會把我如何解 PicoCTF 的過程和思路盡可能詳細的記錄下來,希望能為你帶來一些幫助。

image

為什麼會有這篇文章 ?

駭客 (hacker) 最好的入門就是從 CTF 開始,因為它是一個良好且安全的學習環境,但即便如此,CTF 的入門對很多人來說也是無從入手。

我看過很多高手寫的 Write up (CTF 的解答),都省略了很多新手接觸 CTF 時會遇到的難題和疑問。

所以我想寫一篇能讓新手能看得懂的 Write up,而這一章是記錄了 PicoCTF 最基礎的 100 分以下的題目,如果仍有寫得不清晰的地方,歡迎留言告訴我。

PicoCTF

建議註冊一個帳號邊玩邊學 : https://play.picoctf.org/practice

image


WebExploitation

Insp3ct0r (50 points)

Kishor Balan tipped us off that the following code may need inspection: https://jupiter.challenges.picoctf.org/problem/44924/ (link) or http://jupiter.challenges.picoctf.org:44924

Hints 1 : How do you inspect web code on a browser?

Hints 2 : There’s 3 parts

知識點 :

如何查看網頁原始碼內容

在網頁任意位置按”右鍵”->”檢視網頁原始碼”

<!doctype html>
<html>
  <head>
    <title>My First Website :)</title>
    <link href="https://fonts.googleapis.com/css?family=Open+Sans|Roboto" rel="stylesheet">
    <link rel="stylesheet" type="text/css" href="mycss.css">
    <script type="application/javascript" src="myjs.js"></script>
  </head>

  <body>
    <div class="container">
      <header>
	<h1>Inspect Me</h1>
      </header>

      <button class="tablink" onclick="openTab('tabintro', this, '#222')" id="defaultOpen">What</button>
      <button class="tablink" onclick="openTab('tababout', this, '#222')">How</button>
      
      <div id="tabintro" class="tabcontent">
	<h3>What</h3>
	<p>I made a website</p>
      </div>

      <div id="tababout" class="tabcontent">
	<h3>How</h3>
	<p>I used these to make this site: <br/>
	  HTML <br/>
	  CSS <br/>
	  JS (JavaScript)
	</p>
	<!-- Html is neat. Anyways have 1/3 of the flag: picoCTF{tru3_d3 -->
      </div>
      
    </div>
    
  </body>
</html>

在第 31 行有註解,告訴了 picoCTF{tru3_d3 ,它是 flag 的前 3 分之 1 ,那其餘的 2 段呢?

試試看點開第 6 行的 mycss.css 和 第 7 行的 myjs.js,舉一反三是駭客重要的能力之一。

所以只要使用 inspector 查看原始碼,就會發現分別藏在 html , css , javascript 的註解中

where are the robots (100 points)

Can you find the robots? https://jupiter.challenges.picoctf.org/problem/60915/ (link) or http://jupiter.challenges.picoctf.org:60915

Hints : What part of the website could tell you where the creator doesn’t want you to look?

知識點 :

要了解 robots.txt 在一個網站上有何作用,還有放在什麼地方。

原網址 :

https://jupiter.challenges.picoctf.org/problem/60915/

在網址後面加上 robots.txt :

https://jupiter.challenges.picoctf.org/problem/60915/robots.txt

看到內容 :

User-agent: *
Disallow: /8028f.html

顯然 8028f.html 這個文件是網頁製作者不想被搜索引擎建立索引

網址後面加上 8028f.html :

https://jupiter.challenges.picoctf.org/problem/60915/8028f.html

看到 flag image

logon (100 points)

The factory is hiding things from all of its users. Can you login as Joe and find what they’ve been looking at? https://jupiter.challenges.picoctf.org/problem/15796/ (link) or http://jupiter.challenges.picoctf.org:15796

Hints : Hmm it doesn’t seem to check anyone’s password, except for Joe’s?

知識點 :

Cookie

image

首先是一個登入網站,不論我 Username 和 Password 輸入任何東西,甚至完全不輸入,也無妨 Sign In。

image

再來查看網站原始碼,發現它根本沒有確認帳號密碼,一律通過。

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Factory Login</title>


    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">

    <link href="https://getbootstrap.com/docs/3.3/examples/jumbotron-narrow/jumbotron-narrow.css" rel="stylesheet">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>


</head>

<body>

    <div class="container">
        <div class="header">
            <nav>
                <ul class="nav nav-pills pull-right">
                    <li role="presentation" class="active"><a href="/">Home</a>
                    </li>
                    <li role="presentation"><a href="/logout" class="btn btn-link pull-right">Sign Out</a>
                    </li>
                </ul>
            </nav>
            <h3 class="text-muted">Factory Login</h3>
        </div>
        
        <!-- Categories: success (green), info (blue), warning (yellow), danger (red) -->
        
      
      <div class="jumbotron">
        <p class="lead"></p>
        <div class="login-form">
            <form role="form" action="/login" method="post">
                <div class="form-group">
                    <input type="text" name="user" id="email" class="form-control input-lg" placeholder="Username">
                </div>
                <div class="form-group">
                    <input type="password" name="password" id="password" class="form-control input-lg" placeholder="Password">
                </div>
            </div>
            <div class="row">
                <div class="col-xs-12 col-sm-12 col-md-12">
                    <input type="submit" class="btn btn-lg btn-success btn-block" value="Sign In">
                </div>
            </div>
        </form>
    </div>
    <footer class="footer">
        <p>&copy; PicoCTF 2019</p>
    </footer>

</div>

<script>
$(document).ready(function(){
    $(".close").click(function(){
        $("myAlert").alert("close");
    });
});
</script>
</body>

</html>

那麼,網站又如何確認登入的帳號是不是 Admin 呢?

答案就是透過 Cookie

首先在隨便輸入帳號和密碼。joe : 123

再打開 檢查 (在常見的瀏覽器中一般是 F12 或者 Ctrl + Shift + I)

image

Application -> Cookies -> 目前的所在網站

image

看到有這些資料,其中 3 項資料可以特別留意一下

Name Value
username joe
password 123
admin False

可以看到我剛才輸入的 username 和 password 都儲存在 cookies 裡面,而 admin 的 value 是 False,看來 cookie 是以這個數值去傳送給伺服器,然後伺服器透過 admin 的 value 來判斷是否為管理員。

image

把 admin 的 value 改成True (注意是有區分大小寫),然後 F5 重新整理網頁

dont-use-client-side (100 points)

Can you break into this super secure portal? https://jupiter.challenges.picoctf.org/problem/29835/ (link) or http://jupiter.challenges.picoctf.org:29835

Never trust the client

首先看到是一個登入畫面

image

隨便打幾句密碼,彈出一個”視窗”提示密碼錯誤,這個彈出”視窗”有似乎是用 JavaScript

image

查看一下原始碼

<html>
<head>
<title>Secure Login Portal</title>
</head>
<body bgcolor=blue>
<!-- standard MD5 implementation -->
<script type="text/javascript" src="md5.js"></script>

<script type="text/javascript">
  function verify() {
    checkpass = document.getElementById("pass").value;
    split = 4;
    if (checkpass.substring(0, split) == 'pico') {
      if (checkpass.substring(split*6, split*7) == '723c') {
        if (checkpass.substring(split, split*2) == 'CTF{') {
         if (checkpass.substring(split*4, split*5) == 'ts_p') {
          if (checkpass.substring(split*3, split*4) == 'lien') {
            if (checkpass.substring(split*5, split*6) == 'lz_7') {
              if (checkpass.substring(split*2, split*3) == 'no_c') {
                if (checkpass.substring(split*7, split*8) == 'e}') {
                  alert("Password Verified")
                  }
                }
              }
      
            }
          }
        }
      }
    }
    else {
      alert("Incorrect password");
    }
    
  }
</script>
<div style="position:relative; padding:5px;top:50px; left:38%; width:350px; height:140px; background-color:yellow">
<div style="text-align:center">
<p>This is the secure login portal</p>
<p>Enter valid credentials to proceed</p>
<form action="index.html" method="post">
<input type="password" id="pass" size="8" />
<br/>
<input type="submit" value="verify" onclick="verify(); return false;" />
</form>
</div>
</div>
</body>
</html>

發現了驗證 Password 的步驟是透過前端 JavaScript 驗證的,雖然打亂了排序,但我們可以重組啊,難怪題目叫做 Don’t use client side。

可以手動重組或者寫 python

#!/usr/bin/env python

import requests

r = requests.get('https://2019shell1.picoctf.com/problem/45147')
lines = r.text.split('\n')

lines = [l for l in lines if 'if ' in l]
lines = [l.split('==') for l in lines]
lines = list(sorted(map(lambda x: (x[0].strip(), x[1].split('\'')[1]), lines)))

s = ''
s += lines[0][1]
s += lines[-1][1]
for l in lines[1:-1]:
  s += l[1]

print s

得到flag picoCTF{no_clients_plz_7723ce}


Cryptography

The Numbers (50 points)

The numbers… what do they mean?

Hints : The flag is in the format PICOCTF{}

先看圖片,發現了 {} ,跟我們要的 flag 很像,而且 { 前面有 7 個數字,可能剛好是對應 picoctf

the_numbers

所以這題就是 1 = a ; 2 = b ; 3 = c ,以此類推,可以手寫或用 python 轉換

num = input("input>>")
num_list = num.split()
print(num_list)
new_num_list = [int(c) + 96 for c in num_list]
print(new_num_list)
flag = [chr(int(num)) for num in new_num_list]
print(flag)

Easy1 (100 points)

Description The one time pad can be cryptographically secure, but not when you know the key. Can you solve this? We’ve given you the encrypted flag, key, and a table to help UFJKXQZQUNB with the key of SOLVECRYPTO. Can you use this table to solve it?.

Hints 1 : Submit your answer in our flag format. For example, if your answer was ‘hello’, you would submit ‘picoCTF{HELLO}’ as the flag.

Hints 2 :Please use all caps for the message.

table內容:

    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 
+----------------------------------------------------
A | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
B | B C D E F G H I J K L M N O P Q R S T U V W X Y Z A
C | C D E F G H I J K L M N O P Q R S T U V W X Y Z A B
D | D E F G H I J K L M N O P Q R S T U V W X Y Z A B C
E | E F G H I J K L M N O P Q R S T U V W X Y Z A B C D
F | F G H I J K L M N O P Q R S T U V W X Y Z A B C D E
G | G H I J K L M N O P Q R S T U V W X Y Z A B C D E F
H | H I J K L M N O P Q R S T U V W X Y Z A B C D E F G
I | I J K L M N O P Q R S T U V W X Y Z A B C D E F G H
J | J K L M N O P Q R S T U V W X Y Z A B C D E F G H I
K | K L M N O P Q R S T U V W X Y Z A B C D E F G H I J
L | L M N O P Q R S T U V W X Y Z A B C D E F G H I J K
M | M N O P Q R S T U V W X Y Z A B C D E F G H I J K L
N | N O P Q R S T U V W X Y Z A B C D E F G H I J K L M
O | O P Q R S T U V W X Y Z A B C D E F G H I J K L M N
P | P Q R S T U V W X Y Z A B C D E F G H I J K L M N O
Q | Q R S T U V W X Y Z A B C D E F G H I J K L M N O P
R | R S T U V W X Y Z A B C D E F G H I J K L M N O P Q
S | S T U V W X Y Z A B C D E F G H I J K L M N O P Q R
T | T U V W X Y Z A B C D E F G H I J K L M N O P Q R S
U | U V W X Y Z A B C D E F G H I J K L M N O P Q R S T
V | V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
W | W X Y Z A B C D E F G H I J K L M N O P Q R S T U V
X | X Y Z A B C D E F G H I J K L M N O P Q R S T U V W
Y | Y Z A B C D E F G H I J K L M N O P Q R S T U V W X
Z | Z A B C D E F G H I J K L M N O P Q R S T U V W X Y

知識點 :

看到上面的表格就要聯想到維吉尼亞密碼 (Vigenere)

密文 = UFJKXQZQUNB

KEY = SOLVECRYPTO

密碼和 KEY 的長度都是一樣 11 個位

可以拆想成明文第一個字母 未知 偏移了 S 位,得出密文 U,通過上面表格,得知明文第一個字母 未知C,以此類推,得出明文

明文 = CRYPTOISFUN

注意這題內容要全大寫,構成 flag picoCTF{CRYPTOISFUN}

13 (100 points)

Description Cryptography can be easy, do you know what ROT13 is? cvpbPGS{abg_gbb_onq_bs_n_ceboyrz}

Hints : This can be solved online if you don’t want to do it by hand!

關鍵詞 : ROT13

英文字母共有 26 個,如果分成 2 組,每組就有 13 個,可以兩兩替換。

480px-ROT13_table_with_example svg

不必手算,直接 Google 找 ROT13 decode 的網站就出答案

構成 flag picoCTF{not_too_bad_of_a_problem}

caesar (100 points)

Decrypt this message.

Hints : caesar cipher tutorial

知識點 :

凱撒密碼 (Caesar cipher)

如果一串字原本是 ABC,偏移量是 3 的話,就會變成 DEF

簡單來說,就是進行每個字母的偏移,

A -> B -> C -> D

B -> C -> D -> E

C -> D -> E -> F

下載後的 ciphertext:

picoCTF{ynkooejcpdanqxeykjrbdofgkq}

我們雖然不知道這串文字到底偏移量是多少位,但我們知道最多就 26 種偏移組合。

把其中字串 ynkooejcpdanqxeykjrbdofgkq 透過網站 https://www.dcode.fr/caesar-cipher 做 caescar Cipher 的解密,它會把 26 種不同的組合都列出,並把最優解 crossingtherubiconvfhsjkou 放在首位

構成 flag picoCTF{crossingtherubiconvfhsjkou}


Reverse Engineering

vault-door-training(50 points)

Your mission is to enter Dr. Evil’s laboratory and retrieve the blueprints for his Doomsday Project. The laboratory is protected by a series of locked vault doors. Each door is controlled by a computer and requires a password to open. Unfortunately, our undercover agents have not been able to obtain the secret passwords for the vault doors, but one of our junior agents obtained the source code for each vault’s computer! You will need to read the source code for each level to figure out what the password is for that vault door. As a warmup, we have created a replica vault in our training facility. The source code for the training vault is here: VaultDoorTraining.java

The password is revealed in the program’s source code.

不要害怕程式碼,讀下去就對了,答案就藏在最後。

import java.util.*;

class VaultDoorTraining {
    public static void main(String args[]) {
        VaultDoorTraining vaultDoor = new VaultDoorTraining();
        Scanner scanner = new Scanner(System.in); 
        System.out.print("Enter vault password: ");
        String userInput = scanner.next();
	String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
	if (vaultDoor.checkPassword(input)) {
	    System.out.println("Access granted.");
	} else {
	    System.out.println("Access denied!");
	}
   }

    // The password is below. Is it safe to put the password in the source code?
    // What if somebody stole our source code? Then they would know what our
    // password is. Hmm... I will think of some ways to improve the security
    // on the other doors.
    //
    // -Minion #9567
    public boolean checkPassword(String password) {
        return password.equals("w4rm1ng_Up_w1tH_jAv4_be8d9806f18");
    }
}

構成 flag picoCTF{w4rm1ng_Up_w1tH_jAv4_be8d9806f18}

vault-door-1 (100 points)

This vault uses some complicated arrays! I hope you can make sense of it, special agent. The source code for this vault is here: VaultDoor1.java

Hints : Look up the charAt() method online.

先打開 VaultDoor1.java

import java.util.*;

class VaultDoor1 {
    public static void main(String args[]) {
        VaultDoor1 vaultDoor = new VaultDoor1();
        Scanner scanner = new Scanner(System.in);
        System.out.print("Enter vault password: ");
	String userInput = scanner.next();
	String input = userInput.substring("picoCTF{".length(),userInput.length()-1);
	if (vaultDoor.checkPassword(input)) {
	    System.out.println("Access granted.");
	} else {
	    System.out.println("Access denied!");
	}
    }

    // I came up with a more secure way to check the password without putting
    // the password itself in the source code. I think this is going to be
    // UNHACKABLE!! I hope Dr. Evil agrees...
    //
    // -Minion #8728
    public boolean checkPassword(String password) {
        return password.length() == 32 &&
               password.charAt(0)  == 'd' &&
               password.charAt(29) == '9' &&
               password.charAt(4)  == 'r' &&
               password.charAt(2)  == '5' &&
               password.charAt(23) == 'r' &&
               password.charAt(3)  == 'c' &&
               password.charAt(17) == '4' &&
               password.charAt(1)  == '3' &&
               password.charAt(7)  == 'b' &&
               password.charAt(10) == '_' &&
               password.charAt(5)  == '4' &&
               password.charAt(9)  == '3' &&
               password.charAt(11) == 't' &&
               password.charAt(15) == 'c' &&
               password.charAt(8)  == 'l' &&
               password.charAt(12) == 'H' &&
               password.charAt(20) == 'c' &&
               password.charAt(14) == '_' &&
               password.charAt(6)  == 'm' &&
               password.charAt(24) == '5' &&
               password.charAt(18) == 'r' &&
               password.charAt(13) == '3' &&
               password.charAt(19) == '4' &&
               password.charAt(21) == 'T' &&
               password.charAt(16) == 'H' &&
               password.charAt(27) == '5' &&
               password.charAt(30) == '2' &&
               password.charAt(25) == '_' &&
               password.charAt(22) == '3' &&
               password.charAt(28) == '0' &&
               password.charAt(26) == '7' &&
               password.charAt(31) == 'e';
    }
}

看來是一個判斷密碼是否正確的程式,判斷方式是逐字比較。

這裡可以了解一下 charAt() 這個函式的作用,簡單來說就是返回索引值的字符。值得注意索引是從 0 開始。

例 :

“Hello World” 這句子一共有 11 個字符(含空格)

charAT(0) 就是 H

charAt(1) 就是 e

題解 :

從索引值 0 開始一值到索引值 31 ,共 32 位的長度,重組一遍就會知道密碼是什麼。

重組後得字串 d35cr4mbl3_tH3_cH4r4cT3r5_75092e

構成 flag picoCTF{d35cr4mbl3_tH3_cH4r4cT3r5_75092e}


Forensics

Glory of the Garden (50 points)

This garden contains more than it seems.

Hints : What is a hex editor?

知識點 :

隱寫術 (Steganography)

它雖然是一張 .jpg 的圖片,但是可以把我們想放的文字放到圖片裡面。

直接把圖片用文字方式開檔(就連記事本也行),看到密密麻麻的英文和數字混合,然後搜尋”picoCTF”這串字,發現藏在文字的最後。

image


General Skills

Warmed Up (50points)

What is 0x3D(base 16) in decimal (base 10)

Hints : Submit your answer in our flag format. For example, if your answer was ‘22’, you would submit ‘picoCTF{22}’ as the flag.

就是把 16 進位轉成 10 進位,可用線上工具或者自行寫程式例如 Python :

str = input("input>>")
flag = int(str,16) #16進位轉interger
print(flag)

2Warm (50 points)

Can you convert the number 42 (base 10) to binary (base 2)?

Hints : Submit your answer in our competition’s flag format. For example, if your answer was ‘11111’, you would submit ‘picoCTF{11111}’ as the flag.

就是把 10 進位轉成 2 進位,可用線上工具或者自行寫程式例如 Python :

str = input("input>>")
flag = bin(int(str)) #由於str是字串,要先用int(str)轉成數字型態
print(flag)

Lets Warm Up (50points)

If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?

Hints : Submit your answer in our flag format. For example, if your answer was ‘hello’, you would submit ‘picoCTF{hello}’ as the flag.

就是把 16 進位轉成 ASCII ,可用線上工具或者自行寫程式例如 Python :

str = input("here>>")
flag = chr(int(str,16))
print(flag)

what’s a net cat? (100 points)

Using netcat (nc) is going to be pretty important. Can you connect to jupiter.challenges.picoctf.org at port 25103 to get the flag?

Hints : nc tutorial

netcat 是一個在 CTF 經常會使用的工具之一,通常看到 IP 和 Port 這 2 項資訊,都可嘗試看看 nc (netcat) 連線

在 linux 和 Mac 下的 Terminal ,都自帶了 nc 命令

nc jupiter.challenges.picoctf.org 25103

如果想在 Windows 下使用 nc ,到這裡下載,使用方法是在 cmd 裡執行 nc.exe

>nc.exe jupiter.challenges.picoctf.org 25103

nc 後就能看到伺服器的畫面

You're on your way to becoming the net cat master
picoCTF{nEtCat_Mast3ry_d0c64587}

strings it (100 points)

Can you find the flag in file without running it?

Hints : strings

不用執行它,用任何的文本(記事本也行)打開它,然後搜尋 “picoCTF” 就能找到 Flag

當然可以藉此熟悉一下 Linux 的指令 strings

image

Bases (100 points)

What does this bDNhcm5fdGgzX3IwcDM1 mean? I think it has something to do with bases.

Hints : Submit your answer in our flag format. For example, if your answer was ‘hello’, you would submit ‘picoCTF{hello}’ as the flag.

知識點 :

base64

一般來說,進行了 base64 編碼後都會有一個很明顯的特徵,它們後面大多都會是 === 結尾。

不過它只是一個明顯的重要特徵。通常結尾有 這個特徵的話幾乎可以肯定是 base64 編碼,但沒有這個特徵也有可能是 base64 編碼。

如果了解一下 base64 的結構,就可以發現,當原字串的總長度是 3 的倍數時,那進行 base64 編碼後,就不會有 結尾。而當總長度不足 3 的倍數時,就會以 結尾補齊。

把這字串 bDNhcm5fdGgzX3IwcDM1 進行 base64 decode 得到 l3arn_th3_r0p35

構成 flag picoCTF{l3arn_th3_r0p35}

First Grep (100 points)

Can you find the flag in file? This would be really tedious to look through manually, something tells me there is a better way.

Hints : grep tutorial

知識點 :

使用 linux 的 grep 命令

其實 flag 就藏在眾多文字裡,搜尋文字的方法不少,但這題是想我們嘗試的去用 linux 指令去獲得

$ cat file | grep "picoCTF"
picoCTF{grep_is_good_to_find_things_f77e0797}

Binary Exploitation

(無 100 分以下題目)