セキュリティキャンプ2017の応募用紙さらし

恥を忍んで恥さらし
 
セキュリティキャンプ2017が終わり,さてブログに書かねばと思いながらもインターンが始まり,気付けば10日が経っていた.
10日目になってようやくブログの管理画面を開いたものの,応募用紙の記事を書き忘れたことに気付いた.
そういうわけで,応募用紙さらしをします.
 
今回 私は初応募で初参加.
ギリギリまで書かずに直前になって書き,締め切り2分前に提出した.
それほど高い技術力を持っているわけでもなく熱い情熱があるわけではないのだけれど受かった.ありがたい.
 
応募用紙は全文コピペします.編集が面倒だから.
私の稚拙な応募用紙を見て「ああ,こんな奴でも大丈夫なんだな」と思って気軽に応募する人が増えることを祈ります.

 
 
共通問題
共-1(1).
あなたが今まで作ってきたものにはどのようなものがありますか?
いくつでもいいので、ありったけ自慢してください。
[LED Cube 4x4x4]
LED CubeとはLEDを立体的に並べたものです.4x4x4は一辺に使用するLEDの数を表します.
電子工作の入門用の作品として作られることがあり,綺麗で作りやすいため作りました.
作成したLED CubeはRGB LEDを使用したため,64(=4x4x4)個のLEDをそれぞれ24ビットカラーで表現できます.
プログラムにより,様々な綺麗な光らせ方をすることができます.
ケースは東急ハンズで売っていたアクリルのケースを利用して作成しました.
電源は小型のモバイルバッテリーを使用しており,ワイヤレスで使用することができます.
[LED Cube 3x3x3(未完成)]
前述のLED Cubeは数年前に作成しましたが,現在3x3x3のLED Cubeを作成中です.
新しくLED Cubeを作成する理由としては,4x4x4は少し大きすぎたことや大学のレーザー工作機が使えるようになったことがあります.
新しいLED Cubeでは,古いものの機能に加えサイズの小型化,外装を換装できる予定です.
例えば,木材(MDF)で障子をイメージした外装にすることも,アクリルに彫刻を入れて光の表現を細かく変えることもできます.
[足用キーボード]
PIC18F14K50を用いたUSBキーボードの一種です.
ダイソーのタッチライトを改造して大きなスイッチとして使い,押されたときにキー入力を行います.
キー入力はプログラムにより変更可能で,様々なキーを入力することができます.
また,スイッチが大きいので足で押すことも簡単です.
[自動キー入力ディバイス]
PIC18F14K50を用いたUSBキーボードの一種で,USBメモリによく似た形をしています.
DIPスイッチが5つとタクトスイッチが1つ付いており,DIPスイッチでキー入力のパターン,タクトスイッチでキー入力の送信ができます.
また,DIPスイッチで接続時にキー入力を行うかどうかも選択できます.
[ハードウェアキーロガー対策装置]
卒業研究で作成した装置です.
ハードウェアキーロガーとはキーボードの電気信号を取得し,キー入力を取得する装置です.
USBメモリと変換コネクタを合わせたような形をしており,片方のポートをキーボード,もう片方をPCに接続することでキー入力の盗聴を行います.
現在のUSBキーボードは暗号化を行なっていないため容易に盗聴ができる上,電気信号なのでソフトウェアでは検知不可能なので,対策を研究しました.
具体的な対策としてはキーボード内でのキー入力の暗号化を検討しました.
実際にハードウェア暗号エンジンを持つPIC24FJ128GB202で暗号化(AES256ビット)を行いました.
また,復号化は専用のディバイスで行う方法とPC上で行う方法の2つを検討しました.
復号化を専用のディバイスで行う場合はPIC24FJ128GB202で復号化を行い,一般的なUSBキーボードとしてキー入力を行います.
なお,この復号化装置は暗号化装置に対して対称的な構造となります.
一方,PCで復号化を行う場合は暗号化したキー入力をCOMポートで受け取り,専用のサービスがデータの復号化とキー入力を行います.
[学科展]
苫小牧工業高等専門学校の学校祭では,各学科の出し物として学科展というものが開催されます.
私は学科展のVirtualBowling班として参加し,プログラムやモデルの作成を行いました.
VirtualBowlingとは,ボウリングのレーンの一部を仮想化したものです.
物理的なレーンとボールを用意し,投げたボールをレーン上部に設置されたカメラで撮影します.
カメラはボールのベクトルを算出し,Unityで作成されたプログラムに渡します.
Unityのプログラムでは受け取ったベクトルを用いて仮想空間上でボールがピンに向かう様子を描画し,それをスクリーンに出力します.
[ETロボコン]
部活動ではETロボコンというコンテストに参加しました.
ETロボコンとはロボットレースの一種で,同一ハードウェア上でソフトウェアとUMLを競い合います.
私は主にプログラムを作成して参加していました.
[自分のサイト]
VPSを契約し,自分のドメインを取ってサイトとブログを運用しています.
自分のサイトは勉強も兼ねて1から作成し,ブログはWordpressを使用しています.
 
共-1(2).
それをどのように作りましたか?
ソフトウェアの場合には、どんな言語で作ったのか、どんなライブラリを使ったのかなども教えてください。追加したい機能や改善の案があれば、それも教えてください。
[LED Cube 4x4x4]
主な要素はコントローラ,LEDドライバ,PowerMOSFET,電源の4つです.
コントローラとしてArduino Nanoを使用しました.
また,LEDに対して出力ピンが足りないため16チャネルLEDドライバであるTLC5940を3つ(RGB)使用しました.
Arduino Nanoの出力ポートでは電流を十分に流せないため,IRF9540(Power MOSFET)を使用しました.
電源には小型のモバイルバッテリーを使用しました.
最初に構想としてLEDの数と外装のサイズを決めました.
LED Cubeでは,一辺のLED数をnとすると必要なLEDの数はn^3となります.
配線なども大変になるため,最初はnを4として作成することとしました.
外装はLEDによく映えるアクリルで作りたいと考えていましたが,加工機もなかったので,東急ハンズで売っていた外径が10[cm]x10[cm]x10[cm]のアクリルケースを上下2つに使うこととしました.
LED Cubeはスズメッキ線とはんだを使い,LEDを立体的に配置します.
最初に各層を作成し,次に各層を積み重ねていきます.
回路の作成はサイトを参考に行い,10センチ四方のユニバーサル基板に収まるように配線を考えました.
プログラムはサイトのものを参考にパターンを改良し,自分好みのパターンを作成しました.
追加したい機能としてはセンサとの連動や新しいパターンの追加があります.
しかしケースの大きさが決まっているため,これらは3x3x3のLED Cubeで実現したいと考えています.
[LED Cube 3x3x3(未完成)]
材料は4x4x4を作成したときの余りを使っています.
回路の設計はEagleを用いて行いました.
現在はLEDを立体的に組み立てる作業中です.
[足用キーボード]
ダイソーでタッチライトを買ってきます.これを+ドライバーで開け,中身のスイッチをタクトスイッチに変えます.
次に基板を作成します.PIC18F14K50とICソケットと抵抗,コンデンサ,セラロック発振子,USBコネクタだけで作成することができます.
なお,電源はUSBのバスパワーです.
基板の作成が終われば本来電池が入るスペースに基板を入れ,タクトスイッチと基板とをはんだで接続します.
最後にC言語でプログラムを書きます.Microchip社が提供するMicrochip Application Libraryのサンプルからhid_keyboardを参考に作成します.
元々のサンプルはスイッチを押すたびにa,b,c,…と入力されるものです.
そのためカウンタを削除し常に同じキーを入力するように変更することで機能を実現することができます.
プログラムを書き込み,USBケーブルを接続することで,完成です.
改良したい点としては,ワイヤレス化があります.
この装置はPCから足まで線が伸びるため,少し邪魔です.
そのため,ESP-WROOM-02などで無線化ができないか考えています.
[自動キー入力ディバイス]
前述の足用キーボードと構造的にはよく似ています.
ただしこちらはUSBコネクタをオスにして直接PCに接続でき,スイッチを追加してパターンなどを変更できるようにしました.
こちらもユニバーサル基板を使い,ケースはアクリルの端材をレーザーカッターで加工して作成しました.
サイズはUSBメモリより少し大きい程度になりました.
改良したい点としては小型化があります.
USBメモリより少し大きいので,ディバイスによっては引っかかって隣のポートが使えません.
具体的な案としては生基板を加工することや,チップ抵抗や小さいパッケージのICを用いることが考えられます.
[ハードウェアキーロガー対策装置]
USBのホスト機能を持つPICとディバイス機能を持つPICの2つを使い,ホスト機能を持つPICがキーボードのキー入力を取得します.
取得したキー入力は暗号化された後ディバイス機能を持つPICに転送され,ディバイス機能を持つPICは復号化を行なった後キーボードとしてキー入力をPCに伝えます.
なお,上記の説明は暗号化と復号化をハードウェアで行なった場合ですが,PCで復号化を行う場合はディバイス機能を持つPICで復号化を行わず仮想COMポートとしてデータを送信し,PC上のソフトウェアで復号化とキー入力を行いました.
PCの復号化ソフトウェアはC#でサービスとして記述し,PCに登録することでWindowsの起動時から復号化ができるようにしました.
作成方法としては,ホストとディバイスそれぞれをテストして使い方を覚え,その後2つを組み合わせる形で実現しました.
回路設計にはKiCADを用い,基板は生基板をPカッターで彫って作成しました(エッチング環境も基板加工機もなかったため).
追加したい機能としては,復号化をPCのデバイスドライバ上で行いたいです.
卒業研究時には時間が足りず作成することはできませんでしたが,デバイスドライバで復号化とキー入力ができるのであればユーザからは普通の接続と何ら変化なく使えるはずです.
具体的にはUSBのHIDクラスのフィルタドライバを使用することが最適なのではないかと考えています.
[学科展]
私が入った当初はODEという物演算エンジンを使用していました.
しかしゲームエンジンを使用したほうが良いと考えUnityに移行することを提案しました.
その提案は通り,ODEからUnityにプログラムを移植しました.
また,Mayaでボウリング場のモデルを作成してシステムの見た目をより良いものにしました.
センサとの連携やサーバへのスコアのアップロードなど,改良したい点はまだまだありますが,すでに後輩に引き継いだので生暖かく見守っていきます.
[ETロボコン]
私がETロボコンに参加したときはちょうどOSを変えたタイミングで,先輩の残した遺産も使えない状態からのスタートでした.
ライブラリのサンプルを読み,様々なサイトや書籍を参考にPID制御やまいまい式などの制御方法を実装しました.
[自分のサイト]
4年ほど前からVPSとドメインを契約して自分のサイトとブログを運用しています.
VPSはさくらのVPS,ドメインはお名前.comで契約しています.
Webサーバにはapacheを使用し,サイトはhtml5,css,javascriptで作成しました.
また,ブログはWordpressを使用しています.
共-1(3).
開発記のブログ、スライドなどの資料があれば、それも教えてください。コンテストなどに出品したことがあれば、それも教えてください。
[ブログ]
http://tamatoyaku.com/b
共-1(4).
Twitterアカウント、Github、ブログをお持ちでしたら、アカウント名、URL等を記載してください。
[Twitter]
@pome_11

[Github]
pome1618
https://github.com/pome1618
共-2(1).
あなたが経験した中で印象に残っている技術的な壁はなんでしょうか?
(例えば、C言語プログラムを複数ファイルに分割する方法など)
[C言語の環境構築]
技術的な壁かどうかは分かりませんが,私にとって最も大きかった壁は環境構築でした.
C言語を始めた当時は高専の入学直前で,焦っていました.
きっと周りはみんなプログラミングができるのであろうと思い,焦りながらC言語の勉強をはじめました.
しかし,始めようとした矢先環境構築という大きな壁が現れました.
意味の分からない英語を吐き出す黒い画面に対し,私は長い時間をかけて格闘していました….
ちなみに,私の買った本には環境構築についての記述がありませんでした.
[ハードウェアキーロガーの作り方]
卒業研究でハードウェアキーロガーの対策を行うため,実際にハードウェアキーロガーを作成しました.
しかし,PCとキーボード間のUSB通信を盗聴するにはどうすればよいのか全く分かりませんでした.
単純に電圧をとってプロトコルを解析する場合,それはもはやUSB1.1プロトコルアナライザを自作することになります.
PICを使おうにもサンプリング周波数が足りるのか,そもそもライブラリも全くなしの状態で作れるのかという問題がありました.
共-2(2).
また、その壁を乗り越えるためにとった解決法を具体的に教えてください。
(例えば、知人に勧められた「○○」という書籍を読んだなど)
[C言語の環境構築]
環境構築が終わったのは入学の1週間前で,環境はメモ帳でソースを書きコマンドプロンプトからbccでコンパイル&実行するというものでした.
いろいろなサイトを読み,自分であらゆるパターンを試した結果環境構築ができました.
今思えばもう少しまともな本を選定し,友達や先輩や先生など相談できる人を見つけるべきであったと思います.
C言語だけでなく電子工作を始めるときも同じで,一人で悩んで使いもしないパーツを大量に買うより,誰か話せる人を見つけるべきだったと思います.
[ハードウェアキーロガーの作り方]
解決策は,間にホスト機能を持つPICとディバイス機能を持つPICの2つをはさみこむことにしました.
通信の内容が一部変更されるというデメリットもありますが,比較的簡単に作成できる点や見かけ上分からない点から採用しました.
共-2(3).
その壁を今経験しているであろう初心者にアドバイスをするとしたら、あなたはどんなアドバイスをしますか?
[C言語の環境構築]
何かを始めるとき,人ほど頼りになるものはありません.
友達でも先輩でも後輩でも先生でも,誰でも良いので近くに相談できる人がいないか探してみましょう.
物理的に近くにいなくても,SNSで探してみることもできると思います.
また,本も自分にあったものを買いましょう.
入門する前は「何を知らないか知らない状態」なので,何を知らないかと何を知りたいかをある程度理解してから本屋に行き,大量の目次を読んで選定しましょう.
[ハードウェアキーロガーの作り方]
一番正しい方法が常に最適であるかどうかは分かりません.
要件を満たす範囲で他に方法がないか,ありとあらゆる側面から考察しましょう.
あと,初心者さんには電子工作やPICの良さを伝えて沼に引きずり込みたいです.
やはり自分が作ったモノがあると達成感があります(Web系などを否定するつもりはありません).
コンソール上のプログラムと違い,意味の分からない挙動をすることもありますが,乗り越えればそれすら楽しくなってきます.
世界で1つのディバイスを作れる,そんな楽しい趣味に勧誘したいです.
共-3(1).
あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)
そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?
私はハードウェア寄りのセキュリティに興味があり,今回のセキュリティキャンプではハードウェア関係の講義を中心に受講したいと考えています.
もちろんLinuxカーネルやWeb関係など,他の講義もとても興味深いのですが,時間割の都合上受けられないものが多く残念です.
1.DOS攻撃用FPGAを作ろう
私は高専の卒業研究でPICを用いたハードウェアキーロガーの対策に関して研究を行いました.
この講義もFPGAでイーサネットのパケットを扱うため,少し似たような部分があると思い,参加したいと感じました.
また,来年の大学の卒業研究では楕円曲線暗号をFPGA上に構築する予定なので,FPGAをセキュリティという観点から見たときにどのような使い方があるのか知りたいです.
2.Embedded System Reverse Engineering 101
私は高専の卒業研究でUSBキーボードのハードウェアキーロガーについての対策を行いました.
大学の卒業研究ではFPGAを用いて楕円曲線暗号の実装を行う予定です.
しかし,実際のハードウェアに対する攻撃やその対処法などはわかりません.
この講義では攻撃とその対策を理解し,より強固なシステムを作りたいと考えています.
3.信じて送り出した家庭用ルータがNetBSDにドハマリしてloginプロンプトを返してくるようになるわけがない
今や家庭用ルータは一家に一台あるもので,私達の最も身近にある機器の1つであると思います.
そのルータを自在に操ることはとても楽しいものだと感じます.
学びたいこととしては,NetBSDでなにができるかが一番ですが,法律関連も教えていただけるとうれしいです.
というのも,ネット上の記事では「技適の付いた機器のファームウェアを変えることは違法だ」という主張を見かけるからです.
他にも「ファームウェアを改造して高出力にした電波は電波法違反になる」というものもあります.
一方で「ファームウェアを改造しても電波を飛ばさなければ違法ではない」という主張もあります.
どれも一定の信憑性があるように見えますが,信頼できるソースは見つけることができませんでした.
そのため,法という観点から見てこれらはどうなのか教えていただけると幸いです.
4.AVRマイコンで作るBadUSB工作・改
私が最も楽しみにしている講義です.
この講義は改になる前から気になっていました.
私も卒業研究でキーボードを扱っていましたので,この講義ではAVRマイコンや電気信号のエミュレートなどについて学びたいと思います.
ただ,そもそもBadUSBとはUSBディバイスのファームウェア書き換えの脆弱性であり,作成するディバイスはBadUSBと見かけが同じだけの「自動キー入力装置」ではないかと疑問に思います.
共-3(2).
あなたがセキュリティ・キャンプでやりたいことは何ですか? 身につけたいものは何ですか?(複数可)
自由に答えてください。
[セキュリティについての知識を得ること]
当然これが一番の目標となります.
私は今までIT系の勉強を情報処理技術者試験を目標に行なってきました.
国家資格ですし,何よりも明確なゴールテープがあることがやる気につながっていました.
しかし2年前の秋に情報セキュリティスペシャリストに合格して以来,次に何をすれば良いのか分からなくなりました.
一方でTwitterや掲示板,ニュースサイトを見ているとセキュリティに関するいろいろな情報が入ってきます.
それらは大抵高度な技術が使われており,私は「何を知らないのか知らない」のだと気付きました.
私はセキュリティキャンプで自分が何を知らないのかを知りたいです.
また,それぞれの科目で専門家は日々どのようにして知識と技能を磨いているのか話を聞き,自分も専門家になれないか考えてみたいです.
[友達]
私は友達がとても大事だと考えています.
新しいモノを作るときに友達と話すととても楽しいですし,いろいろな発見もあります.
つまづいたときは互いに助け合い,競い合うことでモチベーションも上がります.
そのため,同じような趣味趣向を持つ友達を探してみたいです.
私の身の回りには電子工作を趣味とする人は数が少なく,特にPICを扱う人には学校で会ったことがありません.
セキュリティキャンプの,特にハードウェア関係の科目であれば同じ趣味の誰かがいるのではないかと期待しています.
選択問題
選択問題セレクト. 参加を希望するコース(集中コースはトラックまで)を選択してください。
書類審査に合格した場合、この設問で回答したコース(集中コースはトラックまで)に必ずご参加いただきます。 [必須]
選-選択コースA-セレクト.
右の中から3つを選択して回答してください
選-A-1 選-A-2 選-A-3 選-A-4
選-A-5 選-A-6 選-A-7 選-A-8
選-A-3.
自分がソフトウェア・ハードウェアを実装した部分について、自分とは意見が異なる実装を提案してきた人が現れた場合、あなたはどうしますか。
– 自分の実装のほうが優れていると思った場合どうしますか?
– 自分の実装のほうが優れていないと思った場合どうしますか?
– 相手の母国語が自分と違うために正確に議論が進まない場合はどうしますか?
– 相手がものすごく強硬で石頭でこちらのいうことを何も聞かず実装を勝手に修正してしまった場合どうしますか?
1.自分の実装のほうが優れていると思った場合
最初に双方が自分の優れていると感じる部分を互いに主張し,共通認識を持ちます.
次に相手の主張に関して自分がどのように感じたかを正直に話し合います.
相手が後から実装を提案したということはなにか理由があるはずなので,そこを明確にします.
そして互いに優れていると感じる部分を取り込めるなら取り込み,より良い策はないか考えます.
ただし,互いに譲歩できない場合は上の者(先生,先輩,上司など)を交えて再度主張を繰り返し,上の者に判断を仰ぎます.
また,修正は他の部分に影響を及ぼすことや時間がかかることも予想されるので,それらを踏まえた上で判断を行います.
2.自分の実装のほうが優れていないと思った場合
優れていると思った場合とほぼ同じことを行います.
ただし,優れていないと感じても修正するかどうかは影響範囲や時間によるので,慎重に判断を行います.
3.相手の母国語が自分と違うために正確に議論が進まない場合
言語だけでなく図やコードを用いた説明ができないか考えます.
特にこの場合はUMLなどを用いると分かりやすいのではないかと思います.
また,翻訳ができないかどうか考えます.
Google翻訳や近くに通訳ができる人がいないかどうか,あるいは通訳を雇うという手もあります.
4.相手がものすごく強硬で石頭でこちらのいうことを何も聞かず実装を勝手に修正してしまった場合
私ならそのようなことをされると怒ります.勝手なことをするなと怒りに燃えるでしょう.
つまり,正常な判断力を失うことは容易に想像がつきます.
そのため,問題の一歩外にいる上の者(先生,先輩,上司など)に判断を仰ぎます.
おそらく当事者同士の仲は険悪になっているでしょうから,一人ずつ上の者と面談を行い実装についての主張を行います.
このとき,すでに完成品が2通りあるので上の者はより優れた方を選んで正式な実装とすれば良いかと思います.
選-A-4.
C言語のprintf()関数またはUNIXのfork()というシステムコールについて、これらはどのようなものですか? 数値や文字列を表示する・プロセスを作るというだけではなく、深堀りして考え、疑問を持ち、手を動かして調べてわかったことを教えてください。
1.printf関数について
printf関数は文字や数値などを標準出力に表示します.
フォーマット文字列と呼ばれる文字列で表示形式を指定し,引数を渡すことで変数の表示を行うことができます.
printf関数の引数は可変長引数を使用しており,引数の数を必要なだけ渡すことができます.
今回は可変長引数について調べてみます.
最初にprintf関数などのソースコードを入手します.
今回はhttp://ftp.gnu.org/gnu/glibc/からglibc-2.25.tar.xzをダウンロード,展開し読み進めます.
printf関数のソースコードは展開先のstdio-commonの中に,printf.cとして格納されています.
内容としては引数をそのままvprintfに渡しているだけのようですが,可変長引数を扱うにはstdarg.hとその中のva_startとva_endが必要なようです.
va_start(v,l)はva_list型の変数を初期化し,vが対象となる変数,lが可変長引数の前の引数を表します.
va_arg(v,l)は指定された型の引数を順次取り出します.vは対象となる可変長引数,lは型で,取り出したものを返り値として返します.
va_end(v)は終了処理を行います.
stdarg.hはgccに付属しているので,gcc-7.1.0.tar.gzをダウンロード,展開しました.
gccに付属しているということは処理系依存ということを表します.
stdarg.hによると,va_start(v,l)は__builtin_va_start(v,l)として定義されていることがわかりました.また,va_argとva_endも同様に定義されていました.
調べてみるとva_startとva_endはbuiltins.cで,va_argはRID_VA_ARGとしてc-parser.cに定義されていました.
中では構文解析を行い可変長引数に対応しているようでしたが,複雑すぎて追いきれませんでした.
2.fork関数について
fork関数は子プロセスを生成します.
子プロセスは親プロセスのコピーとして生成されます.
2つの区別はfork関数の返り値で行い,子プロセスなら0,親プロセスであれば子プロセスのPIDが返ります.
fork関数で生成したプロセスは,正しく終了処理を行わないと子プロセスがゾンビとして残り,無駄にリソースを消費します.
ゾンビプロセスは正確には2種類,ゾンビプロセスと孤児プロセスがあります.
ゾンビプロセスは子プロセスが終了したのに親プロセスがwait関数を実行しないときに生まれます.
孤児プロセスは子プロセスより先に親プロセスが終了したときに生まれます.
今回は,ゾンビプロセスと孤児プロセスの対策について考えました.
2.1.ゾンビプロセスの対策
原因は子プロセスが終了したにも関わらず親プロセスがwait関数を呼ばないことなので,fork関数で子プロセスが生成されてから一定時間の経過で強制終了するようにします.
具体的にはfork関数とwait関数のラッパーを書き,fork関数が実行されるたびに子プロセスのPIDと生成時刻を保存します.
タイマーを使って一定時間が経過したことを確認したら,PIDを指定してkillコマンドで強制終了します.
ただし,killコマンドで終了するだけだとゾンビ化するので,waitpid関数でゾンビ化を解除します.
実装は以下のようになりました.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/time.h>
#include <unistd.h>
#include <signal.h>
#define TIMEOUT 15
#define PROC_NUM 64
typedef struct{
int pid;
time_t t;
} proc_s;
proc_s proc[PROC_NUM]={0};
void update(){
int i;
int status;
for(i=0;i<PROC_NUM;i++){
if(proc[i].pid!=0&&proc[i].t+TIMEOUT<=time(NULL)){
printf(“killkill”);
kill(proc[i].pid,9);
waitpid(proc[i].pid,&status,0);
proc[i].pid=0;
proc[i].t=0;
}
}
}
int myfork(){
int pid=fork();
int i;
if(pid>0){
i=-1;
while(proc[++i].pid!=0&&i<PROC_NUM);
if(i<PROC_NUM){
proc[i].pid=pid;
proc[i].t=time(NULL);
printf(“%d:%d\n”,pid,time(NULL));
}
}
return pid;
}
int mywait(){
pid_t pid=wait();
int i;
for(i=0;i<PROC_NUM;i++){
if(proc[i].pid==pid){
proc[i].pid=0;
proc[i].t=0;
}
}
return pid;
}
int main ()
{
int pid;
int i;
for(i=0;i<10;i++){
pid=myfork();
if(pid==0){
break;
}
sleep(1);
}
if(pid>0){
struct itimerval timer;
signal(SIGALRM,update);
memset(&timer,0,sizeof(timer));
timer.it_value.tv_sec=1;
timer.it_value.tv_usec=0;
for(i=0;i<30;i++){
setitimer(ITIMER_REAL,&timer,NULL);
pause();
}
}else{
sleep(100);
}
return 0;
}
2.2.孤児プロセスの対策
孤児プロセスが生まれた場合,そのゾンビプロセスの親はinitプロセスとなり,子プロセスは動き続けます.
大抵の場合親が先に死ぬことは異常事態だと思うので,子プロセスから親プロセスの生存確認を行い,親がいない場合は終了する方法はないか考えました.
親の生存確認にはgetppid関数が使えます.
getppid関数で親のPIDを取得し,PIDが1ならばinitプロセスに引き取られたことがわかります.
また,終了処理には専用の関数を用意し,atexit関数で登録することで安全に終了できるようにします.
実装は以下のようになりました.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void exit_func(){
if(getppid()==1){
printf(“親が死んだ場合の安全な終了処理\n”);
}
}
int main ()
{
pid_t child_pid;
child_pid = fork ();
if (child_pid > 0) {
sleep (10);
}else {
atexit(exit_func);
while(1){
if(getppid()!=1){
printf(“\r親は生きてる”);
}else{
break;
}
}
printf(“\n親が死んだ\n”);
exit (0);
}
return 0;
}
選-A-5.
以下のプログラムはLinuxカーネル3.8〜4.4に存在する脆弱性を悪用しています。このプログラムの実行により発生する不具合を説明してください。また、この脆弱性をさらに悪用することでroot権限昇格を行うエクスプロイトを記述し、自分が試した動作環境や工夫点等を説明してください。加えて、このような攻撃を緩和する対策手法をなるべく多く挙げ、それらを説明してください。
完全には分からなくても構いませんので、理解できたところまでの情報や試行の過程、感じた事等について自分の言葉で記述してください。また参考にしたサイトや文献があれば、それらの情報源を明記してください。
#include <stddef.h>
#include <stdio.h>
#include <sys/types.h>
#include <keyutils.h>
int main(int argc, const char *argv[])
{
int i = 0;
key_serial_t serial;
serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, “leaked-keyring”);
if (serial < 0) {
perror(“keyctl”);
return -1;
}
if (keyctl(KEYCTL_SETPERM, serial, KEY_POS_ALL | KEY_USR_ALL) < 0) {
perror(“keyctl”);
return -1;
}
for (i = 0; i < 100; i++) {
serial = keyctl(KEYCTL_JOIN_SESSION_KEYRING, “leaked-keyring”);
if (serial < 0) {
perror(“keyctl”);
return -1;
}
}
return 0;
}
私はこのコードが何をするものなのか全く分かりませんでした.
まず最初にkeyctl関数が何者かを調べました.
調べた結果,鍵を保存するものだということがわかりました.
次に,上記のプログラムが脆弱性を悪用しているということから,JVN iPediaでkeyctlをキーワードとして検索を行いました.
また,root権限昇格に関わるもののようなので関係がありそうなものを見ていくと以下のページが見つかりました.
Linux Kernel の security/keys/process_keys.c の join_session_keyring 関数における権限を取得される脆弱性
http://jvndb.jvn.jp/ja/contents/2016/JVNDB-2016-001537.html
上記のページから共通脆弱性識別子がCVE-2016-0728だということまでわかりました.
次に「CVE-2016-0728」で検索を行いましたが,対策についての情報ばかりで詳しい情報は分かりませんでした.
そこで視点を変え,ソースコードの検索を行うこととしました.
上記のプログラムで特徴的なのは”leaked-keyring”という文字列だと考え,Githubで検索を行いました.
その結果leak.cというファイル名が出てきました.
再度Google検索で「cve-2016-0728 leak.c」と検索すると以下のページが見つかりました.
ANALYSIS AND EXPLOITATION OF A LINUX KERNEL VULNERABILITY (CVE-2016-0728)
http://perception-point.io/2016/01/14/analysis-and-exploitation-of-a-linux-kernel-vulnerability-cve-2016-0728/
大量の英語に面食らいながらもGoogle翻訳の力を借りて読み進めていくと,ある研究チームが発見したゼロデイな脆弱性であることが分かりました.
ひとまず原理はさておきthe full exploitと書かれたリンクにあるソースコードを仮想マシン上でコンパイルし,動かしてみました.
cve_2016_0728.c
https://gist.github.com/PerceptionPointTeam/18b1e86d1c0f8531ff8f
実行した結果,シェルは表示されましたがwhoamiではrootと表示されませんでした.
使い方が悪いのではないかと思い,上記のページのコメントを読みましたが,よく分かりませんでした.
そこでYoutubeに動画が上がっていないかと思い検索すると以下の動画が見つかりました.
CVE-2016-0728 Linux Kernel Exploit

どうやらgdbを使いながらleak.cを動かすことで権限を取得していたようでしたが,よく分かりませんでした.
そのため,研究チームのページを見て原理を理解することにしました.
そもそもの発端となったバグは,プロセスがsession keyringを同じもので置き換えようとしたとき参照リークが起きることのようです.
例えば,問題文のプログラムを実行するとleaked-keyringは1つのプロセスであるにも関わらず参照数は100となります.