CTFのWriteup、もしくは、セキュリティ関連の解説において"gadget"という言葉が出てくることがある。
ググラビティが低いために思ったような情報が出てこなかったり、gadgetは攻撃の一部で利用されることもあってフィーチャーされないといったことがあるので、
これから勉強する人のためにまとめておく。
概念的な話になるので、なるべく同じ内容を複数回、別のアプローチで説明していくことを心掛ける。
なお、CTFではpwnとwebでしか出てこない。
入門者向きではないが、中級者いかないくらいの難易度の記事だと思う。
"gadget"
日本語でガジェットと言うと、便利な小物家電みたいなイメージがあるが、おおよそそのようなイメージで問題ない。
「便利」で「小さい、もしくは、欠片」なものである。
加えて、セキュリティにおけるgadgetで重要な要素として「攻撃先の環境に存在する」という要素があげられる。
ふんわりしているので、セキュリティにおけるgadgetの意味する所を明言しておこう。
セキュリティにおけるgadget
攻撃先の環境に存在して、攻撃の過程で便利に使える、とあるパーツのこと
「とあるパーツ」ってなんだ!!!
ごもっとも。
例示をしながら説明していく。
pwn -> webの順で説明をしているが、得意なジャンルに応じてwebから読んでも問題ない。
[pwn] Return-Oriented Programming
pwnをやっている人からするとROPでgadgetという言葉を見ると思う。
この記事で説明しようとしている概念になぜgadgetという言葉が割り当てられているのか起源を見つけることはできなかったが、
ROPのwikipediaにgadgetについて書かれているのが確認できる。
Return-oriented programming - Wikipedia
ROPはバイナリに既に存在するコードの断片を組み合わせることで意図した処理を実行するテクニックのことである。
例えば、バイナリにpop rdi; ret
という命令列の断片があれば、これを利用することで関数呼び出しの第一引数を指定することができる。
この時のpop rdi; ret
がgadgetである。
gadgetは基本的には攻撃の1パーツとして使われる。
例えばバッファーオーバーフロー脆弱性が見つかったとして、そこから攻撃を前進させたいとする。
RCEにつなげるために、何か「攻撃先の環境に存在して、攻撃の過程で便利に使える、とあるパーツ」がないかなーと探すとpop rdi; ret
が見つかる。
このgadgetをうまく使うことで関数呼び出しを行うことができるようになり、最終的にRCE達成できる。
こういった1パーツをgadgetと呼ぶ。
[pwn] one-gadget RCE
仮想関数テーブル、one-gadget RCE、glibc 2.31 - Qiita
特定のレジスタ状態を満たす場合に、glibcの特定のアドレスに制御を移してシェルを起動させるテク。
これも「攻撃先の環境に存在して、攻撃の過程で便利に使える、とあるパーツ」がglibcにあって、うまく使うという話。
[web] Prototype Pollution
javascriptにはPrototype Pollutionという脆弱性がある。
これはjavascriptのプロトタイプチェーンの機能に起因して引き起こされる脆弱性である。エッセンスを抽出すると以下のような形となる。
user = {}; other = {}; // 存在しないフィールド console.log(user.isAdmin); // undefined // Prototype Pollution input1 = '__proto__'; input2 = 'isAdmin'; input3 = 'true'; other[input1][input2] = input3; // なぜか存在している! console.log(user.isAdmin); // true
other[input1][input2] = input3;
が重要な部分で、どこでもいいのでこのような場所があると任意の未定義のフィールドを設定することができる。
Prototype Pollutionの重要な部分として、脆弱性を使ってできることは「任意の未定義のフィールドを設定すること」までであるということである。
攻撃を進めるためには、これを使ってさらに何かを発動させる必要がある。
それっぽく言うと、この脆弱性を悪用できる「攻撃先の環境に存在して、攻撃の過程で便利に使える、とあるパーツ」が無いかなーという話になる。
もっとそれっぽく言うと、なんか使えるgadget無いかなーという感じ。
色々紹介されている。RCEに限らず、本当に色々なことを引き起こすことができる。
forkの例を説明する。
const { fork } = require('child_process'); var proc = fork('something');
どこでもいいので、上記のようなforkを呼び出す箇所があったとする。
このときにprototype pollutionで
b = {} b.__proto__.env = { "EVIL":"console.log(require('child_process').execSync('touch /tmp/fork-environ').toString())//"} b.__proto__.NODE_OPTIONS = "--require /proc/self/environ"
のように未定義のフィールドを用意して、その後にforkを呼び出す箇所を通るようなAPIなどを実行すると、定義されたフィールドを参照して、任意コード実行が達成できる。
この場合では、「Prototype Pollutionがあるので、gadgetとしてfork関数を使ってRCE達成した」みたいな説明の仕方になると思う。
gadgetとして使えるものはたくさん発見されている。
BlackFan/client-side-prototype-pollution: Prototype Pollution and useful Script Gadgets (クライアントサイドのものですが)
Prototype Pollutionの問題ではgadgetを探すことを要求されるものもある。
CakeCTF 2022を開催しました - CTFするぞ (記憶に新しいCakeCTF 2022のPanda Memo)
[web] Insecure Deserialization
外部からデシリアライズするデータを渡せるとき、任意のクラスの任意の状態のインスタンスを作成するテク。
詳しくは安全でないデシリアライゼーション(Insecure Deserialization)入門 | 徳丸浩の日記
単純にunserialize($_COOKIE['FOO']);
みたいな形になっていると任意の入力がデシリアライズされて、いかにも危ないよねみたいな感じ。
これも、任意のクラスの任意の状態のインスタンスが作成できるまでの脆弱性なので、これを利用して攻撃を進める必要がある。
つまり、「攻撃先の環境に存在して、攻撃の過程で便利に使える、とあるパーツ」として使える任意のクラスや特定の状態というのを探す必要がある。
あえて言うとgadgetが必要になる。
使えるgadgetは言語ごとにレポジトリがある。
- java: frohoff/ysoserial: A proof-of-concept tool for generating payloads that exploit unsafe Java object deserialization.
- php: ambionics/phpggc: PHPGGC is a library of PHP unserialize() payloads along with a tool to generate them, from command line or programmatically.
- .NET: pwntester/ysoserial.net: Deserialization payload generator for a variety of .NET formatters
- 他にもいろいろありそう
どれでも共通なのだが、有名な脆弱なライブラリが既に使われている場合にそのライブラリの特定クラスを特定の状態にしたインスタンスをシリアライズして、送り込むことでRCEまで持って行ける。
[web] Breaking XSS mitigations via Script Gadgets
black hatで講演されたタイトルそのまま。
Script Gadgetsのデモを作成してみた. 2019年1月にOWASP Kansai スクールキャラバン2019… | by Yuji Yamasaki | inet-lab | Medium
日本語で解説されているものがあるのでそっちを読んでもいい。
今までとは違って他の脆弱性先行な感じではなく、「攻撃先の環境に存在して、攻撃の過程で便利に使える、とあるパーツ」が最初に来ているような使い方。
gadgetはスラング的な感じだと思っているので、みんな思い思いに使っているんだと思う。
[おまけ] gadget chain
ROP chainとかgadget chainとか、この辺はchainという言葉がよく一緒に使われる。
これは特定の脆弱性から攻撃を前進させるために他のgadgetにchainさせて(連携させて)いくということを言いたいのだと推測される。
gadget chainって言葉の響きがかっこいいから使われてるだけだと思う。
「Insecure Deserializationと古いLaravelがあるから、gadget chainでRCEできそう」みたいなかっこいい文章が作れます。
gadget chainって2ホップすることあるんかな?
Insecure Deserialization -> gadget1 -> gadget2 -> RCE
みたいな。
無理矢理やればできなくはなさそうだけど、それっぽいシナリオ作れるんでしょうか。どうなんでしょう。
終わりに
gadgetという言葉はおそらく雰囲気で生まれた言葉なので、雰囲気で理解しておくのがいいと思う。
多分みんな正確な定義は知らない。
俺だけじゃないよね。
多分ね。