LoginSignup
1
0

More than 5 years have passed since last update.

pico ctf 2017 web exploitation write up

Last updated at Posted at 2018-09-13

目的

解き方を思い出すため

解法

Level1

What Is Web

websiteを開いてdeveloperツールを使うと以下のhtmlソースを見ることができる

index.html

</html>

<!-- Cool! Look at me! This is an HTML file. It describes what each page contains in a format your browser can understand. -->
<!-- The first part of the flag (there are 3 parts) is 8d96c7d8966 -->
<!-- What other types of files are there in a webpage? -->

3つのフラグがあることがわかる
こんな感じで他のファイルにも隠されているのではと考えると簡単に2つ見つかる

script.js
/* This is a javascript file. It contains code that runs locally in your
 * browser, although it has spread to a large number of other uses.
 *
 * The final part of the flag is 3b680682297
 */


function sayHI(){
    alert("Hi there!");
}
hacker.css
/*
This is the css file. It contains information on how to graphically display
the page. It is in a seperate file so that multiple pages can all use the same 
one. This allows them all to be updated by changing just this one.
The second part of the flag is 8106eabacc0 
*/

3つ繋げたらflagになる

Level2

My First SQL

sqlインジェクションを試みる.

まず, パスワードに'のみでloginするとThere Was An Error With Your Requestselect * from users where user = '' and pass = ''';が帰ってくる. これでSQLインジェクションが有効なことがわかり, さらにクエリの全貌までわかった. userカラムは考えずwhere句にorを入れることを考える.

よって, パスワードにa ' or 'a' = 'aを入れるとflag get.

TW_GR_E1_ART

node.jsを使ったロールプレイングゲームとなっている.
4Fでたくさんのフラグがあり, ある一つの正しいflagを使用するとctfのflagがゲットできるが間違ったflagを使用するとゲームが終わってしまい初めからやり直すことになってしまう.

まんまとやり直しになったのでヒントを見る.

I think this game is running on a Node.js server. If it's configured poorly, you may be able to access the server's source. If my memory serves me correctly, Node servers have a special file that lists dependencies and a start command; maybe you can use that file to figure out where the other files are?

node.jsのソースが見れちゃいそうなので, まずpackage.jsonにアクセスしてみる

package.json
{
  "name": "rogue-1",
  "version": "1.0.0",
  "main": "server/serv.js",
  "dependencies": {
    "beautiful-log": "^1.3.0",
    "body-parser": "^1.16.0",
    "callsite": "^1.0.0",
    "clone": "^2.1.0",
    "colors": "^1.1.2",
    "cookie-parser": "^1.4.3",
    "deep-diff": "^0.3.4",
    "dequeue": "^1.0.5",
    "express": "^4.14.1",
    "mongodb": "^2.2.25",
    "morgan": "^1.7.0",
    "nconf": "^0.8.4",
    "promise": "^7.1.1",
    "socket.io": "^1.7.2",
    "sprintf": "^0.1.5"
  },
  "devDependencies": {},
  "scripts": {
    "prestart": "node server/init.js",
    "start": "node server/serv.js"
  }
}

サーバーを起動する2つのスクリプトの場所がわかるので, 一旦server/serv.jsを見てみる.

serv.js
var express     = require("express");
var app         = express();

app.use(require("body-parser").json());
app.use(require("cookie-parser")());
// app.use(require("morgan")("dev"));

var http        = require("http").Server(app);
var path        = require("path");
var fs          = require("fs");
var Promise     = require("promise");
var logger      = require("./logger");
var sprintf     = require("sprintf");
var nconf       = require("nconf");
var db          = require("./db");
var io          = require("socket.io")(http);

require("./game")(app, io);

nconf.argv().env();

var PORT = nconf.get("port") || 8888;

app.get("/", function(req, res){
    res.status(200);
    res.sendFile(path.join(__dirname, "../public/html/index.html"));
});

app.use(express.static(path.join(__dirname, "..")));

http.listen(PORT, function(){
    logger.info("[server] Listening on *:" + PORT);
});

process.on("unhandledRejection", (err) => {
    logger.error(err.stack);
});

gameに関するエンドポイントがserver/game.jsにあることがわかる. このソースは長いので, flagで検索をかけてみる.

game.js
            case "revealFlag":
                if (entity.items[action.item].effects[i].check == 64) {
                    outcome.flag = process.env["PICO_CTF_FLAG"];
                }
                break;
        }

.checkが64ならばflagがもらえそう. ここで?server/config.jsファイルをみるとflagの生成場所に関するソースが見れる.

config.js
                    var r = Math.floor(idx / 5) + 1;
                    var c = (idx % 5) + 1;

                    return createFlag(idx, { r: r, c: c });
                }),

ここで, idx = 64で計算すると r = 13, c = 5となる.

[ -4,  -3,  -3,  -3,  -3,  -3,  -2],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1, flag, -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -5,   1,   1, stair, 1,   1,  -1],
[ -5,   1,   1,   1,   1,   1,  -1],
[ -6,  -7,  -7,  -7,  -7,  -7,  -8]

この場所のflagが正しいflagとなる

TW_GR_E2_EoTDS

同じようなゲームが再び.
4階に行くとフラグが壁に囲まれていてgetできなくなっている.
敵もアイテムを取得できる特性を使う.

今度は/server/ai.jsの中身を見ると敵の動きが書かれている.

ai.js
// If the player is nearby (at most 3 steps) or is in the same room, move toward them
...
// If we're in a corridor, try to keep moving in the same direction
...
// If nothing else, do something random

部屋が同じか3ステップ以内ならば近づく.
1直線の場所ならば同じ方向に進み続ける.
そうでなければランダムに進むらしい.

4階で斜め移動を駆使して敵と鬼ごっこをしているとランダムでプレイヤーが通れない場所を通ってくれる.
そこで壁の外から敵に近づいてフラグを取らせて敵を倒すとフラグget.
ただのゲーム.

スクリーンショット 2018-09-20 23.37.30.png

Level3

Biscuit

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0