「Debianセキュリティ勧告」発行までの対応作業の内側

こんにちは、やまねと申します。サイオステクノロジーでは、本security blogで主に執筆している面と同じ部署に所属しています。

私はDebianというLinuxディストリビューションのDeveloperの一員でもあるのですが、 つい先日にDebianでセキュリティ脆弱性バグのパッケージ更新対応をすることがありました。 あまり「Linuxディストリビューションでのセキュリティ勧告の発行までの対応作業と流れ」という話は(特に日本語では)目にすることがないので、 良い機会だと思いここに経過をメモしてみることにします。

普段あまり目にすることのない「ディストリビューションでの裏方作業」について、読み物として楽しんで頂ければ、 そして多少なりとも興味を持っていただいてあわよくば筆者がSoftware Design誌で隔月連載している「Debian Hot Topics」の読者になって頂ければ…と思っております(なお、手順は説明のため実際の流れと一部前後しているものがあります。あしからずご了承ください)。

今回のお題

今回の対象は「loofah」というRubyのライブラリです。

公式の説明に「Loofah is a general library for manipulating and transforming HTML/XML documents and fragments, built on top of Nokogiri. Loofah excels at HTML sanitization (XSS prevention). It includes some nice HTML sanitizers, which are based on HTML5lib's safelist, so it most likely won't make your codes less secure. (These statements have not been evaluated by Netexperts.)」 とあるように、XSS防止のサニタイズでの利用が目的で、RubyベースのWebアプリケーションで幅広く使われているようです。

未公開のセキュリティ脆弱性対応の場合

脆弱性が未公開の場合はディストリビューションでも一部関係者のみにメールすることでハンドリングされます。 一部関係者というのは、upstream開発者やバグ報告者に加え、Debianの場合は

  • セキュリティチームメンバー
  • 該当のパッケージメンテナ

などが居ます。

また、今回は「既にupstreamが修正公開済み」の問題だったのでやり取りや修正はPublicな場所で行っていますが、 これが一般公開前の問題の場合はPrivateなGitリポジトリを使う・やり取りのメールを暗号化する (特に検証のためのexploitコード情報などの場合は必須)など考慮すべきことが増えます。

既知のセキュリティ脆弱性対応の場合(今回)

既にUpstreamで問題が公開されている、あるいはCVE番号が割り振られている場合はDebian Security Tracker に情報が追加され、Debianセキュリティチームが問題をトラッキングできるようにします (Debian Security Trackerのデータは公開Gitリポジトリで管理されており、セキュリティチーム以外の開発者も編集可能となっており、筆者も編集したことがあります)。 加えて今回のようにセキュリティチームのメンバーがDebian BTS(Bug Tracking System)の該当パッケージにバグ登録することが多いようです。

筆者はDebianのRuby関連パッケージのメンテナチームである「Debian Ruby Extras Maintainers」の一員であったので、 自分がメンテナではないこのruby-loofahパッケージのバグレポートに気づきました。 そして、実は過去にも同じようにruby-loofahパッケージのセキュリティ脆弱性対応作業をしたことがあったのでバグレポートを覗くことにしました (簡単に直せるのであれば作業すればいいし、難しそうであればスルーするつもり)。

UpstreamのGitHubでの修正コミットを見たところ、脆弱性と修正の内容としては「一部のタグがXSSに利用できてしまうので『安全』としたタグ以外は弾く」というもので、以前に報告された脆弱性と基本的には同じで簡単なものでした。 違いは以前のリリースでは lib/loofah/html5/whitelist.rb での指定が、最新のリリースでは lib/loofah/html5/safelist.rb ファイルで見やすく許可するelement毎に1行ずつ記述しているところでした。以前は1行に複数のelementが列挙されていて視認性が悪く、修正できたかどうかもパッと判別できないのでいい変更ですね。

loofah 2.2.3の lib/loofah/html5/whitelist.rb より抜粋

  ACCEPTABLE_ELEMENTS = Set.new %w[a abbr acronym address area
  article aside audio b bdi bdo big blockquote br button canvas
  caption center cite code col colgroup command datalist dd del
  details dfn dir div dl dt em fieldset figcaption figure footer
  font form h1 h2 h3 h4 h5 h6 header hr i img input ins kbd label
  legend li main map mark menu meter nav ol output optgroup option p
  pre q s samp section select small span strike strong sub summary
  sup table tbody td textarea tfoot th thead time tr tt u ul var
  video]

loofah 2.3.1の lib/loofah/html5/safelist.rb より抜粋

  ACCEPTABLE_ELEMENTS = Set.new([
                                  "a",
                                  "abbr",
                                  "acronym",
                                  "address",
                                  "area",
                                  "article",
                                  "aside",
                                  "audio",
                                  "b",
                                  "bdi",
                                  "bdo",
                                  "big",
                                  "blockquote",
                                  "br",
                                  "button",
                                  "canvas",
                                  "caption",
                                 (中略)
                                  "table",
                                  "tbody",
                                  "td",
                                  "textarea",
                                  "tfoot",
                                  "th",
                                  "thead",
                                  "time",
                                  "tr",
                                  "tt",
                                  "u",
                                  "ul",
                                  "var",
                                  "video",
])

作業が簡単なもので済みそうなので、手を付けることにします。

「不安定版 (unstable)」および「テスト版 (testing)」への対応

まずは一番作業が楽な開発版である不安定版リポジトリ(Debian unstable)には最新リリースである2.3.1をほぼそのまま突っ込みました(完全にそのまま、ではないのは一部JSコードがminifyされたものでDebianのポリシーに従ってないためです。 ユーザーが実際に使うバイナリパッケージではminifyしてもOKですが、 ビルド前のソースパッケージではJavaScriptは人間が容易に読み書き修正できるminifyされていないものを同梱することを指定されています。 そのため、その様なファイルをexcludeしたものをソースパッケージとしてアップロードしています)。

$ git clone git@salsa.debian.org:ruby-team/ruby-loofah.git &&  cd ruby-loofah
$ gbp import-orig --uscan --pristinetar
(細かな変更とコミット)
$ gbp dch
$ dch -r
$ git commit -v debian/changelog
$ gbp buildpackage --git-pristine-tar --git-pbuider --git-pbuilder-options=”--source-only-changes” --git-tag
$ cd ../build-area/
$ dput ruby-loofah_2.3.1+dfsg-1_source.changes

内容を細かく説明すると以下となります。

  1. salsaからソースを取得(Debianでは開発にGitLabを利用していますが、そのホスト名が「salsa.debian.org」です)
  2. gbp (git-buildpackage) の import-orig サブコマンドでリリースされているupstreamのtarballを取得(--uscanオプションで debian/watch ファイルで指定されている upstream サイトをチェックして最新のリリースを取得、--pristine-tar オプションで pristine-tar ブランチに tarball をコミット指定)
  3. 諸々の変更作業…。
  4. gbp の dch サブコマンドで debian/changelog ファイルをテンプレートを利用して記述
  5. dch コマンドの -r オプションで unstable ディストリビューションに対してのリリースであることを明示
  6. 上記で変更した debian/changelog ファイルの変更をコミット
  7. gbp の buildpackage サブコマンドでパッケージをビルド。ビルドの際は pbuilder/cowbuilder を利用した chroot でのビルドであること、その際に「--source-only-changes」というオプションを指定すること、最後にビルドが成功したらgitリポジトリにタグを打つことを指定しています。
  8. ビルドしたファイルを配置するディレクトリに移動
  9. dput コマンドでDebianのリポジトリに生成したパッケージをアップロード

これで開発版であるDebian unstable、そしてそのパッケージがコピーされるDebian testingへの対処は終わりです。

「安定版」「旧安定版」への対応作業

次に、既にリリースされているDebian 安定版(stable)や旧安定版(oldstable)への対処とセキュリティ勧告の発行なのですが、 基本ポリシーとして「リリース時のバージョンはそのままでセキュリティ修正に必要な最小の変更だけをピックアップして適用(バックポート)」があります。 今回はバージョン2.3.1での変更点を2.2.3と2.0.5に適用する必要がありますが、先に述べたように2.3.1ではファイル名と指定の仕方が変わっているのでそれを踏まえて変更を行います。

--- ruby-loofah.orig/lib/loofah/html5/whitelist.rb
+++ ruby-loofah/lib/loofah/html5/whitelist.rb
@@ -88,7 +88,7 @@ module Loofah

       SVG_ATTRIBUTES = Set.new %w[accent-height accumulate additive alphabetic
        arabic-form ascent attributeName attributeType baseProfile bbox begin
-       by calcMode cap-height class clip-path clip-rule color
+       calcMode cap-height class clip-path clip-rule color
        color-interpolation-filters color-rendering content cx cy d dx
        dy descent display dur end fill fill-opacity fill-rule
        filterRes filterUnits font-family
@@ -105,9 +105,9 @@ module Loofah
        stemv stop-color stop-opacity strikethrough-position
        strikethrough-thickness stroke stroke-dasharray stroke-dashoffset
        stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity
-       stroke-width systemLanguage target text-anchor to transform type u1
+       stroke-width systemLanguage target text-anchor transform type u1
        u2 underline-position underline-thickness unicode unicode-range
-       units-per-em values version viewBox visibility width widths x
+       units-per-em version viewBox visibility width widths x
        x-height x1 x2 xlink:actuate xlink:arcrole xlink:href xlink:role
        xlink:show xlink:title xlink:type xml:base xml:lang xml:space xmlns
        xmlns:xlink y y1 y2 zoomAndPan]

非常に分かりづらいですがwhitelist.rbファイルで「by」「to」「values」のタグを許可しないようにしています。この変更を各リリースに対して適用します。

まずは旧安定版(oldstable)であるDebian9(コードネーム:stretch)について作業を実施しましょう。

$ git checkout debian/stretch
$ gbp pq import
(変更の適用作業を実施…)
$ git commit -av
$ gbp pq export
$ git add debian/patches && git commit -v
$ gbp dch
$ dch -r
(debian/changelog ファイルの変更)

debian/stretch ブランチで作業、gbp(git-buildpackage)の pq サブコマンドで debian/patches 以下にパッチファイルを生成し、 dch コマンドでテンプレートを呼び出した上でエディタを立ち上げて debian/changelog ファイルに作業内容を記述しています。

debian/changelog より抜粋

ruby-loofah (2.0.3-2+deb9u3) oldstable-security; urgency=high

* Team upload

* debian/patches
  - add 0005-Fix-CVE-2019-15587.patch (Closes: #942894)
    (CVE-2019-15587)

この際のポイントは debian/changelog ファイルでリリースターゲットディストリビューションが 「oldstable-security」であることを明示することと、バージョン番号の付け方が「+deb9u3」のように「debian9でのアップデート3回目」のようにすることです。 ここをキチンと記述しないとターゲットとするバージョンへのリリースとパッケージアップデートがうまくいかないことになります。

また、CVE番号が割り振られている場合はsecurity-trackerでどのバージョンで修正されたかを機械的にトラックできるようCVE番号を記載するのも忘れてはならないポイントです。

変更が済んだらパッケージビルドを実施します。

$ sudo pbuilder --create --basepath /var/cache/pbuilder/stertch.cow --distribution stretch
$ gbp buildpackage --git-pristine-tar --git-pbuider --git-pbuilder-options=”--basepath /var/cache/pbuilder/stertch.cow --source-only-changes” --git-tag

pbuilder コマンドでDebian9「stretch」のminimumなchroot環境(/var/cache/pbuilder/stertch.cow)を生成しておき、 gbpでのビルド時に利用を指定してビルドを行いました(なお、実際にはここで後ほど説明するDebian10向けの作業も実施しています)。

ビルドが出来たところでdiffを取り、レビューをしてもらうためにレポートへパッチファイルを添付してバグ報告者であるセキュリティチームのMoritz Muehlenhoffさんに返信しました。

control: tags -1 +patch +fixed-upstream

Hi,

> On Tue, 22 Oct 2019 23:35:39 +0200
> Moritz Muehlenhoff <jmm@debian.org> wrote:
> Package: ruby-loofah
> Severity: important
> Tags: security
> 
> Please see https://www.openwall.com/lists/oss-security/2019/10/22/1

 I've prepared patches for buster and stretch, just remove insecure
 tags as well as previous security update, please review it.

内容は非常に初歩的な英語ですね :-)(行頭はバグステータス変更のコントロールコマンドです)。

同日に早速Moritzさんから返信が届きました。

On Thu, Oct 24, 2019 at 08:03:33AM +0900, Hideki Yamane wrote:
> On Wed, 23 Oct 2019 21:26:36 +0900
> Hideki Yamane <henrich@iijmio-mail.jp> wrote:
> > +ruby-loofah (2.2.3-2) stable-security; urgency=high
> 
>  It should be
> 
> > +ruby-loofah (2.2.3-1+deb10u1) stable-security; urgency=high

 Ack, these look fine, with the change for the version number added,
 please upload to security-master.

 Cheers,
         Moritz

問題なさそう、ということで次のステップへ進みパッケージをアップロードしました。

$ cd ../build-area/
$ dput security-master ruby-loofah_2.0.3-2+deb9u3_source.changes

前回のような通常のパッケージアップロードと違うのは dput コマンドでのソースパッケージのアップロード時に通常のビルド処理キューではなく、セキュリティ修正専用の「security-master キュー」を指定しているところです。そのため、dputコマンド実行時には確認のメッセージが出てきたので「yes」と入力してアップロードを実施しました。

$ dput security-master ruby-loofah_2.0.3-2+deb9u3_source.changes
Uploading ruby-loofah using ftp to security-master (host: ftp.security.upload.debian.org; directory: /pub/SecurityUploadQueue)
running allowed-distribution: check whether a local profile permits uploads to the target distribution
running protected-distribution: warn before uploading to distributions where a special policy applies
Protected Checker: Are you sure to upload to oldstable-security? Did you coordinate with the Security Team before your upload? [yes, NO]: yes

同様に安定版(stable)であるDebian10(コードネーム:buster)についても対処を実施します。

$ git checkout -b debian/buster debian/2.3.1-1
$ gbp pq import
(変更の適用作業を実施…)
$ git commit -av
$ gbp pq export
$ git add debian/patches && git commit -v
$ gbp dch
$ dch -r
(debian/changelog ファイルの変更)

debian/changelog ファイルの変更時に今回は「stable-security」「deb10u1」と指定し、ビルドはDebian10(buster)のminimumなchroot環境(/var/cache/pbuilder/buster.cow)で実施します

$ sudo pbuilder --create --basepath /var/cache/pbuilder/buster.cow --distribution buster
$ gbp buildpackage --git-pristine-tar --git-pbuider --git-pbuilder-options=”--basepath /var/cache/pbuilder/buster.cow --source-only-changes” --git-tag
$ cd ../build-area/ && dput security-master ruby-loofah_2.2.3-1+deb10u1_source.changes

すると、ここでDebian10(buster)へのアップロードがrejectされた旨のメールが来ました。最初は驚きましたが、原因がDebianのビルドシステムの仕様に伴うもの(*)であることに気づき、対処して再ビルド&アップロードを無事実施しました。

※ stable-securityリポジトリにはビルドに必要なorig.tar.gzファイルがアップロードされていないためでした。 foobarのバージョン1.0をパッケージすると仮定すると、初回である1.0-1のアップロード時にはorig.tar.gzファイルを含めてソースをアップロードし、 次のアップロードである1.0-2では含めません。 ビルドサーバーは1.0-2では前回の1.0-1でアップロードしたorig.tar.gzファイルを参照してビルドします。 これは同じソースファイルを何度もアップロードしなくて済むのでアップロード時の若干の効率化を果たすと共に、 ソースtarballファイルが生成の度にchecksumが変わってしまいreproducibleではなくなるのを防ぐ目的があります。

$ gbp buildpackage --git-pristine-tar --git-pbuider --git-pbuilder-options=”--basepath /var/cache/pbuilder/buster.cow --source-only-changes --debbuildopts -sa” --git-tag
$ cd ../build-area/ && dput security-master ruby-loofah_2.2.3-1+deb10u1_source.changes --force

アップロードが無事完了すると、受け付けた旨のメールがchangelogのエントリに利用したメールアドレス宛に届きます。

Accepted:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Format: 1.8
Date: Wed, 23 Oct 2019 15:09:58 +0900
Source: ruby-loofah
Architecture: source
Version: 2.2.3-1+deb10u1
Distribution: stable-security
Urgency: high
Maintainer: Debian Ruby Extras Maintainers <pkg-ruby-extras-maintainers@lists.alioth.debian.org>
Changed-By: Hideki Yamane <henrich@debian.org>
Closes: 942894
Changes:
 ruby-loofah (2.2.3-1+deb10u1) stable-security; urgency=high
 .
   * Team upload
 .
   * debian/patches
     - add 0002-Fix-CVE-2019-15587.patch (Closes: #942894)
       (CVE-2019-15587)
Checksums-Sha1:
 6a88d1104448bc42a860cf7857ef933836ee3402 2226 ruby-loofah_2.2.3-1+deb10u1.dsc
 d4fd14de1fe1674639b21740e716decb00c2bae2 63626 ruby-loofah_2.2.3.orig.tar.gz
 2858162cad2553398b8c4451bacd0dc1597352a2 4648 ruby-loofah_2.2.3-1+deb10u1.debian.tar.xz
 1d9a501e90492fbb23af30333ee2d848aa3f529d 9031 ruby-loofah_2.2.3-1+deb10u1_amd64.buildinfo
Checksums-Sha256:
 cdff54ccde5083e9d213b572b052097eb32b9eab1ac9ce3b4a52ee093041e80b 2226 ruby-loofah_2.2.3-1+deb10u1.dsc
 522b20f21123e5275e620e6590f549acca442da34c647a1509fafb3248547a50 63626 ruby-loofah_2.2.3.orig.tar.gz
 5e2f6312ab8e3d53bdd508303cc667bb4ff366420e21c80dd405b5efcb39a416 4648 ruby-loofah_2.2.3-1+deb10u1.debian.tar.xz
 f2ad4621036d9b65fc97d7a3f5c09684cb79c8ffc43c07b88f1db28af4c5d6a9 9031 ruby-loofah_2.2.3-1+deb10u1_amd64.buildinfo
Files:
 04b251e6f6f53e9f910bea90ab561279 2226 ruby optional ruby-loofah_2.2.3-1+deb10u1.dsc
 57080866881ec74e76ae01ffa8bfec2e 63626 ruby optional ruby-loofah_2.2.3.orig.tar.gz
 7b5c6300037054ed5bc9265f5bfade00 4648 ruby optional ruby-loofah_2.2.3-1+deb10u1.debian.tar.xz
 d2ae371293d01b6c1dbc88550ff25d86 9031 ruby optional ruby-loofah_2.2.3-1+deb10u1_amd64.buildinfo

-----BEGIN PGP SIGNATURE-----

iQIzBAEBCgAdFiEEWOEiL5aWyIWjzRBMXTKNCCqqsUAFAl20U80ACgkQXTKNCCqq
sUA6sA/+Ohgl7xFcXA68kHToV8fTr4Kow8UWvHCLAKGpz4M6MpdaWI4MhbB2LBlW
guQnM3T9Niu9d1HXm6tReqiLVm7BO+SRSTixcdjYrEGs9DuXIwFW+tjAfRoDDdxq
839eQruTw6UO0rYYffTI6AfvnB8BhMMQOJgh3EUY6T8P6Y2g1S37RqIzaACQu/YB
K/P64Opt2Cm6PZzNjh9vbNYmLXqlZKlXPcCJ0xEnoQzTPumA7JthL1FEoNruXSld
RBjbCeUhz89PMSlreU6wNYPqCfMtGtPDDmQWd6ar4Dj9bib+1SVISorpj5TFZKS7
+ywCG9A5BqSS/MugxzT3XtYEPLxa6f6QUrUq/ke77pEAn3GbYFowpjgKe9B4myhp
G3d5JriZv0EKqwkxMnrOaNCn5B0XTCoCAX9tYqhK2HUTuyqpuyLpN+1HGuld11Uo
lvilz770OUP7lbbF90WqknSAK7jro8yynBN4ExQivUrNHHwHtQS70Bti7MbB00Gh
xpPCtEOYp8qFeub36lhWXXvOyFgNvU5atFFgqlD5RUb8/Bpj3ZgWw2PAjePUNgG1
SMBk5WoYf0ZjI5al16ync4/q2AahdGXlr26BZDvzuqRRzjPOjl55T1wqmXAs8vKY
uw9cSr5f7AiM0Xki4zHOUAco8r3LMnGKhv5/O3ln1M3c4MEXWsg=
=g+7c
-----END PGP SIGNATURE-----


Thank you for your contribution to Debian.

届いたメールのサブジェクトは「ruby-loofah2.2.3-1+deb10u1source.changes ACCEPTED into stable->embargoed」となっていました。 「embargoed」は一般ユーザーは目にすることがない特殊なリポジトリで、ビルドしたパッケージを一定期間秘匿するためのものとなっています (公式なドキュメント記載も無いので、開発者もこの様なセキュリティ修正を実施しない限り存在を知らないと思われます)。

Debianパッケージのビルドは複数のサポートバージョン・アーキテクチャに渡って行われるので全てが揃うまでに時間がかかり、 セキュリティ勧告の文面の準備も必要です。さらには未公開のセキュリティ脆弱性でDebian外の組織と協調して動く必要がある場合は公開タイミングを図らねばなりません。 このように関係者間で歩調を合わせて「いっせーのせ!」で公開を実施する目的のためにembargoedリポジトリが利用されます。

そしてセキュリティ勧告の発行へ

この後は筆者側で行う作業は何も無く、Debianセキュリティチームがセキュリティ勧告を公開するのを待ちます。 暫く待つと2019/10/29の日本時間早朝に無事DSA-4554-1として発行され、 security.debian.orgのリポジトリに修正パッケージがアップロードされてユーザーが取得できるようになりました。

また、その1時間後に「ruby-loofah2.2.3-1+deb10u1source.changes ACCEPTED into proposed-updates->stable-new, proposed-updates」 というサブジェクトのメールが届きました。 文面先頭に「Mapping stable-security to proposed-updates.」とあり、stable-securityリポジトリから次の安定版ポイントリリース(10.2) の候補リポジトリ(proposed-updates)にマッピングされたようです。 これで10.2からは別途セキュリティアップデート用リポジトリを指定しなくても修正されたパッケージが導入されるようになりました。

今回の対応と時間の流れ

10/22 13:09:upstreamで脆弱性対応情報の公開
      13:15:oss-securityメーリングリストでの脆弱性周知メール
      21:35:Debian BTSにバグ登録
10/23 12:26:BTSへ初回の返信
      23:03:BTSへ追加の返信
10/25 20:48:セキュリティチームから変更確認、アップロードのゴーサイン
10/26 13:21:Debian unstableへのアップロード
10/28 21:30:Debian 9および10への修正パッケージのアップロード
10/29 19:49:Debianセキュリティ勧告公開

※10/26の作業から間を置いて10/28夜に対応を行っているのは、単に日曜日は家族対応を、月曜日は業務を優先したからです :-)

前へ

sudoの脆弱性(CVE-2019-14287)が「ALL」が含まれる時だけ発生した理由

次へ

proftpdの複数の脆弱性情報(CVE-2019-19269, CVE-2019-19270, CVE-2019-19271, CVE-2019-19272)