セキュリティキャンプ全国大会2017に参加しました


はじめに

セキュリティキャンプ全国大会2017の選択コースに参加したので、感想を書きます。 技術的な内容ではないので、ご留意ください。 セキュリティキャンプ応募用紙はこちら

notablog.hatenablog.com

キャンプ参加前

キャンプ参加が決定すると、7月中旬から事前学習が始まります。事前学習の有無・量・難易度は講義によって様々で、私が受講した講義では以下のような内容でした。


カーネルエクスプロイト入門 - Linuxカーネル解析の基礎 - - るくすの日記 ~ Out_Of_Range ~

securitycamp2017B2 - Tech Info

Amazon CAPTCHA

セキュリティ・キャンプ全国大会2015でのマルウエア分析講義(2015-09-10)

https://www.ipa.go.jp/security/vuln/documents/fuzzing-guide.pdf

https://www.ipa.go.jp/security/vuln/documents/fuzzing-tool.pdf


キャンプの専門講義は事前課題を行なっている前提で進んでいくので、それらの課題をしっかり理解していないと、当日辛くなると思います(経験談)。

1日目

今年のセキュリティキャンプの会場は府中でした。会場に着くと名刺交換タイムが始まっており、私も多くの方と名刺交換をしていただきました。その後、昼食があり、開会式、セキュリティ基礎、特別講演、チューター紹介、夕食という内容が続きました。特別講演では、チューターさんに起こしてもらう事案が発生し、昼夜逆転を猛省するなどしました。最後のグループワークは、4つのテーマから1つを選択し、最終日にグループで議論した成果を発表するという内容で、私たちのグループは「2020年の東京オリンピックセキュリティキャンプ卒業生が活躍するために自分たちは何をするか?」というテーマに決まりました。正直どのテーマも難しいです。

2日目

2日目から専門講義が始まりました。

D1 Linuxカーネルを理解して学ぶ脆弱性入門

入門編と書いてありますが、カーネルに対するエクスプロイトなので難しくないはずありませんでした(個人の感想です)。内容は以下の3つで、講義と演習がセットになっていました。

  • Slabの基礎
  • デマンドページングとCopy-on-Write
  • Slabを利用した特権昇格と対策

私は1つ目の演習で死んでいたので、演習の内容について書けません orz

B2 組込みLinuxクロス開発スタートアップ

事前学習のWebページの内容を実演していく講義でした。gccbashが使える環境が当たり前になっていたので、ソースコードの状態からビルドしていくのは勉強になりました。あと、ビルドには時間がかかりますね〜

B3 PF_PACKETで仮想IP環境を自作してパケットの理解を深めよう

事前に配布された仮想IP環境のソースコードの実行と解説が行われました。 この講義を受講しなければ、ルータや仮想IP環境の実装について考えることもしなかったと思うので、良いきっかけとなりました。


講義終了後は眠かったため、すぐに就寝しました。

3日目

講義前の時間に、グループワークのテーマについて講師の方や見学している企業の方にヒアリングさせていただいた内容を、グループで議論するなどしました。

D4 マルウェア×機械学習

機械学習には興味があったため、楽しみにしていた講義です。講義の前半では、機械学習についての解説と他の参加者とのディスカッションがあり、後半では、Pythonのコードを使用し実際に機械学習を行い、学習の精度を上げる特徴量について検討しました。

D5 The Anatomy of Malware

静的解析についての講義です。具体的には、IDAを使ってアセンブリコードをひたすら読むという内容です。私はアセンブリコードを読む際、1行1行の意味をおって苦労することが多かったですが、そのような状態にならない知見が得られました。静的解析がんばるぞいという気持ちになります。


3日目は専門講義終了後、BoF、企業プレゼンテーション、グループワークが行われました。BoFは何者なんだと思っていましたが、特定のテーマに対して意見を交わす場のことでした。企業プレゼンテーションでは、エヌ・ティ・ティ・データ先端技術株式会社の方の話を聞き、インシデントレスポンスの業務内容について知ることができました。

4日目

B6 AVRマイコンで作るBadUSB工作・改

キーボードの入力操作を自動化するUSBを作る講義です。私は、PowerShellを使って何かしようと考えましたが、志半ばで講義が終了しました。講義の時間が短く感じるのがセキュキャンの特徴だと思います。

A7 ファジング実習

ファジングツールPeachとamerican fuzzy lop(AFL)のハンズオン形式の実習を行う講義です。今後CTFに挑戦しようと思っていたので、AFLの情報は興味深かったです。


専門講義終了後、企業プレゼンテーション、グループワークが行われました。企業プレゼンテーションでは、富士通株式会社の方の話を聞き、コンサル業務や企業の内情について知ることができました。

5日目

最終日はグループワーク発表がありました。私たちのグループはパワーポイント力をもつ方がスライドを作成してくれて、発表にこぎつけました。本当に、ありがとうございます。私は、終始技術的な意見が出せずグループに貢献できなかったので、ネットワークできるマンになりたいという感情しかないです。

おわりに

5日間と短い期間でしたが、得られたものは想像以上でした。来年もセキュリティキャンプ全国大会は開催されると思いますが、興味がある22歳以下の方はぜひ応募してみてください。充実した5日間が過ごせると思います。

セキュリティキャンプ全国大会2017応募用紙

はじめに

セキュリティキャンプ全国大会2017に参加することになりました。応募用紙を晒している人が多かったので便乗します。来年の応募者の方の参考になれば幸いです。

以下、注意事項:

  • 提出した応募用紙をそのまま掲載するため、誤字脱字があるかもしれません。
  • 完全に課題を理解できなかったため、技術的に未熟な箇所が多くあると思います。
  • 共通問題1は、大学の課題について書いたため、省略させてください。

共通問題

共-2 (1).
あなたが経験した中で印象に残っている技術的な壁はなんでしょうか?

私は、C言語のポインタを理解することに技術的な壁を感じました。C言語を学び始めたとき、C言語の入門書で紹介されている使い方は理解できたのですが、**(int **)p のように少し複雑になると意味を取り違えることがありました。

共-2 (2).
また、その壁を乗り越えるためにとった解決策を具体的に教えてください。

当時の私は、まずインターネットでポインタを理解するための解決策を検索しました。その結果、ポインタに関する情報が多すぎるほど見つかりました。これほど供給があれば、有用な情報が見つかる可能性が高いと思いました。次に、それらの解決策の中で重複している内容を調べたところ、メモリの状態をイメージしそれを図示するとポインタについて理解しやすくなるという内容がありました。実際に、変数名、変数のアドレス、変数の値という3つの情報を表す行とアドレスを表す列を図にしてまとめてみました。その時、ポインタは変数の値にアドレスという数値を持つ変数でしかないと気づきました。そして、間接演算子 * はポインタ変数の値であるアドレスの場所に格納されている値を表し、アドレス演算子 & は、ポインタ変数とポインタでない変数どちらに対しても、表の変数のアドレス欄に書かれている値を表すことがわかりました。その結果、 **(int **)p は以下の図のようになり意味が理解できました。図の具体的な数字は当時の私がイメージしやすくするために書いたものです。

変数名は書いていないですが、2番目の行が *p、3番目の行が **p です。

変数名    |変数のアドレス |変数の値

——————————————————————————

p       |8000    |8004(アドレス)

       |8004    |8008(アドレス)

       |8008    |5(int 型の値)

共-2 (3).
その壁を今経験しているであろう初心者にアドバイスをするとしたら、あなたはどんなアドバイスをしますか?

私は、**(int **)p を始め、「int 型へのポインタへのポインタでキャストした変数 p に2回間接演算子を適用したもの」と考えました。間違っていないですが、少しわかりにくい表現です。私は、初心者にメモリをイメージできる図を書いて見るべきだとアドバイスします。また、図は出来るだけわかりやすく書く方がいいと思うので、実際に変数の具体的なアドレスや値を書いて見るとよいともアドバイスします。この方法をとると、なぜ配列に値を代入できないのかといった配列とポインタの違いも理解しやすくなる副作用があると思います。

共-3 (1).
あなたが今年のセキュリティ・キャンプで受講したいと思っている講義は何ですか?(複数可)そこで、どのようなことを学びたいですか?なぜそれを学びたいのですか?

私はセキュリティキャンプで、カーネルに関する講義を中心に受講したいと考えています。セキュリティキャンプの選択課題を考えている時にカーネルについて理解することはセキュリティについて理解することと大きく相関があると思ったからです。以下に、どのようなことを学びたいかとなぜ学びたいかを書きます。

D1 Linux カーネルを理解して学ぶ脆弱性入門

私は、この講義からカーネル特有の脆弱性の基本について学びたいです。私自身の力量を考慮すると、カーネルのセキュリティの分野では常識のような知識であっても知らないことが多々あると思います。セキュリティキャンプ前に少しでもそのような知識をカバーしようと考えていますが、この講義を通して講師の方が考える基本とはどのようなものなのか知り、今後に生かしたいと考えています。

D2-3 カーネルエクスプロイトによるシステム権限奪取

私は、この講義からカーネルエクスプロイトをどのように行うのかを学びたいです。私は現在CTFのpwnについて学び始め、カーネルエクスプロイトに興味があります。概要にスマートフォンカーネルエクスプロイトの話が書いてあったため、その手法を学びたいです。

A4 Androidマルウェアなアプリを機械学習で検知しよう!

私は、この講義から機械学習がどのようにマルウェアに生かされているのかを学びたいです。機械学習の有用性は以前から知っていましたが、セキュリティキャンプの選択問題を考える中で、さらに機械学習について知りたいと思いました。概要を読むと、マルウェアか否かを機械学習を用いて判断すると書いてあったため、実際にどのように実装するのかを学びたいです。

D5 The Anatomy of Malware

私は、この講義からリバースエンジニアリングに必要な静的解析について学びたいです。私は、大学2年のときに MIPS というアセンブリ言語に触れました。そのとき、アセンブリ言語を読むのは困難ですが、一方で計算機がどのように応用プログラムを解釈しているのか考えるのは楽しいと感じました。マルウェアの解析では、静的解析は欠かせないもので、私も静的解析を試みたことがあります。しかし、読むのに時間がかかり、読み解けなかった部分もありました。この講義で講師の方がどのように逆アセンブルコードを読もうとするのかに注目したいです。

D6 LSM から見た Linux カーネルのセキュリティ

私は、この講義から Linuxカーネルモジュールの開発について学びたいです。この講義は難易度が高いように感じたため少し躊躇しましたが、実際に手を動かしてカーネルについて理解しようとする経験は得難いものであると考えました。知識不足は間違いありませんが、この講義は事前学習があり、私は大学生で多くの時間があることを考慮するとなんとかなります。

B7 組込みリアルタイムOSとloTシステム演習

私は、この講義から組込みシステムの動作の仕組みについて学びたいです。この講義をきっかけに組込みシステムの学習を始めたいと考えています。セキュリティキャンプ後も勉強を継続できると概要にあり、私に適した講義だと思いました。

共-3 (2).
あなたがセキュリティ・キャンプでやりたいことは何ですか?身につけたいものは何ですか?(複数可)自由に答えてください。

セキュリティキャンプでやりたいこと】

私がセキュリティキャンプでやりたいことは、意欲的に新しい分野にチャレンジすることです。私自身に足りないものは、技術力はもちろんですが、何よりも意欲的な姿勢だと最近感じています。話が逸れますが、私がセキュリティキャンプを知ったのは今年の5月です。その時期にこのまま大学の課題をこなすだけでいいのかと考え、勉強会について調べている時に見つけました。セキュリティキャンプのホームページの開催目的を見て興味を持ち、講義内容を見て今まで見たことがないような講義が並んでおり、絶対参加したいと思いました。そして、応募方法を見て課題があることを知りました。選択課題を最初に見たときの感想は、正直なところ「何もわからない。」でした。心が折れかけましたが、諦めきれず課題を行うことに決めました。課題はどれもわからなかったため、前から順番にやろうと思いました。選択問題3はあまりにも難しくて断念したため、私は選択問題1、2、4を行いました。残りの日数があまりなく新しいことも学ぶ必要があるため、大変でしたが、同時に意欲的に学ぶことは面白いとも感じました。私は、セキュリティキャンプの課題から意欲的に学ぶことの楽しさの一端を教えてもらいました。私は、セキュリティキャンプでこのような経験をさらに体験したいです。

セキュリティキャンプで身につけたいもの】

私がセキュリティキャンプで身につけたいものは、私が共通問題3(1)で回答した講義の内容についての知識・技術はもちろんとして、講師の方が持っている熱意です。私は、セキュリティについて多くを知りません。セキュリティキャンプまでの日数は多いとは言えないので、その知識不足を埋めることは難しいと思います。しかし、分野を絞って人より多くの時間を事前学習に割けば講師の方が想定するレベルに到達できると考えています。講師の方の熱意を身につけるには、講師の方の話に食らいついていける知識の土台が必要であると考えるため、私がセキュリティキャンプに参加できるのなら上記のような方針でセキュリティキャンプに臨みます。講師の方がその分野に対してどのように考え、何を楽しいと思っているのかを学ぶことができれば、セキュリティキャンプ後もその経験を生かしていけると思います。

そして、私が身につけたいものは、講師の方の熱意だけではありません。セキュリティキャンプには、私より年下の私より高い技術と意欲・熱意を持った人が参加すると思います。その人たちと交流する機会もあると思います。私は、そのような交流で少しでも自分にはないものを身につけたいと考えています。

選択問題

選-A-1.
添付ファイルに記録された通信を検知しました。この通信が意図するものは何か、攻撃であると判断する場合は何の脆弱性を狙っているか。また、通信フローに欠けている箇所があるがどのような内容が想定されるか、考えられるだけ全て回答してください。なお、通信内容を検証した結果があれば評価に加えます。

【結論】

・この通信が意図するものは何か?

クライアント(192.168.74.1)がサーバ(192.168.74.130)に対して http の通信を要求し、その後クライアントがサーバに対してSSH で遠隔操作を行おうとしている。

・攻撃であると判断する場合は何の脆弱性を狙っているか?

任意のコマンドを実行される脆弱性

・通信フローにかけている箇所があるがどのような内容が想定されるか?

コネクションの切断に関する通信が欠けている。具体的には、クライアントがコネクション切断要求(FIN)をサーバに送り、サーバがFINに対する確認応答(ACK)とコネクション切断要求(FIN)を送り、クライアントがFINに対する確認応答(FIN)を送るという過程が欠けている。また、http 通信に対する応答が欠けている。

・通信内容を検証した結果

以下のアドレスに検証結果の画像を添付する。

(省略します、すいません。)

【思考過程】

 私は、まず添付されたファイルの解析方法をインターネットで調べた。その結果、wireshark というソフトフェアが見つかった。このソフトウェアの使い方を適宜インターネットで調べながら解析した。その結果、この通信はクライアントがサーバに http の通信を要求していることがわかった。また、wireshark によって、通信フローに欠落があることもわかった。コネクションの確立を行い、通信を行うところまでは正常に動作しているが、http の要求に対する応答は存在せず、コネクションの切断のプロセスも欠けている。そして、クライアントがサーバに対して、SSH というリモートマシンと通信するためのプロトコルを利用して通信を要求していることもわかった。

 次に、WiresharkTCPストリームという機能を使って orders.xhtml という、通信で要求されたファイルの内容を確認した。私は、以前Webページを作るために HTML と CSS について調べたことがあるため、Content-Type が明らかに普通ではないとわかった。そこで、Content-Type の内容を調べることにした。インターネットで検索すると、この記述は OGNL 式というもので、 Struts2 という Java アプリケーションで使用されているものであることがわかった[1]。さらに、Struts2.5.10 には脆弱性が存在し、このOGNL 式が任意コマンドを実行される脆弱性を持っていることもわかった[2]。

OGNL式の中から任意コードの部分を探すと「cat /etc/passwd」というLinux のコマンドを見つけた。passwd ファイルは、ユーザがログインする際に必要な情報が記述されており、このファイルがないとLinux にログインできなくなるようなので、重要なファイルであると言える。ただ、現在はセキュリティを強化するためにpasswd ファイルのパスワードを暗号化したものは「/etc/shadow」に存在し、上記のコマンドが実行されても攻撃にはならない[3]。

この通信内容を検証するために、struts2.5.10 の環境を構築した[4]。検証には、RESTClient を使用した。その結果、コマンドが実行されていることが確認できた。

【参考にしたWebページ】

http://s2container.seasar.org/2.4/ja/ognl.html
https://www.ipa.go.jp/security/announce/struts2_list.html
http://www.wakhok.ac.jp/biblion/1997/sysadmin/node18.html
http://io.cyberdefense.jp/entry/2016/06/22/Dockerを使って、Apache_Struts2の脆弱性S2-037のやられ環境を手軽に作

選-A-2.
機械学習の弱点は何だと思いますか?

【結論】

機械学習の弱点として、以下の2点が考えられる。

機械学習に必要な訓練データの数が膨大であるため、十分な訓練データを得られない状況に陥りやすい点。

機械学習で使用する訓練データの正確さを保証できない状況に陥りやすい点。

【思考過程】

 私は、まず機械学習という言葉をWikipediaで検索した。Wikipediaは、機械学習とは、「人工知能における研究課題の1つで、人間が行なっている学習能力と同様の機能をコンピュータで実現しようとする技術・手法のことである。」であると説明していた。このことから、私は、機械学習には様々な手法が存在する可能性を考えた。そこで、現在の主な機械学習について調べた。その結果、機械学習には、教師あり学習と教師なし学習があることを知り、前者の主な手法として、決定木の学習、パーセプトロンニューラルネットワークディープラーニング、後者の主な手法として、クラスタ分析、主成分分析、のような手法があった。この時私は、機械学習のカバーする領域はあまりにも広く、弱点も個々の手法により異なる可能性があると考え、この選択問題の解答時間の限界を考慮して、1つの手法の弱点を探すことに勤めようと考えた。そこで、私は現在注目されているディープラーニングについて理解を深め弱点を探そうとした。

 私は、ディープラーニングを理解するために、「ゼロから作る Deep Learningpython で学ぶディープラーニングの理論と実装」という本を参考にした。この書籍から私は、ディープラーニングニューラルネットワークをベースにして発展した技術であると知った。この時、私はニューラルネットワークに何らかの弱点があれば、その弱点はニューラルネットワークをベースとするディープラーニングにも影響を与えると考えた。そこで、私はニューラルネットワークの弱点を探そうとした。

 ニューラルネットワークの理論の理解がなければ、弱点を見つけることはできないと考え、上記の書籍の該当ページを熟読した。次の2つの段落で、ニューラルネットワークに関して理解できたことを示す。

 ニューラルネットワークとは、入力層、中間層、出力層からなり、各層に役割があることが分かった。まず、入力層とは、ニューラルネットワークを使用するユーザが用意するデータを持つ。このデータ及び重みの積とバイアスの総和が中間層に送られる。重みとは、入力信号の重要度をコントロールするパラメータであり、バイアスとは、出力信号の結果をコントロールするパラメータである。次に、中間層とは、活性化関数により処理を行う層である。活性化関数とは、入力信号の総和を出力信号に変換する関数である。中間層は複数存在することが可能で、各層で同様の処理を行う。最後に、出力層とは、中間層の出力信号に適切な処理を加える層である。一般的に、データがどのクラスに属するかを判断する分類問題では、ソフトマックス関数、入力データから数値の予測を行う回帰問題では、恒等関数を使用する。

 上記の処理で使用する最適な重みを決める作業が、ニューラルネットワークの学習である。この学習は、データから自動的に行うことができる。この特徴により、パラメータの数を膨大にすることを可能とする。データによって、人を介在させず学習を行うため、データがニューラルネットワークの学習では重要である。また、データは訓練データとテストデータに分けられる。なぜなら、訓練データに存在しないデータに対しても正しく動作するかをテストデータによって確認し、その結果を評価することが重要であるからである。

 書籍から私は、上記のようなことを学んだ。そして、改めてニューラルネットワークの弱点を探そうとした。そして、私が目をつけた部分は、ニューラルネットワークの学習では必ずデータが重要な役割を持っている点である。すなわち、訓練データに不備があった場合である。そこで、私は以下の2つの場合を推測した。

 1つ目の場合は、訓練データの数が十分でない場合である。インターネットで検索したところ、ディープラーニングでは万、億単位の訓練データを使用しているものがあるようで、この量の訓練データを用意するのは容易ではないと考えられる。また、Google のような大量のデータを収集することが可能な企業がディープラーニングに強いのはこのことと関係があるのではないかとも考えられる。

 2つ目の場合は、訓練データが正確でない場合である。インターネットで情報を収集したところ、興味深い記事[1]を見つけた。この記事によると、「グーグル・フォト」がゴリラのタグを黒人の方に付けてしまったようだ。このタグ付けミスがどのように発生したのか詳しくはわからないが、私は、黒人の方をゴリラと表現するデータが訓練データとして使用された場合、データが重要な役割を持つディープラーニングの学習では黒人の方とゴリラと学習してしまうのは自然な学習であると考える。このことから、訓練データが正確でない場合、誤った情報や悪意を持った情報をディープラーニングは学習することがわかる。

 これらのディープラーニングの弱点は、訓練データを使用するすべての機械学習に言えるのではないかと考える。

【参考にしたWebページ】

http://jp.wsj.com/articles/SB10468926462754674708104581082773456994848

選-A-4.
C言語のprintf()関数またはUNIXのfork()というシステムコールについて、これらはどのようなものですか?数値や文字列を表示する・プロセスを作るというだけでなく、深掘りして考え、疑問を持ち、手を動かして調べてわかったことを教えてください。

【結論】

C言語のprintf() 関数

この関数は、第一引数である書式指定文字列とそれ以外の複数の引数を持ち、書式指定文字列を標準出力に出力する可変引数関数である。関数の引数はスタックによって非呼び出し側に渡すため、書式指定文字列の中にある%から始まる変換指定子の数が第二引数以降の引数の数より多ければ、標準出力に余分な変換指定子の分だけ何らかの数値が出力される。仮に書式指定文字列が直接入力できるなら、入力の仕方によってはメモリ中のデータを閲覧することができるため、問題であると考える。

UNIX の fork() というシステムコール

このシステムコールは、現在のプロセスを複製するシステムコールである。このシステムコールは、Ubuntu で調べたところ、回数に限界があり、その回数以上はプロセスを作れない。メモリの資源は有限であり、この結果は当然だが、プロセスを無限に作り続けるようなコードを記述すると問題が発生すると考える。また、fork によって作られた子プロセスは管理者権限を引き継ぐため、この特徴を意識してプログラムしないと問題が発生すると考える。

【思考過程】

C言語のprintf() 関数

大学の課題で printf 関数を作ったため、 printf 関数がどのようなものかは知っていた。そこで、printf 関数のバグを探すつもりで自分が作ったプログラムを読んでみた。そのプログラムでは、書式指定文字列の中に変換指定子があれば、第二引数以降の引数から対応する引数の値を得て、その値を出力していた。もちろん自分が作った printf 関数とC言語の printf 関数は違うが、変換指定子の数がどのような影響をもたらすのかに興味が湧いた。そこで、以下のような簡単なC言語プログラムを作った。

/* printf_ex1.c */

#include <stdio.h>

int main(void)
{
  int x = 1;

  printf("%x %x\n",x);

  return 0;
}

実行すると以下のようになった。

./printf_ex1
1 c200dd98

第二引数以降の引数は1つなので、2つ目の値は存在しない引数にアクセスしようとして、そのアドレスに格納されていた値が出力されたと考えられる。また、以下のようにfgets 関数のような文字列を入力できる関数を使用してみる。

/* printf_ex2.c */

#include <stdio.h>

int main(void)
{
  char ss[256];

  fgets(ss, 256, stdin);

  printf(ss);

  return 0;
}

その結果、表示する値の数を任意に変えることができる。

./printf_ex2
%x %x %x %x
b5201c fb594790 78252078 b5201c

printf 関数は、書式指定文字列を標準出力に出力する関数であるため、メモリ中の値に影響を与えることはできないが、出力された値を分析する手法があるのなら、fgets 関数のような文字列を入力できる関数から入力された文字列を、printf 関数の書式指定文字列に使用するのは良くないと考える。

UNIX の fork() というシステムコール

 Man page of Fork というWebページ[1]によると、forkには引数に void を取り、呼び出し元プロセスを複製して新しいプロセスを生成する。そして、戻り値は、プロセスの生成に失敗した場合に親プロセスに−1が返され、子プロセスは生成されない。一方で、プロセスの生成に成功した場合は、親プロセスに子プロセスのプロセスIDが返され、子プロセスに0が返される。私は、forkについてあまり理解していなかったため上記の内容を確認するために以下の簡単なC言語のプログラムを書いた。

/* fork_ex1.c */

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{

  pid_t pid, ret;

  ret = fork();

  if(ret < 0) {
    printf("fork() error.\n");

    return -1;
  }

  pid = getpid();

  printf("return form: fork() is %d.\n", ret);
  printf("pid is %d.\n", pid);

  return 0;
}

実行すると以下のようになり上記の内容を確認できた。

./fork_ex1
return form: fork() is 17172.
pid is 17171.
return form: fork() is 0.
pid is 17172.

しかし、これ以上 fork に深掘りして考えることが難しく悩んだ。その結果、エラーを起こしてみようと考えた。エラーが起きる状況には fork についての情報があるかもしれないと思ったからである。私は、EAGAIN というエラーを起こす方法を考えた。このエラーは、親プロセスのページテーブルのコピーと子プロセスのタスク構造に、生成に必要なメモリを fork が割り当てることができない場合に発生すると、Man page of Fork に書かれていた。そこで、fork を無限に行うプログラムを書けば、いずれエラーが発生するだろうと考えた。私は以下のようなC言語のプログラムを書いて実行した。

/* fork_ex2.c */

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
  int i;
  pid_t pid;

  for(i = 0 ; pid >= 0 ; ++i) {
    pid = fork();
  }

  return 0;
}

どのように実行されるのか見たかったため、strace コマンドを用いた。

clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f7e988979d0) = 17190

clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f7e988979d0) = 17191

・・・

(上記のように fork が繰り返される。)

・・・

clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f7e988979d0) = 25585

clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f7e988979d0) = -1 EAGAIN (Resource temporarily unavailable)

exit_group(0)                           = ?

+++ exited with 0 +++

その結果、エラーの発生が上記のように確認できた。上記のプログラムのループ部分を無限ループにするとプロセスが生成できなるため、この点は問題であると考える。

さらに悩んだ結果、管理者権限を持ったプロセスの子プロセスが管理者権限持つのかについて疑問に思った。そこで、以下のようなC言語のプログラムを書いた。

/* fork_ex3.c */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(void)
{
  pid_t pid, ret;
  char *update = "apt-get update";

  ret = fork();

  if(ret < 0) {
    printf("fork() error.\n");
    return -1;
  }else if(ret > 0) {
    ;
  }else {
    system(update);
  }

  return 0;
}

このプログラムに管理者権限を与えずに実行すると子プロセスは管理者権限を持たなかった。一方、このプログラムに管理者権限を与えて実行すると子プロセスは管理者権限を持った。このことから、fork を呼び出すプロセスが管理者権限を持つ場合、子プロセスも管理者権限を持つことがわかる。fork を使用する場合、上記の特徴は意識しなければいけないと感じた。

【参考にしたWebページ】

https://linuxjm.osdn.jp/html/LDP_man-pages/man2/fork.2.html

おわりに

セキュリティキャンプを知ったのは、今年のゴールデンウィークのあたりでした。その日から、3週間かけて課題を埋めました。

キャンプまで、残り25日ほどですが、他の参加者の方に少しでも追いつけるよう、事前学習を頑張ろうと思います。

ブログ開設しました

初めまして、 nota です。

 

以前からブログに興味があったので、始めてみました。

 

おそらく更新頻度は低いですが、気長にお付き合いください。

 

よろしくお願いします。