はじめに
自社のLT大会において発表した内容を、実装部分をちょい省いて焼き増したものです。
モチベーション
自己紹介ページってプログラミングを学ぶ登竜門じゃないですか。
やっぱり、簡単なものから作って学んで行くって大事だと思うんですよね。
というわけで、Webフロントだけで完結するシェルを作りましょう。
(シェルが簡単かどうかは諸説ありますが、本記事では簡単に「それっぽいの」を作れるように目指します)
あと、これ作ることでCTFみたいな問題を作ることができると思うんです。
通信しないのでローカルで完結しますし、WASMを分析して回答を得るとか、そういうのも問題として現在の解析インフラ的な状況(余り優秀なツールがない時)だとアリだと思ってます。
あとは普通に、出題者が意図したとおりにコマンドを実行してアクセス制御機構を掻い潜りフラグを得るというのでもOKだと思います。
そんなところにもモチベーションがあります。
でもまずは、シェルを作ってその上で動作するプログラムを作り、そこで自己紹介ができるようになるというものを目指します。
とりあえずざっくり3日位で作れる所までのボリューム感でやっていきます!
3日で作れるシェル!
なんて?
- GitHubPagesで自己紹介ページ作りたくない?
- 作りたいよね?そうだよね?
- 3日でそれっぽいシェル作ろう!
何をしたいの?何を求めるの?
ロマンを求めるために、フロントだけで動くシェルを作るんです。
工程表
1日目:シェル全体の管理とオンメモリなファイルシステムを作る
2日目:アクセス権限を管理するモジュールと、アカウント管理をするモジュールを作る
3日目:それっぽく動くコマンドをなにか1個作る
とりあえず機能モデルとかの話
- シンプルなファイルシステム(随意アクセス制御・DAC)
- ファイルシステム関連コマンド(mkdir/mktext*)
- *mktext:リダイレクションははじめのうちは実装しないので、テキストファイルを作るためのコマンド
- キャティネイトコマンド(cat)
- リストコマンド(ls)
- デバイスファイル(/dev/urandom)
- 最初は
/dev/random_text
というデバイスを作って、ランダムなテキストを表示するようにする。将来的に(やるかは気分次第)バイナリも使えるようになる予定なので/dev/urandomを実装しようと思う。
- 最初は
- 権限昇格コマンド(sudo)
- DACと仮想FSの機能を使って特権昇格してコマンド実行するものを作る
- ログイン中ユーザ表示コマンド(whoami)
- sudoコマンド検証用のコマンド、誰(どの権限のユーザ)が今実行してるかを表示する
使う言語(フレームワークとか)
言語 | 使う目的 |
---|---|
Rust(Yew) | WASMに変換される、ファイルシステムとかはこっちで実現する |
JS | そのままJS、Rust側に入力されたコマンドを渡す役割 |
xterm.js | JSから触る、WASM側から受け取った応答を表示するだけ。単なるUIの枠としてつかうだけ。カッコいい |
全体像
基本的な考え方
- 実際のファイルシステムを持つわけではない
- オンメモリでファイルシステムを実装しなければならない
- デバイスファイルはファイルとして振る舞う関数ポインタとして実装する
- コマンドもファイルではないので、関数として実装する。
- ファイルとして扱うことも視野に入れる。
- ただし、最初は「ファイルとして振る舞わなくて良い」ところまでを目指す。
- 実際のLinuxを目指すとコマンド数が多いので、「それっぽく動く」を目指す。
- 各コマンドの再現に関する厳格性は追求しない
実装を軽く舐める
シェル全体を表すオブジェクト:ShellService
アカウントを表現するオブジェクト:Account
アクセス権限を管理するオブジェクト:Authority
ファイルシステムを表現するオブジェクト:FileSystemService
各コマンド:<コマンド名>_service
catコマンド
sudoコマンド
デバイスファイルの実装
JS部分との結合部
おまけ:上下キーでヒストリを出すやつ
感想
自己紹介をするスタートラインに立てた。
lockコマンドと、unlockコマンドを新しく実装したので叩いてみてほしい。
unlockを叩くとタブがunlockされるので。
おわり。
# ん・・・?
自己紹介がない?
そりゃそうだよ、まだ作り途中だもん。
自己紹介って難しいね。
説得力の有る攻撃シナリオを考えるのが一番厳しいかも。
後日談:それっぽい自己紹介を出すコマンドを実装した
segfoコマンドです。叩いてみてください(URLが出ますw)
3割位完成しました