【書評】体系的に学ぶ 安全なWebアプリケーションの作り方 第2版

技術面接でボコボコにされた備忘録に書いた通り、先日おこなわれた技術面談でボコボコにされた。特にセキュリティ周りの質問に回答できなかったのが悔しかった。 そこでセキュリティの勉強をするために『体系的に学ぶ 安全なWebアプリケーションの作り方 第2版』なる書籍を読んだ。 せっかくなのでその書評をば。 #PR 体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 楽天 Amazon 良かった点 体系的、網羅的に学べる この書籍は667ページもあって、内容は体系的かつ網羅的に書かれている(と思う)。 まずWebアプリケーションのセキュリティに関するページは膨大で、これだけで400ページくらいある。 特にXSSやCSRFの説明はいろいろなパターンで何度も何度も出てくるので、自然と脳に定着すると思う。 自分は技術面接でCSRFのことを聞かれてクリックジャッキングのことを話してしまったが、もう今後間違うことはないだろう。 さらに、終盤では脆弱性診断の方法、ネットワークやマルウェアに関連する脆弱性、開発マネジメントの手法などについても触れられていて、かなり手広くカバーされているという印象。 一家に一台欲しいタイプの本だと思う。 サンプルが充実している 脆弱性を抱えるソースコードが大量に掲載されているので、脆弱性がどのようにして発生しているのかを理解しやすい。 加えてサンプルアプリケーション用のDocker環境も配布されているので、手元で気軽に脆弱性を体験できるのも良い。 微妙だった点 Docker環境のソースコードをいじれない 本書のサンプルはPHPで書かれているので、PHP初心者の自分的には「今このセッションの中身はどうなっているんだろう」みたいにデバッグしたくなることがあった。 ただDocker環境ではソースコードが編集できないようになっていたので(厳密には.tar.gzを展開した上でソースコードを編集し再圧縮した上でDockerイメージを再ビルドすれば編集できる)、理解が難しい点もあった。 PHPが得意な人にとっては問題ないかも。 認証周りの説明がやや少ない 例えばJWTやOAuthについての説明がほとんどなかった。 自分は仕事ではJWTやOAuthを利用することが多いので、もう少し詳しく知りたかった。 もし第3版が出るなら、ここらへんの説明をもう少し充実させてほしい。 まとめ 総じてかなり良い本だという印象。 上にも書いた通り、一家に一台欲しいタイプの本だと思う。 この本を読んでセキュリティに対するモチベーションが上がってきたので、秋にはセキュリティスペシャリストの試験も受けてみたい。

2025-04-02

更生した不良は偉くないと言う人がいるけど

更生した不良や犯罪者に対して「更生して偉い」と言ったら、「最初から真っ当に生きている人間の方が偉い」と説教してくる人をSNSではたまに見る。 でも「更生して偉い」という発言の裏で行われている比較って「不良」と「真っ当な人間」の比較じゃなくて、「更生した不良」と「更生していない不良」の比較だよな、多分。 だからそういう説教ってめちゃくちゃ的外れだと思う。 例えば運動会の徒競走で1位になった子どもに「偉いね」と褒めただけなのに、「いやボルトの方が何倍も速いし偉いだろ」と説教してくるのと本質的には変わらないと思う。 ある地域、ある学校、ある徒競走の組の中で1位になったことを褒めているのであって、別にプロアスリートと比較して褒めているわけじゃないんだよ。 それと同じように、一度過ちを犯したら更生できない人がたくさんいる中で、それでも更生できた人のことを褒めているだけなんだよな。

2025-03-30

Hugoでtagの先頭文字が大文字になるのを回避する

Hugoはデフォルトだとフッターなどに表示されるtagの先頭文字が大文字になってしまう。 たとえばtags=['hoge']と設定すると、Hugoの.GetTermsで取得したデータはHogeになっている。 ちなみに.Data.Termsだとそのまま取得できるっぽい。 個人的にはtagsの値は入力そのままで表示したいのでこれを回避する方法を調べた。 方法 hugo.yamlに以下の設定を追加するだけ。 titleCaseStyle: none 公式ドキュメントにもちゃんと書いてあるが、なかなか見つけられずにハマった。 デフォルトはapでnone以外にもchicagoとかgoとか色々ある。 ちなみに今回の記事はtagsの話として書いているが、categoriesに関しても同様の設定が適用されているはず(自分はcategoriesを使っていないので未確認)。

2025-03-27

tcardgenを使ってHugoでOGPを設定する

Go製のtcardgenというツールを使って、Hugoの各記事にOGP画像を設定する方法を紹介する。 今回実際に生成した画像は以下の通り。 tcardgenをインストールする tcardgenの公式ドキュメントを参考にインストールする。 今回はHomebrewを使ってインストールした。 brew install Ladicle/tap/tcardgen tcardgen用のディレクトリを作成する tcardgen用のフォントやテンプレートや設定ファイルはHugoのビルド時には不要なのでなるべくHugoからは切り離したい。 そこで今回はトップレベルに/tcardgenというディレクトリを作成してそこにtcardgenに関連するファイルをまとめた。 トップレベルのディレクトリ構成は以下の通り。 . ├── README.md ├── archetypes ├── assets ├── content ├── hugo.yaml ├── layouts ├── public ├── static ├── tcardgen └── themes フォントをダウンロードする tcardgenの公式ドキュメントを参考にして、均等フォントをダウンロードした。 今回はKintoSans-Bold.ttf、KintoSans-Medium.ttf、KintoSans-Regular.ttfだけを/tcardgen/fontsに放り込んだ。 後述する設定ファイルで他の種類のフォントを指定したい場合はそれらのフォントも同様に/tcardgen/fontsに放り込む。 テンプレートを作成する OGPのテンプレートを作成して、/tcardgen/template.pngとして保存した。 Canvaを使うと簡単にできた。 今回は以下のようなテンプレートを作成した。 tcardgenの設定ファイルを作成する フォントの色や場所などを変更するための設定ファイルを作成した。 今回は公式ドキュメントのtemplate3.config.yamlを参考にして以下のような設定ファイルを作成した。 template: config.yaml title: start: px: 125 py: 185 fgHexColor: "#000000" fontSize: 72 fontStyle: Bold maxWidth: 970 lineSpacing: 10 category: enabled: true start: px: 120 py: 110 fgHexColor: "#555555" fontSize: 42 fontStyle: Regular info: enabled: true start: px: 220 py: 480 fgHexColor: "#555555" fontSize: 38 fontStyle: Regular separator: " | " timeFormat: "2006-01-02" tags: enabled: true limit: 0 start: px: 1080 py: 110 fgHexColor: "#FFFFFF" bgHexColor: "#545454" fontSize: 32 fontStyle: Medium boxAlign: Right boxSpacing: 6 boxPadding: top: 6 right: 10 bottom: 6 left: 10 OGP生成用のシェルスクリプトを作成する 毎回tcardgenのコマンドを打つのは面倒なので、シェルスクリプトを作成して一発でOGP画像を生成できるようにする。 ...

2025-03-25

Hugoで外部リンクを新規タブで開くようにする

Hugoはデフォルトだとリンクが同じタブで開かれる。 デフォルトの設定を変更し、外部リンクを新規タブで開くようにする方法を紹介する。 リンク用のHTMLを作成 /layouts/_default/_markup/render-link.htmlを作成する。 Hugoではリンク用のHTMLは/layouts/_default/_markup/render-link.htmlに定義すると決まっているので、一文字も違わないように/layouts/_default/_markup/render-link.htmlを作成する。 実装は以下。 {{- /* Forked from https://github.com/gohugoio/hugo/blob/master/tpl/tplimpl/embedded/templates/_default/_markup/render-link.html At 2025-03-25 Added target="_blank" to external links */}} {{- $u := urls.Parse .Destination -}} {{- $href := $u.String -}} {{- if strings.HasPrefix $u.String "#" -}} {{- $href = printf "%s#%s" .PageInner.RelPermalink $u.Fragment -}} {{- else if and $href (not $u.IsAbs) -}} {{- $path := strings.TrimPrefix "./" $u.Path -}} {{- with or ($.PageInner.GetPage $path) ($.PageInner.Resources.Get $path) (resources.Get $path) -}} {{- $href = .RelPermalink -}} {{- with $u.RawQuery -}} {{- $href = printf "%s?%s" $href . -}} {{- end -}} {{- with $u.Fragment -}} {{- $href = printf "%s#%s" $href . -}} {{- end -}} {{- end -}} {{- end -}} <a href="{{ $href }}" {{- if strings.HasPrefix $href "http" }} target="_blank" rel="noopener" {{- end }} {{- with .Title }} title="{{ . }}" {{- end }}>{{ .Text }}</a> {{- /**/ -}} HugoのGitHubからリンクの実装をコピペして {{- if strings.HasPrefix $href "http" }} target="_blank" rel="noopener" {{- end }} を追加しただけである。 この実装ではhrefがhttpで始まっていたら外部URLだと判定するようにしている。 リンクを使う 上記の実装を終えたら、普通にリンクを使うだけで外部リンクが新規タブで開くようになる。 [外部リンク](https://example.com)

2025-03-25

Hugoに自作のアフィリエイト用のショートコードを組み込む

Hugoにはショートコードという機能がある。 Reactのコンポーネントみたいな感じで、予め定義したHTMLに引数経由で情報を注入することができる。 今回は以下のようなアフィリエイト用のショートコードを作成したので、その作り方を紹介する。 #PR FACTFULNESS 10の思い込みを乗り越え、データを基に世界を正しく見る習慣 楽天 Amazon 要件定義 ショートコードの引数として以下を設定した。 rakuten_href: 楽天リンクのURL amazon_href: AmazonリンクのURL src: 画像のURL title: 本の名前 ショートコード用のHTMLを作成 /layouts/shortcodes/affiliate.htmlを作成する。 <div id="affiliate_wrapper"> <div id="affiliate_pr">#PR</div> <img src='{{ .Get "src" }}' id="affiliate_image" alt='{{ .Get "title" }}'/> <p id="affiliate_title">{{ .Get "title" }}</p> <div id="affiliate_link_wrapper"> <a href='{{ .Get "rakuten_href" }}' target="_blank" id="affiliate_rakuten"> 楽天 </a> <a href='{{ .Get "amazon_href" }}' target="_blank" id="affiliate_amazon"> Amazon </a> </div> </div> 本当はidではなくclassを使ったほうが良いと思うが、テーマのCSSに詳細度で負けることがあるのでidを使っている。 ショートコード用のCSSを作成 カスタムCSSに関してはHugoでサポートされているわけではなく、テーマごとにサポートされているっぽい。 たとえばPaperModだと、/assets/css/extendedにCSSファイルを追加すると自動でCSSが読み込まれる。 もしテーマ側でカスタムCSSがサポートされていない場合は自分でテンプレートを編集してheadタグ内でCSSを読み込んだりする必要がある。 もしhoverのような疑似クラスを利用しないなら、style属性に直接スタイルを書く方が楽かもしれない。 ということでPaperModなら/assets/css/extended/affiliate.cssを作成する。 #affiliate_wrapper { display: flex; flex-direction: column; align-items: center; row-gap: 10px; padding-top: 10px; padding-bottom: 20px; width: 252px; background-color: white; border: 1px solid #95a5a6; border-radius: 10px; box-shadow: none; margin-bottom: 20px; } #affiliate_pr { width: 220px; color: #0b80a5; font-size: 14px; text-align: right; } #affiliate_image { max-width: 240px; height: 240px; margin: 0; padding: 0; border-radius: 0; } #affiliate_title { max-width: 200px; color: #1f1f1f; font-size: 14px; margin: 0; padding: 0; } #affiliate_link_wrapper { width: 210px; display: flex; justify-content: space-between; align-items: center; } #affiliate_link_wrapper a { width: 100px; height: 30px; border-radius: 18px; font-size: 14px; line-height: 30px; text-align: center; box-shadow: none; } #affiliate_rakuten { background-color: #bf0000; color: white; } #affiliate_rakuten:hover { background-color: #990000; } #affiliate_amazon { background-color: #ffa41c; color: black; } #affiliate_amazon:hover { background-color: #e68a00; } ショートコードを呼び出す {{< affiliate rakuten_href=https://a.r10.to/hNab5q amazon_href=https://amzn.to/4hG1NVS src=https://hbb.afl.rakuten.co.jp/hgb/46510050.5165b4d2.46510051.bf2ae0c3/?me_id=1278256&item_id=17966596&pc=https%3A%2F%2Fthumbnail.image.rakuten.co.jp%2F%400_mall%2Frakutenkobo-ebooks%2Fcabinet%2F7708%2F2000007017708.jpg%3F_ex%3D240x240&s=240x240&t=pict title="FACTFULNESS 10の思い込みを乗り越え、データを基に世界を正しく見る習慣" >}} {と<の間にスペースを入れてしまって20分ほど溶かしたので注意。 ...

2025-03-25

【書評】プロになるJava

転職先でJavaを使うことになったのでJavaの入門書である『プロになるJava』を購入した。 #PR プロになるJava-仕事で必要なプログラミングの知識がゼロから身につく最高の指南書 楽天 Amazon ぶっちゃけ言語の入門書ってどれを買ってもそんなに大差はない気がするので、今回は書評の練習のつもりで手抜きしてサラッと書いてみる。 良かった点 IDEの説明が豊富だった 大量の画像付きでIDEの使い方を詳しく説明していて、IDE初心者の自分はとても助かった。 以前Javaを勉強したときはIDEの使い方が分からなくて挫折したが、今回は説明が丁寧だったので平気だった。 著者の感想が書かれていた たとえば、「Javaには他の言語にある〇〇って機能がないけど、将来的には欲しいよね」みたいな感想が結構載っていた。 そういう感想があるとJavaがその機能を「あえて採用していない」のか「流行に少し遅れているだけ」なのかを区別できたりする。 あと、「ServletやJSPは保守案件をやるわけじゃないならキャッチアップしなくてもいいよ」とかもJavaのトレンドを理解していない人間にとっては有用な情報だった。 感想や雑談からしか得られないコンテキストって間違いなく存在すると思うので、その点がよかった。 実務面もカバーされていた ウェブフレームワークのSpring BootとテストフレームワークのJUnitの解説にぞれぞれ1章ずつが割かれていたのが良かった。 微妙だった点 サンプルコードがやや不親切 たとえば aaa bbb という既存のコードに新しく処理を追加して aaa ccc bbb というコードに変更するステップがあったとする。 このとき本書では ccc のように追加すべきサンプルコードしか記載されておらず、どこにこのコードを追加すればよいのかが分かりにくかった。 文章でどこに追加すべきかという説明は書いてあったが、個人的にはGitHubのコード差分のような形式で変更箇所の前後2行くらいずつもコードで表示してくれるほうが脳に負荷がかからなくてありがたい。 削除するコードに関しても文章で説明されているだけだったので、斜め読みしていると気づかないことがあった。 まとめ サンプルコードの差分が分かりにくいこと以外は良かったと思う。

2025-03-23

社会人って「いつ死んでも良い」って言う人多くない?

社会人になってからちょくちょく「俺はいつ死んでも良いと思ってる」と発言する人に出会う。 新卒でベンチャー気質の会社に入ったのもちょっとは関係しているのかな。 新卒で入った会社の上司がまさにそのうちの一人で「俺は人生は暇つぶしだと思っているし、いつ死んでも良いと思っている。今俺が生きている理由は俺の周りの人達を幸せにしたいからだ。」と言っていた。 こういう類の発言ってどうにも嘘っぽく感じてしまって駄目なんだよな。 「俺の周りの人達を幸せにしたい」は全然いいと思うんだけど、「俺は人生は暇つぶしだと思っているし、いつ死んでも良いと思っている」は99%嘘じゃん。 ちなみにその上司はバイクで転倒して鎖骨とか肋骨を折る大怪我をしたんだけど、普通に手術して、普通にリハビリしてた。 やっぱり人間はみんな生きたいんだよな。 そろそろ死を利用してカッコつけるのやめないか?

2025-03-19

TryHackMeが面白い

『TryHackMe』というサイトがある。 わざと脆弱性を残してある仮想環境に対して攻撃を行うことでセキュリティの勉強をすることができるサイトだ。 こういう種類のゲームをCTF(Capture The Flag)と呼ぶらしい。 セキュリティの勉強をするなら自分が攻撃者側を体験するのが一番効率的だというコンセプトなんだろう。 自分はYoTubeで以下の動画を見てTryHackMeの存在を知った。 これが結構面白い。 攻撃の手順は割とテンプレ化できるところがあるので、よく使うサイトやコマンドをいつでも見返せるようにこの記事に残していく。 この記事は定期的に更新していくタイプの記事にする予定。 よく使うサイト pentestmonkey https://pentestmonkey.net/ リバースシェルのコマンド等が言語ごとにまとまっている。 『TryHackMe』では基本的にはシェルで侵入し、そこから攻撃を仕掛けていくことが多い。 ここで使えそうなコマンドを探してシェルに侵入していこう。 GTFOBins https://gtfobins.github.io/ Linuxのコマンドを使って権限昇格を行う方法がまとまっている。 『TryHackMe』ではrootユーザに権限昇格できればほとんど勝ち確である。 このサイトで権限昇格できそうなコマンドを探してrootユーザになることを目指そう。 よく使うコマンド ポートスキャン nmap -sV (IP Address) -sVオプションを付けることで動いているサービスとそのバージョン情報を取得できる。 実際の実行例が以下みたいな感じ。 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.8 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) tcpの22番ポートでsshが、tcpの80番ポートでhttpがそれぞれ動いていることがわかる。 ...

2025-03-17

落ちた会社のフォロー面談を受けた

2次で落ちた会社のフォロー面談を受けた。メモを取っていたので、その内容を振り返ってみる。 いきなり話題がそれるけど、落ちた人に対してフォロー面談をしてくれる企業の目的ってなんなんだろうな? 落ちて落ち込んでいる人を相手にするのってただでさえシンドそうだし、何十人かに一人は感情的に食ってかかる人もいるんじゃないかな? 担当者のメンタルは結構キツそう。 ただ、落ちた身からするとフィードバックがもらえるのはめちゃくちゃありがたい。 「手応えあったのになんで落ちたんだろう?」みたいなことって割とあるし、そういうときに落ちた理由を知ることができたらめちゃくちゃ成長できると思う。今回の面談も学びが多かったので本当に感謝してる。 フィードバック 良いところ 実装の一つ一つは特に問題なし 悪いところ WikiやREADME.mdを書いていない 環境変数に対するコメントがない 保守性の観点で微妙なところがある 前職はフロントエンドもバックエンドもインフラも全部一人でやるみたいな環境だったから、こういうチームで働く上での当たり前の部分が全然身についてないんだよな。 一応Notionとかにドキュメントを書いたりはしてたんだけど、「コードを書いたら即ドキュメント」みたいな感じではなかったんだよな。 仕事が一段落して余裕のあるときに、「いけね、ドキュメント書かなきゃ!」って感じ。 今回はコーディング試験で落ちたんだけど、仕事でもドキュメント書けない人間がコーディング試験でドキュメントを書こうなんて発想になるわけないよな。これは反省だわ。 こっちからの質問1. どうすれば保守性の高いコードを書けますか? 担当者Aさん「弊社ではオニオンアーキテクチャを採用しています。アーキテクチャに関する知識を身につけると良いかもしれないです。あとは依存性の少ないコードを意識するのも大事です。」 担当者Bさん「会社のフェーズによって保守性を大事にするかどうかって全然違います。弊社では保守性を意識するフェーズに入っていますが、そうでない会社もたくさんあります。座学で保守性を学ぶこともできますが、保守性を意識している会社に身を置かないと経験できないこともたくさんあるので、そこら辺を就活の軸にするのも良いかもしれないです。」 自分でも保守性の高いコードは書けていないんだろうなという自覚はあった。 デザインパターンみたいなのも全然知らない。ここらへんは座学すべきかな。 「保守性を意識している会社に身を置かないと経験できないこともたくさんある」って言葉はかなり響いた。今までがむしゃらに座学中心で勉強をしてきたけど、実務で経験しないと成長しない部分ってあるよなあ。 こっちからの質問2. クッキー認証の実装が自信なかったんですけど、どうでしたか? 担当者Aさん「特に問題があるというコメントはないので大丈夫だと思います。」 やったぜ。今回のコーディング試験では仕様上クッキー認証を使う必要があったんだけど、前職ではlocalStorageにJWTを保存する認証しかやってなかったから不安が大きかった。 結構クッキー認証について調べてから実装したんだけど、特にレビューがつかなかったみたいなので嬉しい。 こっちからの質問3. テストを書こうと思ったんですが認証の部分が難しくて書きませんでした。書いたほうが評価は良かったですか? 担当者Aさん「細かく統計を取ったわけではないですが、合格する人の多くはテストを書いている印象です。認証の部分を乗り越えるためにはE2Eのフレームワークを使ったりするなどの工夫が必要かもしれないですね。認証部分は無理でもユニットテストだけ書く方も結構いますね。」 担当者Bさん「さっき申し上げた環境変数のコメントを書いてないとかにも通じるところがあるんですけど、それぞれの会社に宗教があるので分からなかったら担当者に聞いたほうが良いと思います。ある会社ではGOODとされてたことが、ある会社ではBADと評価されるってことはよくあるので、そこは担当者とコミュニケーションを取りながら探っていくのが良いと思います。自分も聞かずに面接で落とされた経験があるので、それ以来ちゃんと聞くようにしています。」 いやー、Bさんの言葉が響いたね。 俺の場合「聞きたいけど勇気が出なくて聞けない!」とかじゃなくて、そもそも聞くという発想にすら至らない。どんだけコミュニケーション力低いんだよ! 「聞いたほうが良いですよ」と言われて、思わず「おっしゃる通りです」と返答してしまった。 まあ、これに関しては前職でなんでもかんでも自分でやりまくっていたというのも大きいかな。壁にぶつかったら自力で乗り越えるっていうのが当たり前になっていたから、他人に聞くとか他人に頼るみたいな発想がコマンドの1ページ目に出てこないんだよな。 一応SIerに就職が決まっているんだけど、SIerは顧客折衝が大事な仕事だからコミュニケーション能力の低さは改善しなきゃだな。 担当者から最後の一言 担当者Aさん「個人的な印象では〇〇さんは勉強熱心でやる気もあって非常に好印象でした。技術に前のめりで向き合う姿勢も良いと思います。再チャレンジする機会があったらぜひ再チャレンジしてみてください。」 お世辞も入っているのかもしれないけど素直に嬉しい。 今回のフィードバックをもとにもっと成長していこうー!!

2025-03-11