mmash -h

Raspotifyでspotifyを最大限満喫&ラズパイ有効活用する

きっかけ

この度、スピーカーを自作しました。

よくBGMとしてspootifyをよく垂れ流しにしているのですが、これまで家で音楽を聴くときはヘッドホン派でした。

しかしこの真夏にヘッドホンをつけているとどうしても汗をかいてしまったり暑苦しいため、 スピーカーで聞けた方が便利なのでは?と思うようになりました。

このスピーカーの自作についてはそこまで難しいことをしているわけではなく、 横浜の秋葉原ことエジソンプラザにてスピーカーユニットや電線を買ってきて、 それをホームセンターで買ってきて組み立てた木の箱に取り付けただけです。

このスピーカーにはアンプがありませんから、 別途購入する必要があります。

そこで買ったのがこのアンプ。

ネットではちらほら買っている人も見かけます。

このアンプには、音声入力として3.5mm のジャックが用意されているので、 初めはspotifyがインストールされたipadiphoneを接続して、 スピーカーから音を出していました。

f:id:mmash:20200830171946p:plain:w500

しかしながら、途中から曲を流すのは別の端末で行いたいと考えました。 理由として、

  • 曲を変えたいときはたびに物理的にipadないしiphoneのところまで行かなければいけない
  • 曲を流しているときはipadiphoneが占有されてしまう

Raspotify

そんなときに発見したのがRaspotify

このRaspotifyは、Spotifyの機能であるConnectをRaspberry piでも使えるようにするソフトウェアです。

うちにちょうど余っているRaspberry piがあったので(だいたいRaspberry piって最初買って以降放置されてますよね) Raspotifyを使用してみることにしました。

完成後のイメージはこんな感じ。

曲の選択や音量調整は、いつも使い慣れたiPhone, iPadSpotifyのアプリから行います。

その際に再生デバイスRaspberry piに指定してやる、という具合です。

f:id:mmash:20200830171949p:plain:w500

こんな人へおすすめ

  • Spotifyを有料会員で使用している。
  • 家でもスピーカーでSpotifyの音楽をかける。ただしスピーカーの場所まで行かずに、いつも身に着けているスマホで操作したい。
  • 余っているRaspberry pi がある。

手順

手順といってもすべてはGitHubのREADMEに書かれている通りで、

curl -sL https://dtcooper.github.io/raspotify/install.sh | sh

をたたくと勝手にインストールしてくれます。

その後/etc/default/raspotifyに必要な設定を書き込む必要があります。

自分で有効にした設定はこんな感じ。

BITRATE="320"
OPTIONS="--username XXXXXXXX --password XXXXXXXX --device hw:1"

この--device hw:1の部分は、以下のコマンドでデバイスに対応する番号を拾ってきました。

$ cat /proc/asound/cards
 0 [b1             ]: bcm2835_hdmi - bcm2835 HDMI 1
                      bcm2835 HDMI 1
 1 [Headphones     ]: bcm2835_headphonbcm2835 Headphones - bcm2835 Headphones
                      bcm2835 Headphones

設定を書いたら、サービスを再起動。

sudo systemctl restart raspotify

iPhoneSpotifyで曲を再生すると、左下に再生するデバイスを選択できる部分があります。 f:id:mmash:20200830165759p:plain:w300

この中から、Raspotifyで再生するRaspberry piの名前を選択してあげればOK。

f:id:mmash:20200830165804p:plain:w300

SpotifyRaspberry piをフルに活用できて、かつ自作のスピーカーも役に立っているので、 個人的には非常に気に入っております。

今回はここまで。

ありがとうございました。

参考

Spotify Connect Connect - Spotify

【読書メモ】セッション管理

ユーザのセッションIDが攻撃者に知れ渡った場合、 攻撃者はユーザに成りすまして

  • 重要情報の閲覧
  • ユーザの権限で操作
  • ユーザアカウントでメール送信・ブログ投稿、設定変更等

を行うことができる。

攻撃者がセッションIDを知るための手段には、以下の三種類がある。

  • セッションIDの推測
  • セッションIDの盗み出し
  • セッションIDの固定化

セッションIDの推測

セッションIDの生成規則に不備があると、セッションIDを推測される恐れがある。

攻撃者から予測できてしまうようなセッションIDを使用せず、言語やミドルウエアが提供するセッション管理機構を利用することがそもそも脆弱性を作らない対策となる。

予想できてしまいそうなセッションID生成方法には、例えば以下をそのまま使用したり、エンコードしたり、ハッシュ値で利用したりする場合がある。

  • ユーザID、メールアドレス
  • リモートIPアドレス
  • 日時
  • 乱数

セッションIDの盗み出し

RefererによりセッションIDが漏洩するのは、以下の両方を満たしたサイト

  • URL埋め込みのセッションIDを使える
  • 外部サイトへのリンクがある、もしくはリンクを利用者が作成できる

ブログやSNS掲示板、Webメールなどが二つ目の条件に該当する。

セッションIDのURL埋め込みは、Refererヘッダを経由してセッションIDが外部に漏洩するので、禁止する。

php.iniにてセッションIDの設定項目が存在する

セッションIDの固定化

攻撃者の手順

  • セッションIDの入手
  • 被害者に対して、取得したセッションIDを強制する
  • 被害者が標的APPにログインする
  • 攻撃者は、被害者に強制したセッションIDを使って標的アプリケーションにログインする

セッションIDの固定化が可能となる原因

外部からセッションIDを強制できてしまう点にある。 それは。URL埋め込みのセッションIDをつかっていようが、クッキー埋め込みのセッションIDを使っていようが、関係ない。

セッションアダプション

PHPASP.NETに見られる、未知のセッションIDを受け入れる性質。 セッションアダプションの有無は、セッションIDの固定化攻撃の可否に関係ない。

セッションIDをクッキーに保存している場合のセッションIDの固定化

クッキーにセッションIDをセットしている場合でも、Webアプリケーションに以下の脆弱性があれば、攻撃者がクッキーにセッションIDをセット&強制することが可能となる。

セッションIDの固定化への対策

XSSやHTTPヘッダインジェクションなどの脆弱性を全部つぶしていくのは正直つらいので、以下のようなつくりを設計当初から盛り込んでいくのがいい。

  • Webアプリケーション側で、ログイン成功時にセッションIDを再生成する
  • セッションIDが再生成できない場合は、セッションIDと、ログイン時に発行したクッキーを併用する

【読書メモ】CSRF

例えば「パスワードを変更する」などの処理の場合、以下の条件を見大してユーザは無事にパスワードを変更することができる。

  • POSTメソッドでパスワード変更のページがリクエストされること
  • ログイン状態であること
  • POSTメソッドでデータ(この例ではパスワードに相当する値)が指定されていること

CSRFは、この条件を満たした状態のユーザにリクエストを送信させる。

XSSCSRFの違い

CSRFは、

  1. ユーザが罠ページの仕掛けのあるHTMLを閲覧する
  2. 攻撃用のリクエストを発行する
  3. サーバ側でサーバの用意した処理が行われる(正規の処理に見える)

このようにサーバにリクエストが到達し、リクエストに対応する処理が実行された時点で完結する。

これに対してXSSは、

  1. ユーザが罠ページの仕掛けのあるHTMLを閲覧する
  2. 攻撃用のリクエストを発行する
  3. サーバ側はリクエストを解釈してレスポンスを返す
  4. ユーザのブラウザで悪意のあるコードが実行される

のように、ブラウザまでレスポンスが帰ってきて、そこでコードがJSが実行されて攻撃が完結する。

なるほど、今まで違いがよくわからなかったけどようやくわかった

確認画面がある場合のCSRF

重要な処理の際に確認画面を設けても、CSRFは解消されない。

  • hidden パラメータで受け渡ししている場合
    • 処理実行画面でデータを受け取るので、確認画面がない場合と同じ
  • セッション変数にパラメータを格納している場合
    • 下記の数だけiframeを用意して、各々のiframeにリクエストを発行させる
      1. 確認画面に対してメールアドレスをPOSTして、セッション変数にデータをセット
      2. タイミングを見計らって実行画面を呼び出す

iframeが悪用されてるところしか見ない気がする

ファイルアップロードがある場合のCSRF

ファイルをアップロードするようなページでもPOSTデータの送信部分がファイルデータになるだけなので、CSRFが発生する。

  1. データの部分を例えばphpinfo()の結果にして、ターゲットサイトに実行させ、それをファイルとしてターゲットサイトがXMLHttpRequestを利用して自らのサイトにアップロードする
  2. ファイル名が予測できるようなものの場合、攻撃者がターゲットサイトにアップロードされたファイルを閲覧し、phpinfo()の結果が閲覧できる

CSRFが生まれる原因

以下のようなWebの性質に起因している。

  1. form要素のaction属性にはどのドメインのURLでも指定できる
  2. クッキーに保管されたセッションIDは、対象サイトに自動的に送信される

前者は、罠サイトからターゲットサイトへリクエストを送信できるということ。

後者は、罠経由のリクエストに対しても、セッションIDのクッキー値が送信されるので、認証された状態で攻撃リクエストが送信されるということ。

正規のリクエストと、CSRFのリクエストを比べてみると、Refererヘッダしか違いがない

対策

  • CSRF対策の必要なページを区別する
    • ページ遷移図を作成して、外部からリンクを張られてもいい場所か、張られたくない場所かで区別する
    • 外部からリンクを張られたくない場所に対してCSRF対策をする
  • 正規利用者の意図したリクエストを確認できるように実装する
    • 秘密情報の埋め込み
    • パスワード再入力
      • 正規利用者であることを再確認する
    • Refererのチェック
      • 正規サイトがRefererに指定されていれば正規のリクエストと判断
      • ブラウザでRefererを送らない設定にしている場合も多い

保険

パスワード変更や、物品購入に対して、メールを送信することで被害にいち早く気付けるようにする

【読書メモ】SQLインジェクション

SQLインジェクションを使った攻撃手法

DVWAで少しやったけど、そのときはID/PWを表示するとかだった。思えば、無限に出来ることあるのね。

  • エラーメッセージにDBの機密情報を含めて表示させる
  • UNION SELECTを用いて任意のSQL文の結果を取得する
  • ログイン認証を回避する
    • ' OR 'a'='a
  • DB内の任意のデータ書き換え
    • UPDATE TTT SET ccc='new word' WHERE id = 'kkk' --
  • OSコマンド実行
  • ファイル読み出し(/etc/passwdなど)
    • LOAD DATA INFILE '/etc/passwd' INTO TABLE TTT(ccc)' ---
  • ファイル書き出し
  • HTTPリクエストによりほかのサーバを攻撃

DB内の表明・列名の調査

どんなDB・テーブルがあるのかはここを見ると手っ取り早いと。

  • INFORMATION_SCHEMA
    • columns
    • tables

SQLインジェクションを生まないための対策

静的プレースホルダ

プレースホルダがついたSQL文がそのままDBエンジンに送られ、コンパイル等されてSQL文が確定したのち、DBエンジンで値をバインドする。 原理的にSQLインジェクションの可能性がない。

動的プレースホルダ

SQLを呼び出すアプリケーションのありぶらり内で、パラメータをバインドしてからDBエンジンに送る。 実装が不適切だった場合、SQLインジェクションが発生すr場合がある。

SQL文を動的に構築したい

ユーザが入力した検索条件のみで検索したい(=ユーザが入力した検索条件だけでSQL文を組み立てて、実行したい)

プレースホルダ記号「?」を含んだSQL文を各検索条件に対して作り、それを文字連結して最終的に一つのSQL文にする。

やっぱりこういう方法になっちゃうのは仕方ないのか。検索条件が多いと大変そうだけど。

ユーザの選択によってさまざまな列でソートしたい

array_search関数で正当な列名であることを確認したのち、ORDER BY句を組み立てる

SQLインジェクションを防ぐ保険的な対策

  • 詳細なエラーメッセージを抑止する
    • php.inidisplay_errors=off
  • アプリケーション要件に沿った入力値検証
    • 郵便番号であれば数字のみ、ユーザIDであれば英数字、記号なしなど
  • データベースの権限設定
    • DBユーザに最小限の権限を与えることで、DB/テーブルへの読み出し・書き込みに対する制限を行ったり、FILE権限の制限によってファイル読み込みを防ぐ

入力値検証は大事だけど実装漏れとかがありそう。一つ目とか三つ目をまずちゃんとやるのが大事かな。

なるべく実装でセキュリティを担保せずに、フレームワークやライブラリに任せるのが1番いい

【読書メモ】同一オリジンポリシー

同一オリジンポリシーについて

受動的攻撃と能動的攻撃

  • 受動的攻撃
    • Webサイトの利用者に対して罠を仕掛け、罠を閲覧したユーザを介してアプリケーションを攻撃する手法
  • 能動的攻撃
    • 攻撃者が直接Webサーバに対して攻撃する手法

同一オリジンポリシー

同一オリジンポリシー - ウェブセキュリティ | MDNには、以下のように説明されている。

同一オリジンポリシーとは、あるオリジンから読み込まれた文書やスクリプトについて、そのリソースから他のオリジンのリソースにアクセスできないように制限するものです。 同一オリジンポリシーはウェブのセキュリティにおける重要な仕組みであり、悪意ある行動を起こしかねないリソースの分離を目的としています。

同一オリジンである条件は、

  • FQDNが一致している
  • スキーム(プロトコル)が一致している
  • ポート番号が一致している

iframe内の情報へアクセスする実験

アプリケーションに脆弱性がある場合

ブラウザは同一オリジンポリシーにより受動的攻撃を防止しているが、アプリケーションに脆弱性が存在すると、受動的攻撃を受ける場合がある。その代表がXSS

XSSは悪意のある攻撃者によってJavaScriptが実行される例だが、意図的に第三者が、アクセス解析、バナー広告、ブログパーツの設置のためにJavaScriptを埋め込む場合もある。

しかしながら実際には、

といった被害をうけることもある。

クロスドメインアクセスが許可されているもの

  • iframe
  • img
  • script
  • css
  • form要素のaction属性

CORS(Cross Origin Resource Sharing)

オリジン間リソース共有 (CORS) - HTTP | MDNより

オリジン間リソース共有 (CORS) は、追加の HTTP ヘッダーを使用して、あるオリジンで動作しているウェブアプリケーションに、異なるオリジンにある選択されたリソースへのアクセス権を与えるようブラウザーに指示するための仕組みです。 ウェブアプリケーションは、自分とは異なるオリジン (ドメインプロトコル、ポート番号) にあるリソースをリクエストするとき、オリジン間 HTTP リクエストを実行します。

Access-Control-Allow-Originレスポンスヘッダ

Access-Control-Allow-Origin - HTTP | MDNより

Access-Control-Allow-Origin レスポンスヘッダーは、指定されたオリジンからのリクエストを行うコードでレスポンスが共有できるかどうかを示します。

異なるオリジンにHTTPリクエストを送ることができるケース(単純リクエスト)

  • メソッド
    • GET
    • HEAD
    • POST
  • リクエストヘッダ
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type
  • Content-Type
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

プリフライトリクエス

上記の場合に当てはまらない場合、ブラウザが送信するリクエス

始めに OPTIONS メソッドによる HTTP リクエストを他のドメインにあるリソースに向けて送り、実際のリクエストを送信しても安全かどうかを確かめます。 サイト間リクエストがユーザーデータに影響を与える可能性があるような場合に、このようにプリフライトを行います。

クロスオリジンに対する認証情報の送信

デフォルトではクロスオリジンに対してHTTP認証やクッキーなどの認証に用いられる情報は自動的には送信されない。 これを送信するには、

  • 呼び出し元オリジンでのXMLHttpRequestwithCredenialsプロパティをTrueにする
  • 呼び出される側のレスポンスでAccess-Control-Allw-CredentialsをTrueにする

【読書メモ】Webセキュリティの基礎

こちらの本でWebアプリケーションのセキュリティについて勉強中。 きれいにまとまってないただのメモです。

Connectionヘッダ

HTTPの通信が終わった後も、TCP接続を張ったままにするかどうかを制御する。"keep-alive"であればコネクションは閉じられないし、closeであれば閉じられる。

X-UA-Compatibleレスポンスヘッダ

新しいブラウザのバージョンで表示した際に見た目が崩れてしまうのを防ぐために、「ブラウザのこのバージョンで表示して」と指定するもの。

Refererリクエストヘッダ

いまからリクエストするページが、もとはどのページ(URL)から飛んでいるのかをサーバに伝えるもの。 しかしこのRefererにいれるURLの文字列中に、機密情報がパラメータとして埋め込まれてることがあり、しばし問題に。 逆に言うと、URL中に機密情報は含めてはいけない。Refererヘッダから漏洩したり、アクセスログに残るから。

GetメソッドとPostメソッドの使い分け

  • Getはリソースの参照のみ
  • Getには副作用がないこと
  • 機密情報の送信にはPost

Upgrade-Insecure-Requests

もしクライアント、サーバともにHTTPS通信が可能であれば、HTTPSにリダイレクトする。

Varyレスポンスヘッダ

Vary: User-Agentのときは、クライアントの種類によってキャッシュされたページを提供するのかサーバのオリジナルページを提供するのか制御する。 Vary: Accept-Encodingのときは、

hiddenパラメータ

HTTPはステートレスなので、もしページ間遷移で状態を保持したい(変数を保持したい)場合は、HTML内のhiddenパラメータが使える。

クッキーとセッション

サーバからクライアント(ブラウザ)へ、特定の「変数名=値」の組を覚えておくように指示される。例えば、PHPSESSID=(セッションID)をブラウザで覚えることで、セッションが有効な間は毎度このクッキーを送信することで状態を管理できる。 しかしながら、

  • クッキーが保持できる値の個数や文字列長には制限がある
  • クッキーの値は利用者本人が参照・変更できるので、秘密情報の格納には向かない

ので、実際にはセッションIDを各クライアントの「整理番号」として渡して置き、実際はサーバで値を保持することが多い。

セッションIDを発行する際には、

  • 三者からセッションIDを推測されないこと
  • 三者からセッションIDを強制されないこと
  • 三者にセッションIDが漏洩しないこと

に注意する必要がある。

とりあえず、自分でWebアプリケーションを作る際は、セッション管理機構は自作しないでフレームワークに任せるべき部分。

クッキーの属性

種類 役割
Domain ここで指定されたドメインにのみこのクッキーを送信する。サーバは、違うドメインをDomain属性に設定できない。Domainを設定しなければ、クッキーを生成したサーバのドメインのみにクッキーを送信
Path このURLのディレクトリにのみこのクッキーを送信する。
Expires このクッキーが有効な期限。なければブラウザ終了時まで。
Secure HTTPSの場合のみこのクッキーを送信する。
HttpOnly このクッキーへJSからはアクセスできない。

クッキーモンスターバグ

example.co.jpのサイトが、co.jpのクッキーを生成できてしまう問題。ブラウザからXXX.co.jpドメインすべてにクッキーを送信するようになる。ブラウザのバグが原因。

「ptrace入門: ptraceの使い方」を呼んだ

休日にAmazonの技術書ページをぼーっと眺めていた見た時に見つけた。

ptrace入門: ptraceの使い方

ptrace入門: ptraceの使い方

この本をポチったのは、「OSやカーネルにもっと強くなりたい」というのがきっかけだった。

詳解 Linuxカーネル 第3版」を片手にカーネルのソースリーディングしたりとか カーネルのネットワークスタックを追っかけるようなことがしたいけど いかんせんOSやカーネルの知識が浅い。

そこでこの本のKindle版を購入して呼んでみた。

ちなみにこの本は大学の授業で配布する資料をベースに作られていて、説明とともに一部コードが含まれていたり、授業の課題も含まれているので、 実際に読者が手を動かしながら理解していくことも可能になっている。

すこし敷居が高く感じていて手を出しづらかったカーネルシステムコール、シグナルの話を、 実際にプロセスを追跡するプログラム(トレーサ)を作成しながら理解を進めることができる。

システムコールを追いかけるstraceコマンドに似たようなものを自分の手で作り上げることができ、 今まであった苦手感はすこし解消されていた。

あまりページ数も多くない(149ページ)ので、2日もあれば手を動かしながら読み進めることができると思う。

こういうのって、読み終えるまでに長時間かかるとダメなタイプなので、このくらいの分量なのに自分でなにかモノを作れるというのは非常にうれしい。

自分のようにカーネルやOSにエントリーレベルの人には、ちょうどいい本だと思うのでぜひ。