Hatena::ブログ(Diary)

hnwの日記 このページをアンテナに追加 RSSフィード

[プロフィール]
 

2018年7月6日(金) Travis CIのcron jobsを使ってGitHubに定期的にcommitする方法 このエントリーを含むブックマーク このエントリーのブックマークコメント

みなさん、Travis CI使ってますか?Trais CIクラウドCIサービスの1つで、GitHub上で公開しているOSSを自動テストする目的であれば定番中の定番といっていいサービスです。


ところで、さいきん私の公開しているプロジェクト「hnw/wsoui」で以下のことを実現したいと考えました。


  • ネット上のデータを加工してGoの連想配列の形で提供したい
  • 自動更新したい
    • 情報ソースは不定期に更新される
    • そこそこ最新のデータを反映していてほしい

これを実現する方法は何種類か思いつきますが、今回Travis CI のcron jobsを使って1週間に1回、更新があったときだけgit commitするような仕組みを作りましたので、これを紹介します。


Travis CI のcron jobs

Travis CIでは、gitリポジトリに新たなcommitがpushされるたびにテストスクリプトが実行されます。これにより、万一バグがあった場合でも早期に気付くことができたり、どのcommitでエンバグしたか調べる材料になったりするわけです。


また、commitごとのテスト実行とは別に、定期的にテストを行うような機能「Cron Jobs」も提供されています。これはTravis CIのコンソール画面「Settings」「Cron Jobs」から設定できます。ビルド間隔は日次、週次、月次のいずれか一つを選択できます。


f:id:hnw:20180706133401p:image


本来cron jobsは依存ライブラリバージョンアップなどで以前通っていたテストが失敗するようになっていないかを定期的にチェックする機能です。今回のようにcron jobsのときだけ別の処理を行うというのは変則的な使い方ではありますが、色々と便利な応用が考えられるのではないでしょうか。


通常のテストと自動更新との共存

さて、Travis CI上でジョブを定期実行できることはわかりました。テストスクリプト内で環境変数を見ればcron jobsかどうか判定できますから、「定期実行されたときだけ自動更新を実行する」という今回の目標は十分実現できそうです。


とはいえ、テストスクリプトにテスト以外の処理を追記してしまうと保守性が下がってしまうかもしれません。もう少し綺麗に実現する方法はないのでしょうか。


2018/6時点ではβ機能ですが、Travis CIにはBuild Stageという仕組みがあり、「cron jobsのときだけ実行」をシンプルに実現することができます。具体的には、.travis.ymlを次のように記述できます。


jobs:
  include:
    - stage: 'Test'
      script:
        - go test -v .
    - stage: 'Update Check'
      if: type = cron
      script:
        - [cron jobsのときに実行したいコマンド1] ...
        - [cron jobsのときに実行したいコマンド2] ...

このように記述すると普段はテストだけを実行し、cron jobsのときだけテスト成功後に「Update Check」処理が走ります。小さなことですが、別の処理を別の場所に記述できた方が安心ですよね。


f:id:hnw:20180706133358p:image


git commitするために

さて、ここまでの知識Travis CI上でcurlでデータを取ってきて変換スクリプトを動かすところまではできそうです。あとは生成されたファイルをgit commitするだけですが、これが意外と面倒です。


まずは対象リポジトリデプロイキーを用意します。これはSSH鍵ペアを新規作成した上で、公開鍵をGitHubリポジトリページから「Settings」「Deploy keys」で設定します。


$ ssh-keygen -t ed25519 -f /tmp/id_ed25519
$ cat /tmp/id_ed25519.pub
ssh-ed25519 ******************************************************************** hnw@example.com

今回のようにデプロイキーで外部からpushするような場合は「Allow write access」は必須になりますので注意してください。


f:id:hnw:20180706132115p:image


次に、先ほど生成した秘密鍵を暗号化してリポジトリアップロードします。まずtravisコマンドをインストールしてそれを利用します。


$ gem install travis
(snip)
$ travis encrypt-file /tmp/id_ed25519
Detected repository as hnw/wsoui, is this correct? |yes|
encrypting /tmp/id_ed25519 for hnw/wsoui
storing result as id_ed25519.enc
storing secure env variables for decryption

Please add the following to your build script (before_install stage in your .travis.yml, for instance):

    openssl aes-256-cbc -K $encrypted_****_key -iv $encrypted_****_iv -in id_ed25519.enc -out /tmp/id_ed25519 -d

Pro Tip: You can add it automatically by running with --add.

Make sure to add id_ed25519.enc to the git repository.
Make sure not to add /tmp/id_ed25519 to the git repository.
Commit all changes to your .travis.yml.
$ git add id_ed25519.enc

暗号化した秘密鍵Travis CI上で復号して$HOME/.ssh/以下にコピーして使います。設定ファイル.travis.ymlは最終的に次のようになりました。


language: go

go:
  - "1.10"

jobs:
  include:
    - stage: 'Test'
      script:
        - go test -v .
    - stage: 'Update Check'
      if: type = cron
      script:
        - git checkout master
        - curl "https://code.wireshark.org/****" > /tmp/manuf
        - scripts/oui-convert.pl /tmp/manuf > ouidata.go
        - go test -v .
        - openssl aes-256-cbc -K $encrypted_****_key -iv $encrypted_****_iv -in id_ed25519.enc -out $HOME/.ssh/id_ed25519 -d
        - chmod 600 $HOME/.ssh/id_ed25519
        - scripts/push-if-updated.sh ouidata.go

ここで注意すべきことですが、Travis CIのテスト対象は特定commitでありGitでいうところの「detached HEAD」と呼ばれる状態になっているため、そのままでは元のリポジトリにpushできません。そのため、まずmasterブランチに切り替えるという処理を行っています。ちょっとしたTIPSですが、私は少々ハマりました。


Travis CI上で自動更新を行うメリット

上記設定により、Travis CI上で自プロジェクトの自動更新ができるようになりました。しかし、cronで実行するだけであれば、VPSを利用することもできます。わざわざ手間をかけてTravis CIで実行するメリットは何でしょうか。


個人的には、GitHub+Travis CI環境では実行に必要な全ファイルが公開されていること、また実行ログが残ることがメリットだと考えています。


今回は自動生成したソースコードを自動commitしているわけですから、おかしな内容がcommitされてしまう可能性もゼロではありません。そんな場合でも、必要ファイルとログが公開されていれば、赤の他人であっても原因をつきとめて修正してPull Requestを送ることが可能です。


こんな過疎プロジェクトで誰もPull Request送らないでしょ、というツッコミもあるとは思いますが、可能性って大事だと思うんですよね。


まとめ

トラックバック - http://d.hatena.ne.jp/hnw/20180706

2018年4月17日(火) 日本語のパスワードジェネレータを作ってみた このエントリーを含むブックマーク このエントリーのブックマークコメント

Webサービスを使っていると、たまに「秘密の質問」の設定を求められることがあります。


f:id:hnw:20180416042915p:image


こういう場合、個人的にはランダム文字列を登録したいと思うのですが、次のようにマルチバイト文字しか登録できないことが多い気がします。


f:id:hnw:20180416042912p:image


普通のパスワードジェネレータではマルチバイト文字のパスワード生成ができないので、このような用途には使えません。そこで、ランダムなマルチバイト文字列を生成するサービス「 秘密の答えジェネレータ」を作ってみました。


f:id:hnw:20180417094732p:image


自分でも実用しており、既に5サービスに設定しましたが、非常に便利だと感じます。


本稿ではこのサービスの技術面の詳細について紹介します。


「秘密の答えジェネレータ」の構成要素

「秘密の答えジェネレータ」はHTML+JavaScriptだけで実現されており、GitHub Pagesでホストしています。また、独自ドメインのDNSおよびSSL化はCloudFlareで行っています。


このような構成にすると月額コスト0円で運用できる点、また万一GitHub Pagesが使えなくなったようなときに移転先がいくらでも見つかる*1点が良いですね。


ブラウザ上でパスワード生成することの是非

パスワード類は自分だけが知っているのが大前提ですから、リモートサーバ上で生成された文字列はパスワードとしては不適切です。その意味で、パスワードジェネレータをサーバサイド実装するのは良いアイデアとは言えません。


前述したとおり、本サービスはHTML+JavaScriptだけで実現されています。言い換えると、ランダム文字列の生成処理は全てローカルマシンのWebブラウザ上で実行されます。つまり、技術的には安全と言えるはずです。


ただ、利用者が一見してサーバサイド実装かクライアントサイド実装かわからない、というのは問題かもしれません。


乱数生成について

JavaScript上で乱数生成する場合Math.random()を使う事例が多いかと思いますが、この関数は多くのブラウザ上で暗号論的擬似乱数生成器(CSPRNG)として実装されておらず、特にパスワード生成には向かないようです*2


一方、多くのブラウザ上で動くCSPRNGとしてwindow.crypto.getRandomValues()という関数があります。私の手元で試したところ、ChromeSafari、Edge、Firefoxの全てで動作しました。PCブラウザだけでなく、スマートフォン上のブラウザでも実装されているようです。


Operaだけはwindow.crypto.getRandomValues()が実装されていないようですが、OperaではMath.random()がCSPRNGになっているとのことです*3。つまり、window.crypto.getRandomValues()が存在しなかったときだけMath.random()にフォールバックすればブラウザ上でもセキュアに乱数生成ができると言えそうです*4


ちなみに、本実装ではwindow.crypto.getRandomValues()から取り出したUInt32の値の剰余を取ることでN文字から1文字を取り出す処理を実装しているのですが、偏りが出てしまうので厳密には良くありません。具体的には、ひらがなのランダム文字列を生成する際に「ぁ」が「ん」より0.0000000233%ほど出現しやすくなっています。将来的に修正するかもしれませんが、現時点ではそのような問題があると認識した上でご利用ください。


ES6実装について

私は普段JavaScriptをほとんど書かないのですが、そろそろ生のES6で書いても許される空気を感じたため、今回のサービスでは実験的に大半の処理をES6で書いてみました。


そのためIE11で動かなくなってしまいましたが、それ以外であればPC・スマートフォンとも大抵のブラウザで動作します。


私が使った機能はarrow functionとclassくらいではあるのですが、トランスパイラなしでES6を書ける時代はすぐそこかな、という印象を持ちました。


秘密の質問は常に悪なのか?

さて、今回秘密の質問に対して嘘の回答をすることをオススメしているわけですが、そもそも秘密の質問というやり方自体にセキュリティ上の問題があるのでしょうか?


個人的には秘密の質問が常に悪いとは思いません。重要な操作の際のみ要求するような、第二パスワード的な位置づけであれば十分意味があるように思います。一方で、秘密の質問に答えられたらパスワード変更ができるようなサービス設計は非常に問題があると感じます。


また、秘密の質問の答えを他人が推測可能であるのも問題点ではありますが、それ以外に複数のサイトで重複しやすい点(母親の旧姓や好きな食べ物など)、また平文で記録されることが多い点も問題だと言えるでしょう。つまり、あるサービスでユーザ情報の漏洩が起きた場合に、他サービスの秘密の質問の答えまでバレてしまうかもしれません。


上記のような理由から、秘密の質問の答えは毎回異なるランダム文字列にすべきだと私は考えています。


生成した文字列をどう保管するか

このサービスで生成した文字列をサービス登録後に破棄してしまうことはオススメしません。破棄するのでなく、パスワードリマインダーのメモ欄などに記録しておいた方が後々面倒が無いように思います。


秘密の質問の答えを平文で保存しておくのが不安な場合は、正しい回答と自動生成文字列を組み合わせて使うこともできます。たとえば「母親の旧姓は?」に対して「高橋ゃたぞゅもぽねん」などと入力し、後ろの8文字だけを平文で記録しておけば多少は安心度が増すかもしれません。


参考URL


まとめ

  • 「秘密の質問」向けのパスワードジェネレータを作りました
  • 半分シャレのつもりでしたが、案外実用的です
    • 入力内容を他人に見られた場合のショルダーハック対策にもなるように思います(↓入力例)

f:id:hnw:20180417215234p:image

*1:パッと思いついた中ではGAEかNetlifyが良さそうです

*2Secure random values (in Node.js)

*3cryptanalysis - Are there any Javascript CSPRNGs? - Cryptography Stack Exchange

*4:IE10以前ではセキュアじゃないと思いますが、今回はそもそも動作しないので無視しています

2018年4月14日(土) PHPのis_numeric関数は使うべきでないという話 このエントリーを含むブックマーク このエントリーのブックマークコメント

本稿は私が前職の技術ブログで執筆した記事「そのis_numeric()は適切ですか?」を改題・再編集して掲載するものです。前職には許可を取ってあります*1


本稿ではPHP関数is_numeric()の使いどころについて問題提起をしてみます。


is_numeric関数とは

さて、まずはis_numeric()リファレンスマニュアルを見てみましょう。


bool is_numeric ( mixed $var )


指定した変数が数値であるかどうかを調べます。数値形式の文字列は以下の要素から なります。(オプションの)符号、任意の数の数字、(オプションの)小数部、 そして(オプションの)指数部。つまり、+0123.45e6 は数値として有効な値です。十六進表記(0xf4c3b00c など) や二進表記 (0b10100111001 など) は認められません。


http://php.net/manual/ja/function.is-numeric.php


なるほど、与えられた引数がnumeric(数字的)かを調べるような、名前の通りの関数なんですね、というのが初見での印象かと思います。


何が問題なのか?

マニュアルの記述を見ただけでこの関数の問題点に気付く人はあまりいないかもしれません。私がこの関数について問題だと思うのは、「numeric」と言われたときに想像するものが人によって違う点です。


具体的には、ユーザーの入力値が10進整数として正しいかチェックする意図でis_numeric()を利用しているPHPプログラムを見かけることがあります。しかし、マニュアルを読めばわかるように、この関数は以下の文字列を受け取ってもtrueを返してしまいます。


  • 1.23
  • .123
  • 1e2

これらの文字列を与えてもtrueになることを忘れていないですか、というのが今回の問題提起です。もちろん、is_numeric()によるチェックをすり抜けて先の処理に進んだところで、セキュリティホールになるようなコードは考えにくいと思います。しかし、これが原因のバグというのは十分考えられるのではないでしょうか。


下記はネット上で見つけたコードを少しアレンジしたものです。


<?php
function validate_date($date) {
    $dateArr = explode("-", $date);
    if (count($dateArr) == 3 &&
        is_numeric($dateArr[0]) && strlen($dateArr[0]) == 4 &&
        is_numeric($dateArr[1]) && strlen($dateArr[1]) == 2 &&
        is_numeric($dateArr[2]) && strlen($dateArr[2]) == 2) {
          return checkdate($dateArr[1], $dateArr[2], $dateArr[0]);
    }
    return false;
}

例えば、上記のコードでvalidate_date("12e3-12-31")はtrueになりますが、この値をそのままSQL文の日付型の値として使うとSQLエラーになります。似たような状況は十分あり得るのではないでしょうか。


is_numeric()の詳細な挙動

細かい挙動が気になる人のために、以下にPHP 7.2.4でis_numeric()がtrueを返す条件を書き出してみました。(バージョンごとに挙動が異なる部分もあるのですが、下記のように把握をしておけば大抵の人にとっては十分だろうと思います)


  • 整数
  • 浮動小数点数
  • 全体が下記のいずれかの正規表現にマッチする文字列
    • [\x20\t\x0a-\x0d]*[\+\-]?[0-9]+([\.][0-9]*)?([Ee][\+\-]?[0-9]+)?
    • [\x20\t\x0a-\x0d]*[\+\-]?[\.][0-9]+([Ee][\+\-]?[0-9]+)?

ほぼマニュアルの通りの挙動です。マニュアルに書いていないことは、先頭の空白文字列を読み飛ばしてくれることくらいでしょうか。「3.」も「.3」もtrueになるのに驚かれた方がいるかもしれませんが、PHPプログラム中に浮動小数点数を書く場合も同じように書けますので、それほど意外なことではありません。


まとめ

is_numeric()引数が数値っぽいかを返す関数ですが、浮動小数点数形式の文字列であってもtrueを返します。知識としては知っている人が多いと思いますが、うっかり10進整数のチェックに使っていたりしないでしょうか。10進整数のチェックが目的であれば、正規表現^[0-9]+$などと記述するのが一番誤解が少ない書き方のような気がします。


is_numeric()のチェックの後で浮動小数点数にキャストするのが適した状況も考えられなくはありませんが、少なくとも私はそんなコードを書いたことがありませんね…。


じゃあctype_digit()を使えばいいんじゃないか?と考える人がいるかもしれませんが、これはこれで罠があるので使わない方がいいというのが私の考えです(参考:「ctype_digit関数の罠」)。

*1:「いっすかー」「いいよー」くらいのノリです

トラックバック - http://d.hatena.ne.jp/hnw/20180414

2018年4月1日(日) PHP 7.2.0からDateTimeでミリ秒表示するときの丸め処理が変わった話 このエントリーを含むブックマーク このエントリーのブックマークコメント

エイプリルフールなので(?)、PHPの日付処理の細かい挙動がひっそり変わった話の解説をします。


ちなみに本稿はSlackグループ「PHPユーザーズ」の#randomチャンネルでの議論をまとめ直したものです。議論のきっかけを下さったmsngさん、tadsanさん、do_akiさんはじめとする皆様ありがとうございました。


PHP 7.0から日付のフォーマット文字列にミリ秒を意味するvが追加された

PHP 7.0.0から、DateTime::format()でミリ秒指定ができるようになっています。


v ミリ秒 (PHP 7.0.0 で追加) Same note applies as for u. 例: 654


http://php.net/manual/ja/function.date.php


date関数と違ってDateTimeオブジェクトはマイクロ秒の処理を行うので、これをミリ秒単位に丸めるような場合にv有用というわけです。たとえば次のように利用できます。


<?php
var_dump((new \DateTime('2018-04-01 00:11:22.123456'))->format('v')); // string(3) "123"

PHP 7.2から挙動が変わった

ところで、このvの挙動がPHP 7.1と7.2とで変わりました。7.1までは1ミリ秒以下を四捨五入していたのが、7.2からは切り捨てになっています。


<?php
var_dump((new \DateTime('2018-04-01 00:11:22.345678'))->format('v')); // PHP 7.1.x: "346" / PHP 7.2.x: "345"

仕様変更が必要だった理由

仕様変更の理由を想像すると、単純に四捨五入すると困る状況があるから、ということだと思います。たとえば次のように現在時刻をミリ秒まで表示するプログラムを考えてみます。


<?php
var_dump((new \DateTime())->format('Y-m-d H:i:s.v'));

DateTimeのコンストラクタは無引数の場合現在時刻を返します。たとえば次のような値を返しているのであれば、四捨五入でも切り捨てでも全く問題はありません。


string(23) "2018-04-01 00:11:22.346"

しかし、現在時刻の秒未満が仮に999.9ミリ秒だった場合、四捨五入すると次のような結果になってしまいます。


string(24) "2018-04-01 00:11:22.1000"

この文字列全体を日付関数でparseするような場合、これでは23秒ではなく22.1秒として解釈されてしまうでしょう。つまり、vで四捨五入するのは仕様として良くないということになります。切り捨てであればこのような問題は起こらず、丸め後の値は必ず3桁になります。


一般に、何かの数を丸める場合に良かれと思って四捨五入にしてしまうことがある気がします。ところが、今回は四捨五入では問題になるという面白い事例でした。


参考URL

2018年3月21日(水) セキュリティの話題に丸腰で踏み込んでくる人を見た このエントリーを含むブックマーク このエントリーのブックマークコメント

Qiita上で「ゲームでよくされるチート手法とその対策 〜アプリケーションハッキング編〜」という記事がいいね数を集めているようですが、全セクションにツッコミどころがあるような印象です。私はセキュリティ本職というわけではありませんが、素人の私から見てもひどいと思ったところだけ個別にツッコミを入れてみます。


念のため補足しておくと、誰であろうと情報発信すること自体は大変良いことです。ただ、誤りを含んだ文章がウッカリ注目されてしまうとそれを信じてしまう人も出てくるので、大人げないと思いつつツッコミを入れる次第です。


デコンパイル(逆コンパイル)

2.の詳しい解説として、C/C++で記述されたコードをコンパイルすると機械語に変換されます。これを逆コンパイルしても、逆アセンブラまでにしかなりません。そのため、この状態ではソースコードの中身を解析するのは(人間では)非常に困難なため、ネイティブコードで書いた処理というのはデコンパイルへの対策となります。


技術用語の使い方が正確でない点は見なかったフリをするとして、C/C++で記述すれば安全だというのは幻想です。攻撃者の多くは高機能な逆アセンブラ(おそらくIDA Pro)を所有しており、昔に比べると格段に処理を追いやすい環境が整っています。基本的にはネイティブバイナリからでもコードの内容は把握可能だと考えるべきでしょう。


そもそもこのセクションの前半で紹介されている「iOS Reverse Engineeringの操作手順」もARMのアセンブリIDA Pro/Hopperで解析する話題になっており、ネイティブコードなら安全という主張とは反対の内容です。ご自身で紹介している記事なのに読んでいないのかしら?と思ってしまいますね。


話を戻すと、クライアントバイナリの挙動は全て解析される前提でシステム全体を設計すべきです。つまり、解析されて困る内容はサーバ側で実装するのが原則論になるでしょう。


絶対に秘密にしたいロジックをユーザーに配布するバイナリに入れたい場合は、自前での対策はあきらめてアンチデバッギング機能・アンチ逆アセンブル機能を持ったセキュリティ製品を購入した方が良いでしょう。実際の現場ではバレてもクリティカルじゃないけど簡単にバレるのはイヤという程度の状況だったりするため、自前実装で頑張っているところもあれば外部ソリューションに頼っているところもあるといった印象です。


乱数調整

なお、乱数を生成する際、現在時刻を基にして、擬似乱数を生成することが多いので、特定のタイミング(時刻)を狙うとうまくいく、といった都市伝説みたいな論調はあながち間違っているわけではありません。

間違いでしょう。明示的ににひどい実装をしない限りそんなことにはなりません。


引用部からすると乱数シードとして現在時刻を利用している言語・環境が多い、という風に読み取れますが、モバイルアプリ文脈でそんな環境はないはずです。現在のOSは各種割り込みのタイミングから十分なエントロピー(乱雑さ)を蓄積し、それを利用して乱数を生成しているため、十分にセキュアだと言えます(マシンの外部から乱数列を推測することは原則不可能です)。また、各言語の乱数生成の実装はOSに依存しているはずで、これらもセキュアだと言えます。


ネット上には自前実装の乱数生成器が転がっていたりして、そうしたものは時刻を乱数シードに使っているかもしれませんが、それらはセキュリティ知識の無い人が作成した脆弱な実装です。言うまでもありませんがコピペして使うなどは言語道断です。


攻撃者がOSroot権限を持っている場合など、乱数生成器の内部状態にアクセスできるようであれば次に生成される乱数を事前に知ることも可能でしょう。その意味で、重要な抽選はサーバ側で行うべきという主張自体は正しいと思います。ただし、サーバ側で実装するにしても乱数シードのエントロピー確保をOSに任せること、および採用する疑似乱数の性質を把握することの2点は必須です。


ちなみに、乱数シードのエントロピー不足でサーバ上の乱数生成器が攻撃対象になりうるという事例は私が以前会社の技術ブログ記事「PHPのセッションIDは暗号論的に弱い乱数生成器を使っており、セッションハイジャックの危険性がある」で紹介しました。古いPHPで設定がイマイチなときにしか発生しない話題ですが、ご参考まで。


余談

本当はDBトランザクションとロックに関してツッコミを入れようと思ったんですが、長編になりそうだったのでその他のところだけ記事にしました。もちろん私より適任の方が記事を書いてくださってもいいんですよ?(チラッ

RishatangRishatang 2018/03/22 20:04 文字数の都合上書けなかったのですが、私が邪推した理由はブコメの内容だけではなく、本文中の「ご自身で紹介している記事なのに読んでいないのかしら?と思ってしまいますね。」の部分も理由としてあります。

人によって感覚は違うのでhnwさんがどういうつもりで書いたのかはわかりませんが、少なくとも私は「完全な煽り、ないし元記事の筆者を馬鹿にしているな」と思いました。

「誰であろうと情報発信すること自体は大変良い」と思っているのなら自然と元記事の筆者に対して敬意を払った態度になると思うのですが、個人的にそうは見えませんでした。

以上です。

hnwhnw 2018/03/22 21:07 情報発信する姿勢はまず良いと思いますが、正しい情報を発信しようとする姿勢があった方がなお良いと私は思います。

ですから、もし自分が読んでもいない記事を紹介しているのであればそれは正しく非難されるべきでしょう。そして、その疑いを私が持っているということも隠すことではないと思います。

そのような可能性は薄い、文脈として十分に整合性がある、とRishatangさんが思われたのであれば不快に思われるのも当然かもしれません。

hnwhnw 2018/03/22 21:42 もう一点補足しておきますと、私は元記事を書いた方が悪だと思っているわけではありません。自分のメモ書き程度の文章であっても気軽に公開すること自体は悪いことではないし、むしろ良いことだと感じているのは本心です。そうした文書の中に宝が埋もれている可能性もあるわけですから。

一方で、誤りを含んだ文章が多くの人に注目されてしまうと、それを鵜呑みにしてしまう別の技術者が現れてしまうかもしれないという危惧も本心です。そうなってしまったときにその文書の品質が批判されることも当然のことだと思いますが、今回について言えば注目を集めるに至った仕組みの側の問題ではないでしょうか。つまり、技術メディアとしてのQiitaにおいて記事の品質担保の仕組みが機能していない点が一番の問題だと思います。

そもそも編集者がいないようなサイトですから品質担保が難しいのは当然なのですが、現在のQiitaはいいね数だけを基準にしたランキングを提示しているなど、いいねの数を良記事の基準のような使い方をしており、品質担保をあきらめてバズる記事を書いた方が偉い、というような姿勢のサイトに見えます。もう少し何とかできるんじゃないの?というのが私の意見です。

hnwhnw 2018/03/23 00:43 タイトルが煽りっぽくなってしまった感はあるかもしれません。セキュリティ本職の人にかかったらすごい量の添削が来そうだなーと思ったのを深く考えずに記事タイトルにしてしまいました。

taptappuntaptappun 2018/03/25 02:39 記事を書いた本人です。
記事をご覧いただきありがとうございます。
記事を書いた意図や経緯の齟齬があるようなので、この場で述べさせていただきます。
・記事に書いた内容は私がこれまでの実務での経験に基づいたもの
・表現は内容を整理して端的にまとめたもの
・参考記事は基本的に結論として述べるにあたり、裏付けを得るためのもの
この3点を基準として記事を書いています。
記事の内容が絶対正しいと述べる気もこれで十分だと述べる気も全くありません。
ただ、実務に基づいたものであるので、「理論的に考えればおかしい」という内容は大いにあります(理論的には問題があると思ったが、実際に開発、運用した中での最適解は違いました。その最たる例がボタン連打なのですが)
また、もちろん記事を書くまでに考察、調査した過程を省略してのべているものもありますし、プラットホームに依存した話のため、いっぱい注釈をつけなければ正しくないというものもあります。
しかし、それらすべて上記3点の基準に準ずる形になるように変えて書いています。
また、私は学生時代、セキュリティの研究室でしたので、ご指摘のようなことも多く経験しました。その中での経験を通して私の記事もご指摘の内容も結果としては眉唾物でしかない、ということを感じています。(セキュリティというものは問題を提起すると必ず批判があるもので、正解も絶対にありえません。)
そのため、私の記事が正しいのか間違っているのかといった評価はご覧にいただいた方にお任せしたいと思います。

hnwhnw 2018/03/25 16:21 taptappunさん

独り言くらいのつもりの記事でしたので、わざわざ反応いただきありがとうございます。

> 私は学生時代、セキュリティの研究室でしたので

ではセミプロくらいの方なんですね。であれば周囲にCTFやっててアセンブリが友達みたいな人もたくさんいそうな気がしますし、韓国や中国の方が実力が断然上だなーといった感覚値も持たれていそうな気がしますが、その上で今回の記事の内容なんですね。

> ・記事に書いた内容は私がこれまでの実務での経験に基づいたもの

なるほど。乱数調整の章で書かれた下記部分も実務で経験されたんでしょうか?

> 特定のタイミング(時刻)を狙うとうまくいく

私はそのような実装はあまり一般的ではない(乱数実装に関するバグがあるにしても、時刻ベースで攻撃が成立するような状況は珍しい)と感じました。一方、taptappunさんの書き方ではそのような実装がありふれているかのように捉えられかねないと感じたので、この点を抜き出して反論させてもらいました。

引用部の直後で例示しておられるポケモンの件もGameBoyでの事例で、昨今のモバイルOSとは相当違う環境ですので、実務での経験のお話が裏にあるとは全く予想もしませんでした。もしも実務での経験で近いお話があったのであれば、書ける範囲でその話を書いた方が良かったかもしれませんね。

> セキュリティというものは問題を提起すると必ず批判があるもので、正解も絶対にありえません

状況を限定すれば必ず正解はあると思いますよ。そうでなければセキュリティの研究や仕事って何をするんでしょう?

 
ページビュー
2673918