本サイトは、快適にご利用いただくためにクッキー(Cookie)を使用しております。
Cookieの使用に同意いただける場合は「同意する」ボタンを押してください。
なお本サイトのCookie使用については、「個人情報保護方針」をご覧ください。

最新情報

2023.11.06

ChatGPTで脆弱性を探す

MBSDでWebアプリケーションスキャナの開発をしている寺田です。

遅ればせながら、ひと月ほど前から有料版のChatGPT(GPT-4, Plus)を使い始めました。ChatGPT-3.5と比べると応答は遅いですが、人間からの指示の理解力はかなり高いという印象です。筆者がGPTを使うのは、たまに開発のテストデータ作成などをしてもらうのが主な目的ですが、Webアプリケーションスキャナの機能強化に使えそうなアイディア探しも行っています。

その一環で、最近はテストサイトに存在するWebアプリケーションの脆弱性をGPT-4に探させる試みをしており、今回はその結果を簡単に紹介したいと思います。本記事では主にWhitebox手法(ソースコードなどを参照して脆弱性を見つける)を取り上げています。

過去の実施例

当然、筆者より前に同じことを考えて、ChatGPTにソースコードのセキュリティ診断をさせた方たちがいます。

日本語のものとしては以下の情報が見つかりました。

Open AI – ChatGPT に脆弱性診断をやらせてみた - 二本松 哲也

ChatGPTのCode Interpreterのコードリーディング能力は結構優秀 - laiso

何らかの考察を加えているものは、以下の記事です(英文)。

Security Code Review With ChatGPT - NCC Group

NCC Groupの記事の結論は「Don't use ChatGPT for security code review」です。その理由として、分析できるソースコードの分量の制限偽陽性の多さ、そして(そもそも論の)外部サーバにソースコードを送る必要があることなどを挙げています。筆者の感想もこれに近いのですが、検証の中でChatGPTならではのユニークな長所も見つけられたため、以下で概略を説明したいと思います。

この分野ではAcademicな世界でも研究がなされています。いくつかのペーパーを本記事の末尾に挙げました。

ChatGPTの長所

筆者が考えるところ、ソースコード診断におけるChatGPTの長所は以下の3点です。

  1. ペイロードの作成能力(DOMXSS)
  2. ロジックの理解力
  3. 拡張性

以下で順番に見ていきましょう(この節ではChatGPTの優れた面のみを紹介しています)。

長所1: ペイロードの作成能力(DOMXSS)

DOMXSS-1

最初に試したのは以下のHTML/JavaScriptコードです。

domxss01.png

URLSearchParamsを使ってlocation.hashから'hoge'パラメータを取り出し、それをdiv要素のinnerHTMLに入れるプログラムです。脆弱性のPoC(Proof of Concept)のURLは以下のようなものになります。

http://host/#hoge=<img src=_ onerror=alert()>

ChatGPTに脆弱性を探してもらいましょう。赤下線は筆者によるものです(以下同)。

domxss01_qa.png

PoCのURL、対策ともに満点の回答です。

DOMXSS-2

今度はもう少しだけ長いコードで試します。

domxss02.png

parse関数は、key=value&...形式の文字列を受け取り、それをオブジェクトに変換したものを出力します。下の例のとおり、パラメータ名を/で区切って、ネストしたオブジェクトを作成する点が特徴です。

入力: aa/x=1&bb=2
出力: {aa:{x:"1"}, bb:"2"}

DOMContentLoadedイベントでは、クエリストリングをparse()に渡して、戻り値のオブジェクトのsetting.redirプロパティの値をlocation.hrefに入れています。

ソースコードの赤下線の箇所にそれぞれ以下の脆弱性があります。

  • Prototype Pollution
  • DOM Based XSS (DOM Based Open Redirect)

このコードもChatGPTに渡して脆弱性を探してもらいました。

domxss02_1st_ans.png

domxss02_openredir_attack_url.png

パラメータ名の区切りが/であること、setting.redirプロパティを使用することなどをきちんと理解して、動作する正しいURLを組み立てています。ちなみに、区切り文字を変えたり、プリフィックスを必要とするようにparse関数を変更すると、それに応じたペイロードを作ってくれます。賢いですね。

一般的にlocation.hrefへの代入はXSSにも利用できます。この点をChatGPTに質問します。

domxss02_xss_qa.png

XSSについては最初の回答で触れてほしかったのですが、質問(誘導)したら答えてくれました。

DOMXSSの回答から分かること

DOMXSS-1, 2の回答から、ChatGPTに以下の能力があることが分かります。

  • 脆弱性/攻略法についての一般知識
  • コードから読み取った処理内容をもとに脆弱性を発見する
  • コードの処理内容にあわせたペイロードを組み立てる

人間ならできることであり、機械でもこれくらい当然と思われるかもしれませんが、実はそれほど簡単なものではありません。Google Bard, Snyk, Burpで試した結果を以下に書きます。

DOMXSS-1 DOMXSS-2
XSS Prototype Pollution Open Redirect/XSS
ChatGPT 検出+ペイロード 検出 検出+ペイロード
Bard 検出+誤ったペイロード 検出
Snyk 検出
Burp

2023年9月~10月に試した結果です。 BardのDOMXSS-1のペイロードは?nm=<script>alert("XSS")</script>でした。色々と間違ってます。

同じLLMであるBardと比べると、ChatGPT(OpenAI)にはCodex, Github Copilotなどの蓄積があり、コードの解析と組み立て(ペイロード作成を含む)に関しては一歩先を行っているように思います。

長所2: ロジックの理解力

長所の2つ目は、従来のツールでは十分にカバーできなかった、ロジック(ロジック系の脆弱性)の理解力です。ロジック系のバグを含む、PHPの簡単なやられアプリを作って、ChatGPTに診断させた結果が以下です。

server01_logic_ans.png

1つ目の「ブルートフォース攻撃対策の不備」の指摘は正しいです。診断対象のソースコードからロックアウト判定をしている箇所(以下)を特定し、回数(5回)や時間(10分)を読み取っています。

server01_logic_lockout_php.png

2つ目の「アカウント更新の認証の不備」は、やられアプリが以下の処理を行っているため、他人の情報が変更できるという問題です。

  • 会員情報を表示するフォームのhiddenに会員IDを埋め込んでいる。
  • 会員情報を変更する処理では、変更対象の会員IDをリクエストパラメータから取得している。

いわゆるIDOR(Insecure Direct Object Reference)バグですが、この脆弱性も検出しました。

1, 2ともに文脈やデータフローを理解できているように見えます。人間なら当たり前ですし、1つの簡単なやられアプリで検出したにすぎませんが、機械がこういうことをできるのを見ると面白いなーと思います。

長所3: 拡張性

ChatGPTを拡張する、つまり知識や能力を増す方法としては、プロンプトに情報を盛り込むか、モデル自体を微調整するファインチューニングをするかの2つです。GPT-4はファインチューニングに対応していないこと、3.5でのファインチューニングには時間が掛かることから(試したところ時間は40分程度)、今回はプロンプトを使ってみます。

以下は、プロンプトの中で新種の脆弱性「MBSD Injection」を定義して、ChatGPTにそれを検出させた結果です。

mbsd_injection.png

ChatGPTは内容を理解して「MBSD Injection」を検出し、正しいPoCを提示しました。この例で定義したのは何も意味がない脆弱性ですが、独自の診断項目を追加したい時などに使えそうです。自然言語で書いた簡単な指示だけで脆弱性を探してくれるというのは面白いです。

ちなみに、上のコードには「MBSD Injection」だけでなくXSSも存在しますが、XSSもChatGPTで検出できます。

ChatGPTの短所

前節ではChatGPTの長所にフォーカスしましたが、今度は短所を見ていきましょう。

  1. 入力サイズの制限が厳しい
  2. 外部サーバにソースコードを送信する必要がある
  3. 不正確な検出結果(偽陽性/偽陰性)

項目としては冒頭で紹介したNCC Groupの記事と基本的に同じです。以下で順に説明します。

短所1: 入力サイズの制限が厳しい

ChatGPTのプロンプトにはサイズの上限があります。今回取り上げたアプリケーションは最大でも約10KB、トークン数で言うと2K~3Kであり、トークン数の上限である8K(GPT-4のAPI)に達していないため、全ソースコードをAPIのプロンプトに入れて脆弱性を探させました。しかし、トークン数の上限を考えると、通常のWebアプリケーションをまるごと渡して診断させることは現実的ではありません。

β版のAdvanced data analysisを使えば、より大きなプログラムを固めたZIPファイルを診断させることができます。しかし実際にやってみると回答の途中で「Network Error」や「Error in input stream」が発生して先に進まない、あるいは呼び出しメソッドの取得処理の問題によりフローが追えない、などの現象が見られました。つまるところ、現時点においては現実的なサイズのアプリケーションの解析はほとんど機能しないと思います。

GPTが扱えるトークン数は徐々に増えており、最近では最大で32Kまで拡張されています。

短所2: 外部サーバにファイルをアップロードする必要がある

ソースコードに限ったことではありませんが、ChatGPTに入力したデータが学習、つまりモデルの改善に使われ、結果として他のユーザに漏洩する可能性があります。学習利用を防ぐにはブラウザごとに設定が必要です。

data_setting.png

学習利用をしないとしても、入力したデータはChatGPTのサーバに一定期間保存されます。学習利用の有無に関わらず、業務の情報を外部のサーバにpostすることを許さないルールの組織もあるでしょう。ChatGPTを利用する際には、外部サーバに入力データが渡される点も考慮する必要があります。

筆者が所属する組織にもルールがあり、現状postできるのは自前のテストデータや一般に公開されているデータなどに限られています。 AzureのOpenAI ServiceやOpenAIのAPIについては、ChatGPTとは別のポリシーが適用されるようです。詳細はご自身で確認ください。

短所3: 不正確な検出結果(偽陽性/偽陰性)

次は結果の正確さに関する問題です。サンプルとして、筆者が作ったPHPのやられアプリのソースコードを診断させた際に、ChatGPTが指摘した脆弱性の一覧を下に記します。

  1. SQL Injection [OK]
  2. IDOR [OK]
  3. Weak Account Lockout Mechanism [OK]
  4. Insecure Password Storage [偽陽性]
  5. XSS [偽陽性]
  6. CSRF [偽陽性]
  7. Insecure Session Management [偽陽性]
  8. Information Leakage [?]
  9. Missing Input Validation [偽陽性]
  10. Insecure Transport [?]

APIで「Find all vulnerabilities. You don't need to explain countermeasures.」と英語で指示した際の結果です。 同じPHPアプリをBardとSnykに診断させたところ、両者とも(意味のある脆弱性は)検出できませんでした。

ChatGPTが報告した脆弱性は全部で10個あり、そのうち正しく検出されたもの(OK)が3個、偽陽性が5個、その他(判定不能なものや、事実ではあるが指摘する必要が無さそうなもの)が2個という結果です。また、筆者が仕込んだOpen Redirectは上のリストに含まれていないので、偽陰性も1個あるということになります。

偽陰性を減らす方法としては、「XYZ脆弱性はありますか?」というような内容(脆弱性の種類)を絞った質問をするという手があります。実際「Open Redirectはある?」と聞くと見つけてくれました(最初から発見する場合もあります)。偽陽性が増える可能性はありますが、一般的に内容を絞った質問の方が良い応答を得られるので、考えられる脆弱性の種類を挙げて質問していくという手は有効だと思います。

偽陽性は減らせるか?

筆者のやられアプリくらいのサイズ(10KB程度)のプログラムをChatGPTに与えると、コードを斜め読みして「脆弱性があるかもしれない」のレベルで報告してくるようになります。このことも偽陽性の多さにつながっているでしょう。指摘してきた項目に対して1つずつ「True PositiveかFalse Positiveか確認して」と再質問していくと、個別の事項に絞って検討するため正確性が上がります。筆者のPHPアプリでも検出された10個すべてについて再質問したところ、5つの偽陽性のうち3つについて「偽陽性」との返答が得られました。

パラメータの調整によっても偽陽性を減らせる場合があります。APIではtemperature(回答のrandomness)を指定できますが、これを小さくすると回答のバラつきが減ります。IDORバグを修正したやられアプリをChatGPTに診断させると(IDORがないにもかかわらず)誤検出してしまうことがたまにありましたが、この偽陽性はtemperatureの調整で減らせました。バラつきを減らすだけなので根本的な対処ではありませんが、もともと偽陽性が生じる頻度が低いもの(ChatGPT的に確証が低いもの)には効果があると思います。

再現性が低い結果は扱いづらいので、筆者がAPIを使う時は基本的にTemperatureを0にしています。ただし0にしたからといって常に同じ返答になるわけではありません。

脆弱性の定義を変える

偽陽性を減らす他の方法についても検討してみたいと思います。

長所1で取り上げたDOMXSS-1の脆弱性を修正したコード(下記)について、「DOM Based XSSがあるか?」とChatGPTに質問すると、textContentを使用しているにもかかわらず、DOM Based XSSを報告してきます。

domxss01_textcontent.png

このコードにはContent Spoofingの脆弱性があると言えばありますが、XSSはありません。 聞き方(英語で聞いたり、脆弱性が無いという答えを誘導するなど)によっては、XSSを検出しないこともあります。

調べてみたところ、そもそもDOM Elementのプロパティ(input.value, element.dataset.foobar, element.textContentなど)に値をセットしているだけで、DOM Based XSSが検出されてしまうことが分かりました。

以下のような処理をしている時も検出して、動くはずのないPoCを提示してしまいます。

domxss01_repl.png

これらも「True PositiveかFalse Positiveか」と再質問すると正しい結果を返す場合が多いですが、脆弱性の定義を変えることで、偽陽性が減らせるか試してみます。以下のプロンプトを作ってみました。

与えられたコードにMBSD1000脆弱性はありますか? 以下の条件を全て満たすときに、MBSD1000脆弱性が存在するとします。 【条件】 (1) ユーザ入力値を含む文字列が、ElementのinnerHTMLプロパティにセット可能である。 (2) ユーザ入力値に含まれる"<"記号が、ElementのinnerHTMLプロパティへのセットまでに変化しない。 (3) ハードコードされたリテラル値や、ハードコードされたリテラル値から来る変数は、ユーザ入力値とはみなさない。

このプロンプトでは、ChatGPTのDOM Based XSS定義を捨てて、innerHTML専用の新しい脆弱性をゼロから定義しています。

別のアプローチとしては、下のようにChatGPTの脆弱性の定義から誤検出するものを差し引くものもあります。

与えられたコードにMBSD2000脆弱性はありますか? 以下の条件を全て満たすときに、MBSD2000脆弱性が存在するとします。 【条件】 (1) DOM Based XSSがある。 (2) DOM Based XSSを最終的に引き起こす機構が、以下のいずれにも該当しない。  (2-1) ElementのtextContentにユーザ入力値がセットされる。

GPT-3.5では、MBSD1000, 2000ともちゃんと解釈されないかもしれません。

DOMXSS-1のコードでMBSD1000,2000のプロンプトを使うと、innerHTMLではYes、textContentではNo、という期待どおりの返答が得られました。別のコードを診断させるとうまくいかないケースが割と出てきますが、脆弱性有り/無し両方のコード例を何個かプロンプトに足してやると、こちらの意図に近い解釈をしてくれるようになります。

なお、上のMBSD1000, 2000の記述を増やしていけばどんどん精度が上がるのかというと、必ずしもそうではありません。そもそもの「コードの理解力」という土台がフニャっとしている上に精緻なロジックを築いても砂上の楼閣ですし、プロンプトが複雑になるとプロンプトの内容を期待どおりに解釈しなくなる可能性があるからです。ここで言うコードの理解力というのは、データフローの理解や、正規表現パターンの理解など、基本的なコード解析の能力を指しています。筆者がOpen Redirectの検出能力を強化するプロンプトを試作した時には、このコード理解力の問題のために、検出能力を一定のレベル以上に引き上げるのは困難でした。

ペイロード作成

最後にペイロード作成の正確性についても書きます。長所の節ではうまくいった例を取り上げましたが、もう少し複雑になると誤ったペイロードを作成する場合があります。対象は下のコードです。

domxss01_wrong_payload.png

ChatGPTが作った、この脆弱性の攻撃ペイロードは以下です。

#{"hoge":"{\"fuga\":\"<img src=x onerror=alert(1)>\",\"foo\":\"bar\"}"}

正しいのは以下です。

#hoge={"fuga":"<img src=x onerror=alert(1)>"}

注意事項

テストアプリに対するSQL Injection診断用のペイロード作成をChatGPTに依頼すると、たまに以下のような画面が表示されます。

dont_be_evil.png

本ブログ記事も同じ前提です。本記事の内容を不正な目的に利用しないようにお願いします。

まとめ

ChatGPTによるソースコード診断について、筆者が感じた長所と短所を書きました。現状では、厳しいサイズの上限があり、またその上限に収まる小さいアプリでも人間並みの正確なアウトプットは得られないというのが、筆者の感想です(ご存じのとおり、そもそもChatGPTは脆弱性診断用に作られたツールではありません)。

とはいえ、拡張できること、ロジックバグを理解できることなど、ソースコード診断の観点で面白い点があります。これらの点については、下に挙げた研究例の2と3でも活用されています(これらの研究では、汎用的なロジックバグではなく、特定の領域のバグに絞って適用しています)。これまでのツールには無かったこれらの能力を診断に利用したい、という期待は大きいようです。筆者も、より大きなデータを、より賢く、より高速に処理できる日が来れば… と期待しています。

研究例

Whiteboxでの脆弱性発見のためにGPTを使用している研究例です。

1. Technical Report: Evaluation of ChatGPT Model for Vulnerability Detection (2023/4)
脆弱性の修正前/後のソースコードの脆弱性検出率を比較。

2. A New Approach to Web Application Security: Utilizing GPT Language Models for Source Code Inspection (2023/8)
Angularアプリケーションのロジックバグ(CWE-653)の検出にGPTを使用。

3. When GPT Meets Program Analysis: Towards Intelligent Detection of Smart Contract Logic Vulnerabilities in GPTScan (2023/8)
Smart Contractのロジックバグ検出(のうち分類)にGPTを使用。

4. Can Large Language Models Find And Fix Vulnerable Software? (2023/8)
GPTに脆弱性の発見と修正をさせる。

プロフェッショナルサービス事業部
寺田健