GoでAESアルゴリズムを使った実装をする (と暗号歴史を一部紹介)
実はCISSPを受験しようと思ってて、最近その勉強をしている。(結構長く勉強してるはずなんだけど、業務が忙しくて実質時間が書けられてなくて進捗だめであああああああああああああああああああああああああああああああ)。まあ、こういうこと書いてるからなのかもしれないんだけど、しかたがない(しかたなくない)
CISSP自体に暗号はドメインとして含まれていないのだが、ドメインをまたがる問題として出題されているので、結城先生の「暗号技術入門」を読書している。
せっかくなので、そのアウトプットとしてGoでAES・CBCモードのSecret Keyを実装してみることにした。 余談だが、共通鍵方式はSecret Key, Common Key, Shared Key...など色々あるようだが、CISSP(の問題)ではSecret Keyに統一されているので、本投稿もそれに合わせる。
尚、@ken5scalは暗号技術の専門家ではないので、間違いはあると思う。何か見つけた場合は是非連絡を頂きたい。
AESアルゴリズム
さて、AESアルゴリズムの実装に入る前に、その説明だけしておこう。 これは別名Rijndaelアルゴリズムともいい、DESが機械の性能向上により物理的敗北を喫したのをきっかけに、NIST(米国立標準技術研究所)によりFIPS(連邦情報処理標準規格)と認定された。これにより保管データ暗号化時の推奨アルゴリズムとして、デファクトとなる。@ken5scalの使うMBPのディスク暗号化機能「FileVault」もAESアルゴリズムを利用している。
面白いのは、このアルゴリズムがNISTによって秘密に作成・運用されているのではなく、DESに変わるSecret Keyアルゴリズムを選定するコンペで採用されたものであり、公開されていることだ。wikiにも結城先生本にも記載されてるし、NISTもがっつり公開している。*1
実は米国は、AESが選定されるまで暗号に関しては非常にクローズな立場をとっていた。1992年の時点では暗号化ソフト(含むアルゴリズム)をAuxillary(補助的?)軍需品と指定し、輸出規制の対象としていたぐらいである。具体的にはアルゴリズム・鍵長(40bit以上)で規制をかけてた*2。当然、通信の暗号化などプライバシーの強化に大活躍したが、それと同時に犯罪者によっても悪用される。従って、法執行当局のシギント的捜査が難航するからコントロールしようとするのは当然のことだろう。包丁をコンビニに置くと...みたいな話に感じそうだが、当時の背景(第2次世界対戦後と冷戦後)を考慮すると、「せやな」と思えなくもない。当局による取り組みの1例としては、1994年に「鍵預託」(key escrow)というシステムを組み込んだ「預託暗号標準(EES)」があるだろう。ホワイトハウスはこれを承認し、電話通信・コンピューター通信に個人の秘密鍵を埋め、同時に鍵のコピーを連邦当局に保存する方向に持っていこうとしてた*3。日本のマイナンバーの前身みたいなものだろうか。
でも、結局のところ、規制を米国ほどかけたくないヨーロッパや市場からの反応により、管轄が1996年に国務省(Department of State)から商務省(Department of Commerce)に移管され、それとともに軍需品の対象ではなくなった。そして、その後色々あって(知らない)、2000年のAES選定につながる。ただし、現在でも輸出規制が完全になくなったかというとそうではなく、Secrete Keyアルゴリズムは鍵長64bit超のもの且つマスマーケットになっていないものが輸出規制対象となっている。*4
なお、米国に暗号の輸入出規制があると書いたが、別に米国に限ったものではない。武器輸出を規制するワッセナー・アレンジメントに調印した国や、独自の基準をもつ中国など、様々な規制があって面白いので、別途調べてみたい。*5
AESアルゴリズムとは(リトライ)
AESルゴリズムはブロック暗号アルゴリズムで、固定長(128bit)のブロックを、128/192/256bitの鍵で暗号化するもの。この暗号化は複数回行われ、各回(ラウンド)ではSubBytes -> ShiftRows -> MixColumns -> AddRoundKeyするもの。それぞれの解説は図が絡むのでしないw 結城先生の「暗号技術入門」を買ってください。実装といっても、そんな難しくはなく、すでにGoでは標準パッケージ「crypto/aes」で容易されているので、それを使ってやればおk。
// AESによる暗号化 func EncryptByBlockSecretKey(key []byte, plainText string) ([]byte, error) { c, err := aes.NewCipher(key); if err != nil { // NewCipherで暗号オブジェクトを作る。 return nil, err } cipherText := make([]byte, aes.BlockSize) c.Encrypt(cipherText, []byte(plainText)) // Input/Output must be 16bits large return cipherText, nil } func DecryptByBlockSecretKey(key []byte, cipherText []byte) string { c, err := aes.NewCipher(key); if err != nil { // NewCipherで暗号オブジェクトを作る。 fmt.Println(err.Error()) return "" } plainText := make([]byte, aes.BlockSize) c.Decrypt(plainText, cipherText) return string(plainText) } func main() { plainText := "1234123412341234" key := []byte("1234123412341234123412341234123") // あえてAES規格ではない鍵長を使う fmt.Println(EncryptByBlockSecretKey(key, plainText) # crypto/aes: invalid key size 31 <- 暗号オブジェクト作成時にKeySizeErrorが発生 key = []byte("1234123412341234") // AES-128 fmt.Println(EncryptByBlockSecretKey(key, "12341234123412345")) // Longer than 16 byte # [196 235 186 96 98 151 252 89 132 220 117 226 229 247 4 48] <nil> <- 1ブロック以上は処理対象にならない fmt.Println(EncryptByBlockSecretKey(key, "123412341234123")) // Shorter than 16 byte # panic: crypto/aes: input not full block cipherText,_ := EncryptByBlockSecretKey(key, plainText) fmt.Println(cipherText) # [196 235 186 96 98 151 252 89 132 220 117 226 229 247 4 48] plainText = DecryptByBlockSecretKey(key, cipherText) fmt.Println(plainText) # 1234123412341234 <- 復号できた。 }
しかし、これでは固定長の平文しか処理できない。固定長以上の平文を暗号化したい場合、16byteのブロック長にきって暗号化を繰り返せばいいのだが、これをブロック暗号のモードを実装しなければいけない。これを次回は実装してみる。
追記( @bata_24さん ありがとうございます)_
復号化 vs 復号 前職のパイセンにもよく言われていたが、本来"復号化”は国語的におかしいみたいだ。なぜなら「復号」は暗号文を元に戻すという意味の動詞だからそうだ。暗号は名詞以外の定義はない。よって、暗号化の対義語は復号になる。ただし、結城本は復号化だが...って思ってたら、字面の対称性を重視しているらしい*6。ま、職場でもよく復号化...と言われてるが、とりあえず本投稿は復号に寄せてる。怒られそうだけど、正直どっちでもいい
Rijndael vs AES Rijndaelは厳密には128, 160, 192, 224, and 256bitsの鍵長をサポートしている。また、128, 160, 192, 224, and 256bitsのブロックサイズもサポートしている。AESは鍵長を128,192 and 256bits、ブロックサイズを128bitsに絞った点で異なる。
- 作者: サイモンシン,Simon Singh,青木薫
- 出版社/メーカー: 新潮社
- 発売日: 2007/06/28
- メディア: 文庫
- 購入: 30人 クリック: 216回
- この商品を含むブログ (233件) を見る
- 作者: サイモンシン,Simon Singh,青木薫
- 出版社/メーカー: 新潮社
- 発売日: 2007/06/28
- メディア: 文庫
- 購入: 23人 クリック: 70回
- この商品を含むブログ (161件) を見る
- 作者: 結城浩
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2015/08/26
- メディア: 大型本
- この商品を含むブログ (14件) を見る
Github + CircleCI + DockerでGCEを動かす - ファイル暗号化 on Github編
- 先に断っておくと本編はあまり、DockerとGCE関係ない。
- 見られたくないファイルをGithubにあげたい場合、Github上では暗号化してCircleCIのビルドのタイミングで複合化したいニーズがあると思う。
- 例えば 証明書をNGINXイメージに埋め込むとか。
- なのでGithubにprするときにはAESアルゴリズムで暗号化すればどうカナ〜と思った。
- せっかくなのでGoで
- 単純で。こうやればおk。パッケージがあるのが素晴らしい。っていうか自力ではじめて暗号化するコード書いたな。
- CBCモード使わないと、出力も入力も16byte固定なんすね。普段意識しないから新鮮だった。やはり自分で実装するのはいい。必ず発見があって面白い <- 一番いいたかったこと
func main() { // key := []byte("1234123412341234123412341234123") // Not AES-128, 256, 512(bit) c, err:= aes.NewCipher(key); if err != nil { fmt.Println(err.Error()) // Erro発動 } key = []byte("1234123412341234") // AES-128 c, err = aes.NewCipher(key); if err != nil { fmt.Println(err.Error()) } cipherText := make([]byte, aes.BlockSize) plainText := []byte("1234123412341234") c.Encrypt(cipherText, plainText) // Input/Output must be 16bits large fmt.Println(cipherText) c.Decrypt(plainText, cipherText) fmt.Println(string(plainText)) }
追記
- よく考えてらIAMのkey management 使えばいいわ
Github + CircleCI + DockerでGCEを動かす - デプロイ編
- 今日はデプロイするところまで.
- 基本的にはKubernetesのチュートリアルを参考にしつつ作った.
- 説明はしないスタイルで。
Kubernetes関連用語
- 説明はしないと言ったな。アレは嘘だ。
- Kubernetesはコンテナ化されたアプリをClusterにデプロイしたり、配布をスケジュール化したりする。今風に言うとオーケストレーションツール?
- Cluster -> 複数のリソース群が1つのユニットとして接続されたもの。2種類のリソースから構成される
- Pod: 正直捉えづらかった。現在進行系で捉えきれてない。デプロイのタイミングで作られるコンテナの集合体 + 共通リソースの集合体。Logical Host. PodはNodeの上で走る。
- Services: Podsの集合。Podsの外部ネットワークへ公開、ロードバランス、サービスディスカバリを出来るようにする
- Labels: そのまんま。PodやServiceにラベリングできる。環境、バージョン、サービスタイプ(front, backend,db)などの情報を負荷できる
Gophishのデプロイ
> kubectl run gophish-deploy --image=asia.gcr.io/${PROJCET_ID}/gophish:latest --port=3333 # gophishアプリをClusterにデプロイ(ポート3333ではしらせる)。デプロイノードは1つ > export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}') # Podの名前を取得 > kubectl expose deployment/gophish-deploy --type="NodePort" --port 3333 # 今回は1インスタンスしか立てない > export NODE_PORT=$(kubectl get services/gophish-deploy - ate='{{(index .spec.ports 0).nodePort}}') # Portを取得
さて、ここまでやれば外部公開されているはずなのだが、curl "$NODE_IP":"$NODE_PORT"してもtime outする。nmapしたところfilterとの結果が帰ってきたのでFirewall系とあたりをつける。
Firewallの設定
なのでコンピュートサービス > ネットワーキング > ファイアウォールルールで見ると、任意のIPから対象のノード:$NODE_PORTへのアクセス許可設定がされていなかったので、以下で設定
> gcloud compute --project "gophish-150317" firewall-rules create "external2gophish" --allow tcp:NODE_PORT --network "default" --source-ranges "0.0.0.0/0" --target-tags "gke-gophish-cluster-bc6565eb-node"
これで、curl "$NODE_IP":"$NODE_PORT"したら無事アクセスできた。でも、毎回NODE_PORT指定するのダルいなぁ...と思ったので、kubectl exposeでオプションがないか探したが見つからなかった(targetPortオプションは使ってみたが駄目だった)。ただ、yamlファイルでの方法なら指定が可能らしいのでyamlファイルを作成。
http://kubernetes.io/docs/user-guide/services/#type-nodeport
apiVersion: v1 kind: Service metadata: labels: name: gophish name: gophish spec: ports: - port: 3333 #targetPort: 3333 protocol: TCP nodePort: 30333 selector: name: gophish type: NodePort
一旦、過去のサービスを消して再設定. 又、今回は指定したポートを指定してFirewallに穴を開ける。無事通る
% kubectl delete svc/gophish % kubectl create -f gophish-service.yaml % gcloud compute --project "gophish-150317" firewall-rules create "external2gophish" --allow tcp:30333 --network "default" --source-ranges "0.0.0.0/0" --target-tags "gke-gophish-cluster-bc6565eb-node" % curl 104.199.208.112:30333 <a href="/login">Found</a>.
ブラウザ側からも大丈夫
NodePortじゃなくてLoadBalancingも試す
yamlを書き換えるだけ
apiVersion: v1 kind: Service metadata: labels: name: gophish name: gophish spec: ports: - port: 3333 targetPort: 3333 <- ★ protocol: TCP selector: name: gophish type: LoadBalancer <- ★
ロードバランサーが作成される過程でFirewallの穴あけもやってくれるらしいので、ロードバランサーに公開IPが付与され次第、アクセスできる。NodePortは手動でやらなきゃいけないからメンドクサイ。
[Kengo@Mac] ~/workspace/docker_gophish % kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE gophish 10.3.249.184 104.155.214.128 3333/TCP 3m kubernetes 10.3.240.1 <none> 443/TCP 4d [Kengo@Mac] ~/workspace/docker_gophish % curl 104.155.214.128:3333 <a href="/login">Found</a>.
スケールアップ
折角ロードバランサー形態にしたので、スケールアップしてみる。おk。
# Before % kubectl get deploy NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE gophish-deployment 1 1 1 1 1h % kubectl scale deployment gophish-deployment --replicas=2 # After NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE gophish-deployment 2 2 2 2 1h
余談 - お金の話
24日の記事を含めて、このコンピュートエンジンを立ち上げたのが約1週間前。それから立ち上げっぱなしで、利用料金はトータルで1102円。為替とかはもろもろ無視すると、ロードバランサー・ストレージもあるものの、90%がCompute Engineにかかった費用と考えられる。内訳は以下の通り。
でも、あれれ?GCEって5node/clusterまで無料じゃなかったっけ?って思ったら、それはCluster管理の価格だった。ノード料金はそのままかかる。個人だと結構いたいかなあ。こまめに管理しないと。
Google Container Engine Pricing and Quotas | Container Engine Documentation | Google Cloud Platform
下記で計算もできる。 cloud.google.com
次は
- CircleCIでデプロイしようと思う。一旦サービスはおとそう。
デバッグ
> kubectl cluster-info # > kubectl get nodes # Cluster内でアプリをホストできるノード > kubectl get deployment > kubectl proxy & # ローカルでいながらClusterのAPIに接続できる -> ブラウザからhttp://localhost:8001/uiで管理コンソールを開ける。便利。 > kubectl get pods # 存在しているpodsをリスト > export POD_NAME=$(kubectl get pods -o go-template --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}') # Podの名前を取得 > curl http://localhost:8001/api/v1/proxy/namespaces/default/pods/$POD_NAME # 接続テスト > kubectl describe pods # podsの情報(構成情報・イベント)を取得 > kubectl logs ${POD_NAME} # 対象Podのログを取得 > % kubectl exec -it $POD_NAME COMMAND #対象Pod上でCommandを実行。docker execみたいなもん。 > kubectl describe svc/gophish-deploy # サービスの情報
参考資料
Kubernetes - kubectl Overview * 安定の本家ドキュメント GKEで半年運用してみた * お金を調べてるうちにみつけた...最初からこれをみつけていたかった...
Github + CircleCI + DockerでGCEを動かす - レジストリ編
- 2017/08/31: コメントでの指摘を受け、一部コマンドを変更
背景:
- 今、(ほぼ)1人チームで継続性が強く必要な仕事をしているので、あらゆる面で運用を楽にしていきたい。なのでコードで楽に管理でき、デプロイまで自動でやってくれて、オフィスアカウント(googleアカウント)との連携もできるGCPに強く興味がある。特にContainer周りやGCEは深くほっていきたいエリア。
- 最終目標はDockerイメージをGCPで動かすところだが、今回はイメージをGithub + CircleCIを用いてレジストリにPushするところまでが目的
- コードはこちらです。
Cloud SDKインストール & セットアップ
https://cloud.google.com/sdk/docs/quickstart-mac-os-x
% tar xvzf google-cloud-sdk-121.0.0-darwin-x86_64.tar.gz % ./google-cloud-sdk/install.sh % gcloud init % gcloud components update kubectl // Instal kubectl
GKE setup
% export PROJECT_ID=gophish-150317 % gcloud config set project ${PROJECT_ID} % gcloud config set compute/zone asia-east1-a % gcloud config set container/cluster gophish-cluster % gcloud container clusters get-credentials gophish-cluster
- Dockerイメージのビルド
% docker build -t asia.gcr.io/${PROJECT_ID}/gophish:v1 .
- ビルドしたイメージをGKEのContainer RegistryにPush
% gcloud docker -- push asia.gcr.io/${PROJECT_ID}/gophish:v1 % gcloud docker -- search asia.gcr.io/${PROJECT_ID}
- 問題なくできていれば下記のようにイメージがタグ付きで表示される
自動ビルドをする
Github + CircleCIの構成で。
事前準備
- Githubにリポジトリを作る。ローカルで作ったファイルをPushしておく
- GithubとCircleCIを連携する。circle.ymlはない状態だがとりあえずビルド一回ぐらい回す
- GCPプロジェクトのサービスアカウントキー(JSON)を取得する
- プロジェクト > API Manager > 認証情報 > 認証情報を作成 > サービスアカウントキー
- 役割は「編集者」の役割 をもっているメンバーだけが可能みたいだ。とりあえずCompute Engine default service accountを使っといた。
- https://cloud.google.com/container-registry/docs/access-control
circle.yml作成
- Githubフローに似た流れのジョブを作る。つまり…
ブランチを切ってMaster向けPRを作成。 ↓ Dockerイメージをビルド + テスト ↓ レビュー ↓ マージ && テスト環境デプロイ ↓ リリースtagをきる on Github ↓ 本番環境デプロイ
真のGithubフローだとprを送った時点でデプロイされる、といったことをどこかで読んだ事が、切り戻しまでの時間を考えるとアグレッシブだな、と思う。切り戻しまでの時間 < Maximum Tolerant Downtimeであればいい、という発想なのだろうか。組織と個人のレベルが高ければ実現できそうだな。
このフローを作るには、Github > Settings > Webhooksのイベントで以下を設定しておけばいい
- Push, Pull request, Deployment, Release
どう動くか
- BranchをきってPRを作った時にはテストまで実行されてデプロイはされない
- MergeするとMasterブランチでのビルドが走る。デプロイまでされる. GCPでみるとlatestタグのついたイメージが更新されていることがわかる
- GithubでReleaseをすると、WebHookしてくれて、やはりデプロイまでしてくれる。ただdeploy.shにリリースタグがある場合の追加処理があり、それによりリリースタグが付与されたDockerイメージがレジストリにpushされる。以下は v1.0.1をリリースした例。こういう形で変更管理を楽にできそう。
- 以上。
その他
- CircleCI内でgcloudをupdateしてるけど、デフォルトで最新化しててくれませんかね…15秒もかかっとんぞ
- Dockerイメージをビルドするのが遅い。これはCircleCIのコンテナ内でビルドしてるので、キャッシュされないから。対策としてはdependenciesで、ジョブ開始時点での最新イメージをGKEからpullしてくること。これをすると30秒くらい早くなる。
- CircleCI 2.0でなんとかするらしい。
- deploy.shって, deploymentのタイプ毎に分けた方がいいのかな〜
DockerイメージをGKEのレジストリにアップロードする
背景:
- 今、(ほぼ)1人チームで継続性が強く必要な仕事をしているので、あらゆる面で運用を楽にしていきたい。なのでコードで楽に管理でき、デプロイまで自動でやってくれて、オフィスアカウント(googleアカウント)との連携もできるGCPに強く興味がある。特にContainer周りやGCEは深くほっていきたいエリア。
- 最終目標はDockerイメージをGCPで動かすところだが、今回はイメージをGithub + CircleCIを用いてアップロードさせるところまで
- コードはこちらです。
Cloud SDKインストール & セットアップ
https://cloud.google.com/sdk/docs/quickstart-mac-os-x
% tar xvzf google-cloud-sdk-121.0.0-darwin-x86_64.tar.gz % ./google-cloud-sdk/install.sh % gcloud init % gcloud components update kubectl // Instal kubectl
GKE setup
- Clusterの作成をGUIで。gcloudかRESTでも作成可能
- gophish-clusterをasia-east1-a上に作った
- コマンド環境の設定
% export PROJECT_ID=gophish-150317 % gcloud config set project ${PROJECT_ID} % gcloud config set compute/zone asia-east1-a % gcloud config set container/cluster gophish-cluster % gcloud container clusters get-credentials gophish-cluster
- Dockerイメージのビルド
% docker build -t asia.gcr.io/${PROJECT_ID}/gophish:v1 .
- ビルドしたイメージをGKEのContainer RegistryにPush
% gcloud docker push asia.gcr.io/${PROJECT_ID}/gophish:v1 % gcloud docker search asia.gcr.io/${PROJECT_ID}
- 問題なくできていれば下記のようにイメージがタグ付きで表示される
自動ビルドをする
Github + CircleCIの構成で。
事前準備
- Githubにリポジトリを作る。ローカルで作ったファイルをPushしておく
- GithubとCircleCIを連携する。circle.ymlはない状態だがとりあえずビルド一回ぐらい回す
- GCPプロジェクトのサービスアカウントキー(JSON)を取得する
- プロジェクト > API Manager > 認証情報 > 認証情報を作成 > サービスアカウントキー
- 役割は「編集者」の役割 をもっているメンバーだけが可能みたいだ。とりあえずCompute Engine default service accountを使っといた。
- https://cloud.google.com/container-registry/docs/access-control
circle.yml作成
- Githubフローに似た流れのジョブを作る。つまり...
ブランチを切ってMaster向けPRを作成。 ↓ Dockerイメージをビルド + テスト ↓ レビュー ↓ マージ && テスト環境デプロイ ↓ リリースtagをきる on Github ↓ 本番環境デプロイ
真のGithubフローだとprを送った時点でデプロイされる、といったことをどこかで読んだ事が、切り戻しまでの時間を考えるとアグレッシブだな、と思う。切り戻しまでの時間 < Maximum Tolerant Downtimeであればいい、という発想なのだろうか。組織と個人のレベルが高ければ実現できそうだな。
このフローを作るには、Github > Settings > Webhooksのイベントで以下を設定しておけばいい
- Push, Pull request, Deployment, Release
どう動くか
- BranchをきってPRを作った時にはテストまで実行されてデプロイはされない
- MergeするとMasterブランチでのビルドが走る。デプロイまでされる. GCPでみるとlatestタグのついたイメージが更新されていることがわかる
- GithubでReleaseをすると、WebHookしてくれて、やはりデプロイまでしてくれる。ただdeploy.shにリリースタグがある場合の追加処理があり、それによりリリースタグが付与されたDockerイメージがレジストリにpushされる。以下は v1.0.1をリリースした例。こういう形で変更管理を楽にできそう。
- 以上。
その他
- CircleCI内でgcloudをupdateしてるけど、デフォルトで最新化しててくれませんかね...15秒もかかっとんぞ
- Dockerイメージをビルドするのが遅い。これはCircleCIのコンテナ内でビルドしてるので、キャッシュされないから。対策としてはdependenciesで、ジョブ開始時点での最新イメージをGKEからpullしてくること。これをすると30秒くらい早くなる。
- CircleCI 2.0でなんとかするらしい。
- deploy.shって, deploymentのタイプ毎に分けた方がいいのかな〜
VagrantとAnsibleを触ってみたのでメモ
構成管理に手を出してみたので、メモ。 AnsibleとVagrantで。 本ドキュメントでは手順とハマリポイントを紹介しますが、手順は他の本やブログでもさんざん上がってるので、最小限にとどめます。
目的
実践的な意味での構成管理、プロビジョニングの勘所を探したい
Ansibleを選んだ理由
最初、Itamae かAnsible で迷ってたが、以下の観点からAnsibleを選択
記述方法
ItamaeじゃなくてAnsibleを選択したのは、rubyに詳しくなく、多少離れてるyaml記述の方が学習コストが少なそうだったから。docker fileもyml記述だし。複雑なことをするとツライっぽいけど、そこまで複雑じゃないからいいかな、とも。ここらへんは感覚値です。
ドキュメント
ドキュメントの総数やSOFの記事数も多かったのがポイント。公式ドキュメントの充実度もAnsibleが上だった。
後、moduleがAnsibleのが充実してたし、Andsible-Galaxyもよさげだった。
とか、色々言ったけど、結局決定打はない。というか決定できるほど知らないので、Ansible暫くやってつまったらitamaeでゴニョゴニョしに行く方針。
構成
Mac + VM on VirtualBox + Vagrant + Ansible
構築
Vagrant構築
作業ディレクトリの作成と移動
mkdir ~/workspace/ansibleDemo cd ~/workspace/ansibleDemo
- Vagrantボックスを取得
% vagrant box add centos6-7 https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box
- Vagrant初期化
vagrant init centos6-7
- Vagrantfile作成(下記を追加)
# vim Vagrantfile実行 config.vm.box = "centos6-7 config.vm.network "private_network", ip: "192.168.33.10"
- VM起動
vagrant up
- Ansibleインストール
brew install ansible
- Inventory登録
echo "[TestServer]" > hosts echo "192.168.33.10" >> hosts
- ssh接続先設定
vagrant ssh-config --host 192.168.33.10 >> ~/.ssh/config
% ansible -i hosts 192.168.33.10 -m ping 192.168.33.10 | SUCCESS => { "changed": false, "ping": "pong" }
- playbook作成
# vim playbook.yml - hosts: TestServer become: yes tasks: - ping:
- playbook実行
% ansible-playbook -i hosts playbook.yml
とりあえず、出来たところはここまで
ハマりポイント
Guest VMにpingが通らない
- ansible経由どころか、hostマシン(Mac)からもできなかった
- vagrantのVagrantFileにprivate_networkを記述すれば、staticにIPを決定出来るのかと思ったが、vagrant upしても接続できない。VM内でifconfigうつも、private_networkに記述したIPは表示されず
- VirtualBoxからみるとVMのネットワークのアダプタ1にhost_onlyのインターフェースがあるはず。
- 仕方ないので /etc/sysconfig/network-scripts/ifcfg-eth1を直接編集して、ネットワーク再起動
BOOTPROTO=none ADDR=192.168.33.10 NETMASK=255.255.255.0 ONBOOT=yes DEVICE=eth1
/etc/init.d/networks restart
- 上記で解決
Vagrant up時にWarning: Authentication failure. Retrying...が出る
- sshの設定を調査
% vagrant ssh-config --host 192.168.33.10 Host 192.168.33.10 HostName 127.0.0.1 User vagrant Port 2222 UserKnownHostsFile /dev/null StrictHostKeyChecking no PasswordAuthentication no IdentityFile /Users/Kengo/workspace/ansibleDemo/.vagrant/machines/default/virtualbox/private_key IdentitiesOnly yes LogLevel FATAL
- IdentifyFile内のprivate_keyにマッチするpublic_keyがゲスト側にいなければいけないので、作る
% ssh-keygen -yf .vagrant/machines/default/virtualbox/private_key > public_key % cat public_key ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCg4qWCq3mPom9TzcAdDoDHt61s7tjsmeHaD0pLePYW0p4+qZCr2u8cLk0gJElB7BQc3c3mMuo5iCsYoxrjXbVHpNNUDmRHNLdSxNVO3Z7qLY7VzyQWwoqyqrCcbN3fG/MV+6cs+8d0dcvHGrEYnR9O6Q81VS4sdBucM0J8jQ2oyzumr8QZdXFEEeQbG9SKOVIFpuPHBiOFV+skc22VfgZNlxANBizFV7uguCxhEoQs74L1XMvC1ae7TjVhnIZbZ1063QyXtPgO25TwFqZUsCltqFxgBA032YKZFAtFXyF5vu0pootG91biS9f43dccp8cFuizgLc5FkUYUhjDtNRLV
- ゲスト側にpublic_keyを登録....けど、すでに存在した。
% vagrant ssh Last login: Sun Aug 7 18:41:24 2016 from 10.0.2.2 [vagrant@localhost ~]$ cat .ssh/authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCg4qWCq3mPom9TzcAdDoDHt61s7tjsmeHaD0pLePYW0p4+qZCr2u8cLk0gJElB7BQc3c3mMuo5iCsYoxrjXbVHpNNUDmRHNLdSxNVO3Z7qLY7VzyQWwoqyqrCcbN3fG/MV+6cs+8d0dcvHGrEYnR9O6Q81VS4sdBucM0J8jQ2oyzumr8QZdXFEEeQbG9SKOVIFpuPHBiOFV+skc22VfgZNlxANBizFV7uguCxhEoQs74L1XMvC1ae7TjVhnIZbZ1063QyXtPgO25TwFqZUsCltqFxgBA032YKZFAtFXyF5vu0pootG91biS9f43dccp8cFuizgLc5FkUYUhjDtNRLV vagrant <- ★あれこれはssh-keygenして作ったものと同じ...
- ぐぐったら.sshの設定がいけなかったらしい
[vagrant@localhost ~]$ chmod 0700 /home/vagrant/.ssh/ [vagrant@localhost ~]$ chmod 0600 /home/vagrant/.ssh/authorized_keys
これでおk
ansibleでpingができない
% ansible -i hosts 192.168.33.10 -m ping 192.168.33.10 | UNREACHABLE! => { "changed": false, "msg": "SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue", "unreachable": true }
vagrant ssh-config --host 192.168.33.10 >> ~/.ssh/config
- これでpingができた
% ansible-playbook -i hosts playbook.yml PLAY *************************************************************************** TASK [setup] ******************************************************************* ok: [192.168.33.10] TASK [ping] ******************************************************************** ok: [192.168.33.10] PLAY RECAP ********************************************************************* 192.168.33.10 : ok=2 changed=0 unreachable=0 failed=0
以上。ヨサそう
JTB不正アクセス & 個人情報流出についてまとめてみた
更新履歴
- (6/15更新)下記にてpiyologが更新されているので、そちらを見つつ足りてない情報を加え、情報を再整理d.hatena.ne.jp
- (6/16更新)6/15午前から6/16 0時までに公表された情報を追加
- (6/16 18:20更新)タイムラインを更新
- (6/17 01:30更新)6/16から6/17 0時までに公表された情報を追加
- (6/20 01:17更新)6/17から6/20 0時までに公表された情報を追加
- (6/27 19:00更新)6/20から6/27 までに公表された情報を追加
イントロ
タイムライン*1*2
- ここではすべて2016年内での出来事とします
日時 | 出来事 | 備考 |
---|---|---|
3/15 | i.JTBの従業員がメール上の添付ファイルを開いたことでパソコンが感染 | 取引先を装ったメール。この時点で感染は認知されず。最終的にサーバー |
3/19 | JTB情報システム(JSS)が |
当該サーバは本来個人情報を含まない。システム監視会社によって検知。継続的な不信通信をブラックリストに登録する作業をおこなっていた。遮断に関する報告はi.JTBからJTBにはなかった*5*63連休 |
3/20 | Webサーバーを社内ネットワークから物理的に切り離し。不審通信は別経路で継続 | 「当該日に不審通信を全遮断することは業務的にも技術的にも可能だった」*7 3連休 |
3/21 | 不正侵入者はデータベースにアクセスしCSVファイルを生成。制御サーバにCSVファイル設置し、その日の内に削除.*8 | | データファイルが作成された制御サーバと不審通信を発したサーバは別*9。3連休 |
3/24 | 内部サーバから外部への不審通信を最後に確認 | |
3/25 | 遮断作業を終了。JSSがJTB IT企画部門に報告 | *10 |
3/XX~3/YY | ネットワーク内の全サーバとパソコンを調査 | 3/19 ~ 3/30? |
4/1 | 不正侵入者が作成・削除したデータファイルの存在を確認。CSIRT立ち上げ。 | |
X/XX~5/13 | 外部セキュリティ専門会社と共同で、ウイルスを駆除・データファイルの復元と不正アクセスの調査・分析・対応を実施 | 調査開始のタイミングの記述はない。復元対象のデータファイルは不正侵入者が作成・削除したデータファイルかと思われる |
5/13 | 復元したデータファイルに個人情報が含まれることを確認。i.JTBよりJTBにエスカレーション*11 。個人情報流出の可能性を認定。事故対策本部を設置。 | |
5/13~X/XX | 直ちにデータを正規化し、 |
*12 |
5/17 | JTB 高橋社長が情報を認知 | |
5/30 | 警察に相談 | |
5/31 | 観光庁に相談 | *14 |
X/XX | 問い合わせ窓口を設置 | |
6/10 | 対象顧客が判明 | *15 |
X/XX~ | 対象のユーザーへメールによる通知を開始 | 1ヶ月以内に連絡するとのこと*16 |
6/14 | 発表 && 調査継続。警察による操作開始 | 不正アクセス禁止法違反や不正指令電磁的記録供用の容疑にて操作中*17 |
6/15 | 個人情報流出の可能性があるユーザーへの注意喚起 *18 | 送信元メールアドレス、添付ファイル、ヒアリング内容に関して通達。観光庁が再発防止策の提出依頼*19 |
6/17 | 国交省、再発防止策を検討する有識者検討会の設置を発表 | *20 |
6/24 | 観光庁への再発防止策の報告期限。該当する顧客への連絡は24日午前までに、ほぼすべて終了 | 「さまざまな企業や団体で個人情報が流出した事案の教訓が生かされておらず、大変遺憾だ」「全体的に遅すぎる」 |
7/1 | 末永安生専務をCISOに任命。社長直下のITセキュリティ専任統括部門を設置 | *21 |
攻撃の概要
当時のJTBの体制
発覚以前
- セキュリティを横断的に見る部門は存在せず *23
5.対策: (中略)ジェイティービー(グループ本社)内にITセキュリティ専任統括部門を設置いたします
- CSIRTも存在せず *24
サイバー攻撃の緊急対応チームも当時は存在しなかった
- 一部ログを取得していなかった*25
- すぐ情報を公開しなかったのは「不安と混乱を招くと考え、特定できた段階で公表する方針を取った」*26
- 対象データを暗号化していなかった。*27
- 実績データベースへアクセス可能な社員は1人だが、そのPCは乗っ取られていない*28
- 実績データベースのデータを使うBI(ビジネスインテリジェンス)ツールは25人の社員がアカウントを持っていたが、今事案との関連性は薄いと見られる*29
発覚後
- 問い合わせ窓口を設置
- スタッフ300名規模*30
- 6/14時点で数千件の問い合わせ
- 警察への相談済み(調査中)
- 7/1までにITセキュリティ専任統括部門を設置
「外部流出について可能性があるという表現にとどめたという。JTBは通信ログの一部を取っていなかった。」とあるので事実がないのではなく事実を確認する術がないというのが正しいかもしれませんね。 https://t.co/fkvewFVs7P
— nobuhiro tsuji (@ntsuji) 2016年6月14日
送信された標的型メール*31*32*33*34*35
- 件名: 航空券控え添付のご連絡
- メアド: ごくごく普通のありがちな日本人の苗字@全日本空輸のドメイン*36
- 署名: 取引先の署名
- 添付ファイル名:
- 添付ファイル種別: PDF。
- 実態はELIRKS(の亜種?)とPluX(の亜種?)に当該PCを感染させる新種マルウェア
- オペレータから返信。エラーメールがかえってくる
- 開封すると航空券のeチケットが表示される
- メールヘッダー: 海外のレンタルサーバー(香港を経由)*39
- 本文内容
- 添付ファイル開封者: オペレータ
- 標的型メールの訓練済み
- JTB全体では定期的に訓練していたようだが、当該オペレータが複数回の訓練を受けていたかは不明
- 標的型メールの訓練済み
被害範囲
- 個人情報悪用の報告もない
流出は確定されていない- 流出に関するログが確認できないため、わからない*42
- 尚、一部ログを取得していなかったとのこと
- 可能性は否定されていない*43
- 知らない宛先から不審なメールマガジンが届いた」といった指摘がおよそ100件よせられた
- 詳細調査中*44
個人情報の項目
以下の一部か全て
- 氏名(漢字、カタカナ、ローマ字)
- 性別
- 生年月日
- メアド
- 住所
- 郵便番号
- 電話番号
- パスポート番号
- パスポート取得日
- 現在で有効なものは
約4300件4359件*45
- 現在で有効なものは
訪日外国人の情報も含む*46
- 以下の情報は含まれない*47
- 予約した旅行の内容
- クレカ情報
対象となるユーザー
JTB関連のサービス
- 以下のサービスでオンライン予約したユーザー679万人
- "ネットで予約後、店舗でご清算のお客様の情報は対象となります。" <- ??
- 予約 && オンライン清算が対象??
期間についての記述はない- 2007/9/28 ~ 2016/3/21*48
別会社
NTTドコモのdトラベルユーザー*49*50
- 対象ユーザー: 2014/2/27~2016/3/21に予約したユーザー
- 対象範囲: 33万人
- 窓口設置済み
- ドコモの吉澤和弘新社長が謝罪と対策の強化を表明
auトラベル by DeNAトラベルを*51
対策
不正アクセス対策
- 特定された外部への不審な通信の遮断
- 感染範囲の特定とウイルスの駆除
- 個人情報へのアクセス制御の強化
グループ全体の対策
被害額試算
不明な点
ウイルス感染からの流れ
- 最初に不審通信を確認してから何をしたのか*52
- 感染したパソコンがどの様な用途で使われたか。
- 踏み台もしくは直接操作されたのか
- 内部パスワードを取得されたのか
- 取得したパスワードで社内ツールを使ったのか
- 取得したパスワードでサーバにログインしたのか
- サーバ上でどうファイル作成・削除の操作する権限を得たか。
サーバ上に普段はないデータをどの様に取得したか。
不審通信はどの様な内容なのか => 不審なパケットデータだったか*57
- 宛先・通信種別は一定なのか
- ファイルを送信するような通信なのか
- 単純にいままでに観測されていない通信だったのか
普段の通信量とどれぐらい違うか(ちがわなそう)
- 何をもってして流出の可能性があると判断したか
- 不正アクセス者が作成・削除したファイルの存在で判断したか
- ファイルを外部に送信するような不審通信があったのか
- ウイルスの解析結果をもって判断したのか
業務推進がミッションの実務担当者に、標的型攻撃につながるメールを開いてしまったことに責任など負わせられない。「そこは訓練していたんです」なんてことは、記者会見で言い訳として言及することですらない。むしろ、その後の攻撃の連鎖への対応に何が欠けていたのかが、スタディには必要。
— riotaro okada (@okdt) 2016年6月14日
インパクト
事後対応
- なぜ情報公開が認知後すぐでなかったか
- CSVデータを復元しても正規化が必要で、それだけではユーザーの特定ができず、余計な混乱をまねきたくなかったから
- パスポート情報漏洩(の可能性)に対するエンドユーザーの対策
- 対策をJTBがしめすのか。外務省がしめすのか。
- 可能性であれば対応不要で終わらせるのか。
その他
- ホームページのニュースリリース配下に「不正アクセスによる個人情報流出の可能性について」がないのはなぜ?
- 公表した日付と警察が捜査に着手した日付が同じ
- 一部のログが取得されてなかッタ理由
- 意図的ではなく様々なWebサイトを運営する中で統一できなかったとみられる*61
その他
- 後でpiyologと答え合わせする。
- (2016/6/15追記) piyologと初期情報の量が異なるので、piyologが取得している情報ソースのリストを作る
- 見せ方に関しては、それをまとめてどう使うかは作成者によって違うので、これはこれでよし
- (2016/6/20追記)2日置いてみたが特にめぼしい新情報がなかった(非営業日だからか?)。とりあえずここまでの振返りをする
振返り
まず最初に
- 今回はJTBがいちはやく整理された公式報告を公表していたので、概要が掴みやすかった。
- 恐らく、こういうタイプのインシデントはレアなのだと思うが、今後のインシデントを気にする(いや、起こらないのがベストなのだが)
情報ソースについて
- Googleでの検索"JTB 情報流出 情報漏洩"
- Feedlyでのニュース登録: Security NEXT, ITmedia, ITpro, Jpcert/CC, ZDNet, @IT, INTERNET Watch
- piyologを見て利用したニュースサイト: 日経、毎日、朝日、産経、時事通信、読売
- 上記のサイトをウォチしてて思ったことは、大手ニュース(日経、毎日...)の情報提供は早く且つ頻繁だということ。
- ただし各ニュースが全てを完結しているのではなく、欠けていたり、定義が異なったりしていた
- 当たり前だけど複数の情報ソースを通じてフィルターするのは大事。仮に共通点がない場合は、確定していないということで、断定めいた文脈にしないよう本エントリでは意識した。
- 産経の記事がどの大手ニュースよりも初情報で踏み込んだ内容をリリースしていたイメージ
- 日経の記事が最速だったイメージ
- 日経と毎日の記事は更新頻度が高いイメージ
- まとめを作りたいなら、大手ニュースをくまなく見るのがヨイ
- 逆に、非大手ニュースはリリース時期も後ろで、内容はほぼ共通していた
- まとめだけをみたいなら、非大手ニュースを数個見ればヨサそう
情報整理について
- まあまあ出来たのではないかと。できるだけpiyologを見ずに情報収集・整理したが(途中みてしまったが...)、取りこぼしたものはあまり無かったので。
- 勿論、取りこぼしたものもある。ので、更新頻度が高く、また情報密度も濃いpiyologはやっぱり凄かった
まとめの構成
GotSome \W+ech?
- 更新内容 -> イントロ -> タイムライン -> 攻撃の概要 -> JTBの体制(発覚前と後) -> 流出した可能性のある情報の項目 -> 対象となる可能性のあるユーザー ->対策 ->被害額 -> 不明点
piyolog
公式発表 -> タイムライン(提携先も含む) -> 被害状況 -> 発端 -> 原因 -> 対策…対応 -> ユーザーへの対応 -> 更新履歴
まず最初に更新内容を持ってくるのはやめる。更新が増えれば増える分だけ、リーダーが欲しい情報に到達するまでの距離と時間が長くなるから
- タイムラインを直後に持ってきたのは良かった。提携先を別テーブルに切り出すことはまでは考えつかなかったけど....備考カラムを作ったのは良い
- 此処から先が明確にpiyologの構成と大きく異なってくる。piyologの場合は"被害状況"と軸をユーザーと現在の時間に置いてるが、本エントリの場合は「攻撃の概要」と環境に軸を置いている。これは本エントリが、この話を自分の担当する環境とのdiffをとり改善ポイントを洗い出せることを目的としているので、この書き方になっている。逆にpiyologは広範囲への情報共有が主目的である(気がする)から、軸が異なるのではないかと推測する。よって、どっちが良い悪いではないと思う。
それを踏まえた上でいうと、本エントリの流れと粒度は若干ぎこちない。攻撃内容ときたからには、攻撃結果(攻撃成否, 攻撃対象,..)が次にくるべきではないか。で、その後に対策がくるのがキモチイと思われる。よって、今後新しく書くとしたら...
- イントロ -> タイムライン -> 攻撃の概要 -> 攻撃の成否 -> 攻撃の影響(範囲、期間、被害額) -> 原因 -> 対策 -> 不明点 -> 更新内容
という訳で、次は構成にもうちょっと気をつかって書いてみる
- ミニネタとして、はてなでは大見出しと中見出し2つで構成したほうがよさそう。少見出しと中見出しの見た目に違いがないように思える
- piyologの標的型メールのみやすさが圧倒的だった
- 問い合わせ窓口は想定リーダーが異なるから本ブログではいいかな...
今後
- 本件について引き続きウォチ
- 現在わかっていることを元に、仮説を立ててみたいと思う
- 今後のインシデントもまとめていけたらおもう。どれを線引にするかは自分の匙加減次第で、自分にもわからない。何となくじゃないかな。
- piyologはやっぱり凄い
*2:標的型メール急増 情報流出、経営に打撃も :日本経済新聞
*3:JTB情報流出、感染サーバー3台以上 再発防止策など公表 - 産経ニュース
*4:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*5:JTB個人情報793万件流出か?…標的型攻撃の巧妙な手口 : 科学 : 読売新聞(YOMIURI ONLINE)
*6:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*7:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*8:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*9:JTB、最大793万人分の情報流出か 不正アクセスで:朝日新聞デジタル
*10:標的型メール急増 情報流出、経営に打撃も :日本経済新聞
*11:記者の眼 - (4/5)JTBの情報漏洩事故報告は遅すぎだ! ではいつだったら良かったのか?:ITpro
*12:JTB、情報流出で再発防止策など報告 観光庁に :日本経済新聞
*13:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*14:JTB情報漏洩、国交省が有識者委設置へ :日本経済新聞
*15:JTB、個人情報流出か、約793万人分-7月に対策部門新設 | 旅行業界 最新情報 トラベルビジョン
*16:JTBの端末、海外サーバーと不審通信 顧客情報流出 :日本経済新聞
*17:不正アクセス容疑で捜査=JTB情報流出-警視庁:時事ドットコム
*18:http://www.jtbcorp.jp/jp/160615.html
*19:http://www3.nhk.or.jp/news/html/20160615/k10010557611000.html
*20:全文表示 | 国交省へ「批判の矛先」向く可能性も JTB個人情報流出と「対応の遅さ」 : J-CASTニュース
*21:JTB、情報流出で再発防止策を報告 外部調査委を設置 :日本経済新聞
*24:標的型メール急増 情報流出、経営に打撃も :日本経済新聞
*25:ニュース - 「流出事実ないがお客様にお詫びする」、793万人の情報流出可能性でJTBの高橋社長が謝罪:ITpro
*26:JTB:不正アクセス、最大793万人分の情報流出か - 毎日新聞
*27:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*28:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*29:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*30:JTB、個人情報流出か、約793万人分-7月に対策部門新設 | 旅行業界 最新情報 トラベルビジョン
*31:ニュース - 「流出事実ないがお客様にお詫びする」、793万人の情報流出可能性でJTBの高橋社長が謝罪:ITpro
*32:JTB、外部侵入者が閲覧の可能性 「標的型メール」か :日本経済新聞
*33:JTB情報流出:また「標的型メール」 巧妙偽装、防げず - 毎日新聞
*34:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(2/2ページ) - 産経ニュース
*35:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(1/2ページ) - 産経ニュース
*36:JTBの顧客情報流出、ウイルス発信源は中国か :日本経済新聞
*37:【情報流出】あなたは見抜けるか JTB がはまった「巧妙なメール」の罠とは (BuzzFeed Japan) - Yahoo!ニュース
*38:JTB個人情報793万件流出か?…標的型攻撃の巧妙な手口 : 科学 : 読売新聞(YOMIURI ONLINE)
*39:【JTB情報流出】全日空装うメールで感染 香港を経由 - 産経ニュース
*40:【情報流出】あなたは見抜けるか JTB がはまった「巧妙なメール」の罠とは (BuzzFeed Japan) - Yahoo!ニュース
*41:JTB個人情報793万件流出か?…標的型攻撃の巧妙な手口 : 科学 : 読売新聞(YOMIURI ONLINE)
*42:ニュース - 「流出事実ないがお客様にお詫びする」、793万人の情報流出可能性でJTBの高橋社長が謝罪:ITpro
*43:JTB、外部侵入者が閲覧の可能性 「標的型メール」か :日本経済新聞
*44:http://www3.nhk.or.jp/news/html/20160624/k10010570411000.html
*45:JTB、個人情報流出か、約793万人分-7月に対策部門新設 | 旅行業界 最新情報 トラベルビジョン
*46:JTB、顧客情報793万人分流出か 取引先装うメール :日本経済新聞
*47:JTB、最大793万人分の情報流出か 不正アクセスで:朝日新聞デジタル
*48:http://www.yomiuri.co.jp/national/20160614-OYT1T50095.html
*49:報道発表資料 : 提携先のJTB社のグループ会社サーバーへの不正アクセスに伴う「dトラベル」の個人情報流出の可能性について | お知らせ | NTTドコモ
*50:ドコモ、JTBへの不正アクセスに伴う「dトラベル」の33万人の個人情報流出か | マイナビニュース
*51:株式会社i.JTBへの不正アクセスによる個人情報流出の可能性に関するお知らせ|auトラベル
*52:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*53:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*54:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(2/2ページ) - 産経ニュース
*55:793万人分の個人情報流出…JTB、対応後手に 巧妙な標的型メール「脅威を十分に認識していなかった」(2/2ページ) - 産経ニュース
*56:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*57:News & Trend - (2/4)[詳報]JTBを襲った標的型攻撃:ITpro
*58:JTB社長、情報流出問題「補償は個別対応」 一律は考えず :日本経済新聞
*59:JTB個人情報流出事件「パスポート番号」は悪用できるのか調べてみたときのメモ
*60:http://www.nikkei.com/article/DGXLASDZ24HHZ_U6A620C1000000/