WebDAV時代のセキュリティ対策[前編]


WebDAV時代のセキュリティ対策[前編]
各メソッドに内在する脅威

WebDAVはWebの利便性を大きく向上させる可能性を持っている。しかし、高機能化はセキュリティホールの原因ともなる。どこにどのような危険性があるのかを正しく認識・対処することで、利便性と安全性を両立していかなければならない。そこで、WebDAVを使ううえで必須ともいえるセキュリティ対策方法を紹介する。

WebDAVの特徴と機能

 次世代プロトコルWebDAVの可能性で、WebDAVの技術仕様と構築・運用方法について解説しました。そのときに説明したとおり、WebDAVはHTTPを読むだけのプロトコルから書くこともできるプロトコルへと拡張したものです。その主な機能をあらためて振り返ると、

といったものが挙げられます。見てのとおり、ファイル操作に必要とされる機能が拡張されていることが分かります。この機能を何の制限もなく公開することは、「データを壊してください」というに等しい行為です。とはいえ、機能として便利なものがそろっているのも事実です。適切な制限をかけたうえで利用すれば、その威力は絶大なものとなります。

 本稿では、Apache 1.3.22+mod_dav-1.0.3(2001年11月28日時点の最新版)の組み合わせを例に、制限をかけない(もしくは破られた)際の影響とその対策について、各メソッドの機能とともに説明します。

 検証用クライアント環境としては、基本的にはtelnetによる80番ポートの接続を用いていますが、検証結果を分かりやすくするため必要に応じてWebフォルダ、SkunkDAV、cadaver(編注)などを使っています。

編注
Webフォルダ:Windows 98 SE以降およびWindows 2000から標準実装されているWebDAVクライアント機能(Windows 95やWindows NT 4.0などもIE 5.xをインストールすれば利用可能)
SkunkDAV:Java製WebDAVクライアント
cadaver:UNIX系OS用CUIベースのWebDAVクライアント
詳しくは「WebDAVクライアント/サーバ環境の構築」参照。

メソッドとステータスコードから見るセキュリティホール

 各メソッドの詳細に入る前に、WebDAVに関連するメソッドやステータスコードを概観しておきましょう。メソッドやステータスコードにはどのような種類があり、どのような危険性があるのかを大まかにつかんでおけば、後述する詳細も理解しやすいでしょう。

 まず、表1にメソッド、表2にステータスコードの種類を示します。

メソッド
機能
PROPFIND プロパティの取得
PROPPATCH プロパティの変更
MKCOL コレクションの作成
COPY コレクションを含むリソースおよびプロパティの複製
MOVE コレクションを含むリソースの移動
LOCK コレクションを含むリソースのロック
UNLOCK コレクションを含むリソースのロック解除
OPTIONS 既存のメソッドと同じ
GET 既存のメソッドと同じ
HEAD 既存のメソッドと同じ
POST 既存のメソッドと同じ
PUT リソースの作成
DELETE コレクションおよびそのコレクションに含まれるリソースの削除
表1 WebDAV関連メソッド

ステータス
意味
102 Processing リクエストは受け付けたが、まだ処理が終わっていない
207 Multi-Status 複数のステータスを持つ
422 Unprocessible Entity リクエストの書式は正しいが、その内容が間違っている
423 Locked リソースはロックされている
424 Failed Dependency あるリクエストに関連したリクエストが失敗したため、依存関係が保てない
507 Insufficient Storage 記憶領域が不足している
200 OK PROPPATCHが成功した(PROPPATCH)
201 Created リソース/コレクションが作成された(MKCOL、PUT)
コピーが成功(コピー先は新規作成)した(COPY)
移動が成功(移動先のリソースなどは新規作成)した(MOVE)
204 No Content リソース/コレクションの削除が成功した(DELETE)
コピーが成功(コピー先は既存のリソース)した(COPY)
移動が成功(移動先のリソースなどは既存)した(MOVE)
ロックが解除された(UNLOCK)
400 Bad Request ロック解除時に指定したロックトークンが不正なものだった(UNLOCK)
403 Forbidden サーバ側の設定で、コレクションの作成を許していない(MKCOL)
認証設定などで、許可されていないURL下にコレクションを作成しようとした(MKCOL)
コピー元とコピー先が同一(COPY)
何らかの理由でプロパティを変更できなかった(PROPPATCH)
移動元と移動先が同一(MOVE)
404 Not Found プロパティが見つからない(PROPFIND)
405 Method Not Allowed すでに存在する名前のコレクションを作ろうとした(MKCOL)
409 Conflict 読み取り専用など、変更できないプロパティを変更しようとした(PROPPATCH)
存在しないコレクションの下にリソースやコレクションを作ろうとした(MKCOL、PUT、COPY、MOVE)
例:http://localhost/DAV/の下にDAV2というコレクションがない状態でhttp://localhost/DAV/DAV2/DAV3を作ろうとした
412 Precondition Failed 指定したリソースがロック可能な状態ではないか、サーバがlockinfo XMLエレメントの要求を満足できなかった
プロパティの内容を保持できなかった、もしくはOverwriteヘッダの値がFである(COPY、MOVE)
415 Unsupported Media Type MKCOLのリクエストボディが受け付けられないものだった(MKCOL)
502 Bad Gateway コピー/移動先が別サーバであり、かつリソースへのアクセスができない(COPY、MOVE)
表2 新設/拡張されたステータスコード

 表2の中で、注意すべきステータスコードと考えられるセキュリティ上の脅威を表3に示します。

ステータス
メソッド
意味
想定される脅威
102 Processing COPYなど リクエストは受け付けたが、まだ処理が終わっていない 処理時間のかかるリクエストが発行される(DoS)
207 Multi-Status
-
複数のステータスを持つ ステータスの1つに、脅威となるステータスが含まれる
423 Locked LOCK リソースはロックされている 勝手にリソースがロックされる(DoS)
507 Insufficient Storage COPY、PUT 記憶領域が不足している 不正に記憶領域を使用される(DoS)
200 OK PROPPATCH PROPPATCHが成功した リソースのプロパティが改ざんされる(破壊)
201 Created MKCOL、PUT リソース/コレクションが作成された リソースが不正に作成される(不正利用)
COPY コピーが成功した(コピー先は新規作成) リソースが不正に作成される(不正利用)
MOVE 移動が成功した(移動先のリソースなどは新規作成) リソースの位置が不正に移動される(改ざん)
204 No Content DELETE リソース/コレクションの削除が成功した リソースが破壊される(破壊)
COPY コピーが成功した(コピー先は既存のリソース) コピー先のリソースが破壊される(破壊)
MOVE 移動が成功した(移動先のリソースなどは既存) 移動先のリソースが破壊される(破壊)
UNLOCK ロックを解除された 不正にロックが解除される(改ざん)
表3 注目すべきステータスコード

 また、表3には含まれませんが注意すべきメソッドとして、リソース/コレクションのプロパティの取得を行う「PROPFIND」があります。

 表3のステータスコードの大半はWebDAVで新規に追加されたメソッドに対するものですが、PUTなど一部既存のメソッドに関するものも含まれます。このように、従来のメソッドも拡張が施されていますので、新旧に関係なくあらためてメソッドの動きを見直した方がよいでしょう。

各メソッドに内在する脅威と対策

 ここから、メソッドごとに脅威となり得る点とその対策方法を詳述していきます。本稿ではApacheのディレクティブで制限する方法を挙げておきますが、ほかのWebサーバでも同様のポリシーによって防御可能()です。

:バグなどで防御できない場合はこの限りではありませんが……。

PROPFINDメソッド

脅威:

 例えば、Webフォルダによるファイル一覧(画面1)はPROPFINDメソッドをコレクションに対して発行し、結果を取得しています。リスト1は、その際のパケットキャプチャの結果です。

画面1 Webフォルダによるファイル一覧(画像をクリックすると拡大表示します)

#######
T 10.1.87.156:1896 -> 10.1.87.157:80 [AP]    ←PROPFINDリクエスト
 PROPFIND /davnoauth HTTP/1.1..Accept-Language: ja, en-us;q=0.2..Conten
 t-Type: text/xml..Translate: f..Content-Length: 380..Depth: 1..User-Ag
 ent: Microsoft Data Access Internet Publishing Provider DAV 1.1..Host:
  tripmachine..Connection: Keep-Alive....<?xml version="1.0" ?>..<propf
 ind xmlns="DAV:">..<prop>..<name/>..<parentname/>..<href/>..<ishidden/
 >..<iscollection/>..<isreadonly/>..<getcontenttype/>..<contentclass/>.
 (中略)
##
T 10.1.87.157:80 -> 10.1.87.156:1896 [A]     ←PROPFIND結果
 HTTP/1.1 207 Multi-Status..Date: Wed, 28 Nov 2001 09:36:49 GMT..Server
 : Apache/1.3.22 (Unix) DAV/1.0.3..Keep-Alive: timeout=15, max=100..Con
 nection: Keep-Alive..Transfer-Encoding: chunked..Content-Type: text/xm
 l; charset="utf-8"....f13..<?xml version="1.0" encoding="utf-8"?>.<D:m
 ultistatus xmlns:D="DAV:">.<D:response xmlns:i0="DAV:" xmlns:lp0="DAV:
 " xmlns:lp1="http://apache.org/dav/props/">.<D:href>/davnoauth/DAVSec.
 txt</D:href>.<D:propstat>.<D:prop>.<D:getcontenttype>text/plain</D:get
 contenttype>.<lp0:creationdate xmlns:b="urn:uuid:c2f41010-65b3-11d1-a2
 9f-00aa00c14882/" b:dt="dateTime.tz">2001-11-28T08:55:14Z</lp0:creatio
 ndate>.<lp0:getlastmodified xmlns:b="urn:uuid:c2f41010-65b3-11d1-a29f-
 00aa00c14882/" b:dt="dateTime.rfc1123">Wed, 28 Nov 2001 08:55:14 GMT</
 lp0:getlastmodified>.<lp0:getcontentlength>7533</lp0:getcontentlength>
 .<D:resourcetype/>.</D:prop>.<D:status>HTTP/1.1 200 OK</D:status>.</D:
 propstat>.<D:propstat>.<D:prop>.<i0:name/>.<i0:parentname/>.<i0:href/>
 .<i0:ishidden/>.<i0:iscollection/>.<i0:isreadonly/>.<i0:contentclass/>
 .<i0:getcontentlanguage/>.<i0:lastaccessed/>.<i0:isstructureddocument/
 >.<i0:defaultdocument/>.<i0:displayname/>.<i0:isroot/>.</D:prop>.<D:st
 atus>HTTP/1.1 404 Not Found</D:status>.</D:propstat>.</D:response>.<D:
 response xmlns:i0="DAV:" xmlns:lp0="DAV:" xmlns:lp1="http://apache.org
 /dav/props/">.<D:href>/davnoauth/FIG.txt~</D:href>.<D:propstat>.<D:pro
 p>.<lp0:creationdate xmlns:b="urn:uuid:c2f41010-65b3-11d1-a2
(以下略)
リスト1 Webフォルダ表示時のパケットキャプチャの様子

 通常のWebブラウザでも、Apacheの設定によってはGETリクエストの結果としてディレクトリの内容が分かる場合があります(画面2)が、

などしておけば、これを防ぐことができます。詳しくはApacheによるWebサーバ構築 第7回の最後を参照してください。

画面2 Apacheの設定によってはディレクトリ構造が見えてしまう

 しかし、PROPFINDメソッドはそもそも「コレクションのプロパティ」を取得することによってコレクションに含まれるリソースを確認するため、上記の対策では防げません。

対策:

 具体的には、httpd.confでPROPFINDメソッドの実行を制限したい場所(例では/davauth)をリスト2のように設定して、Limitディレクティブで指定したメソッド(ここではPROPFIND)が使われた場合は認証を求めるようにします。

<Location /davauth>
        DAV     on
        AuthUserFile     /home/kmiya/htpwd/user.pwd
        AuthGroupFile    /dev/null
        AuthName         DAVhome
        AuthType         Basic
<Limit PROPFIND>
            Require user wakatono
        </Limit>
</Location>
リスト2 制限の実際の設定例

 上記の設定を施しておくことで、リスト3のようなレスポンスがWebブラウザに対して返却されます。正しい認証情報を与えない限り、不正にアクセスされることはありません。

##
T 10.1.87.157:80 -> 10.1.87.156:2114 [AP]
 HTTP/1.1 401 Authorization Required..Date: Wed, 28 Nov 2001 11:40:55 G
 MT..Server: Apache/1.3.22 (Unix) DAV/1.0.3..WWW-Authenticate: Basic re
 alm="DAVhome"..Keep-Alive: timeout=15, max=100..Connection: Keep-Alive
 ..Transfer-Encoding: chunked..Content-Type: text/html; charset=iso-885
 9-1....1e8..<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">.<HTML><
 HEAD>.<TITLE>401 Authorization Required</TITLE>.</HEAD><BODY>.<H1>Auth
 orization Required</H1>.This server could not verify that you.are auth
 orized to access the document.requested.  Either you supplied the wron
 g.credentials (e.g., bad password), or your.browser doesn't understand
  how to supply.the credentials required.<P>.<HR>.<ADDRESS>Apache/1.3.2
 2 Server at tripmachine.ts.u.coe.nttdata.co.jp Port 80</ADDRESS>.</BOD
 Y></HTML>...0....
リスト3 制限を施した場合のパケットキャプチャリングの様子 

MKCOLメソッド

脅威:

 実際に、ポート80に対してtelnetで接続した場合の実行例と、作成されたコレクションに対応してディレクトリができている様子をリスト4に示します。

Connected to localhost.localdomain.
Escape character is '^]'.
MKCOL /davnoauth/sample HTTP/1.0 ←コレクション作成リクエスト

HTTP/1.1 201 Created              ←作成された旨レスポンスが返る
Date: Wed, 28 Nov 2001 11:46:13 GMT
Server: Apache/1.3.22 (Unix) DAV/1.0.3
Connection: close
Content-Type: text/html

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>201 Created</TITLE>        ←作成された旨レスポンスが返る
</HEAD><BODY>                     ←作成された旨レスポンスが返る
<H1>Created</H1>                  ←作成された旨レスポンスが返る
Collection /davnoauth/sample has been created. ←作成された旨レスポンスが返る
<P><HR>
<ADDRESS>Apache/1.3.22 Server at tripmachine.ts.u.coe.nttdata.co.jp
 Port 80</ADDRESS>
</BODY></HTML>
Connection closed by foreign host.
$
$ ls -l /home/davnoauth/
total 56
-rw-r-----   1 share   share      7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share   share      7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share   share     13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share   share      1155 Nov 28 17:55 FIG.txt
-rw-r-----   1 share   share       284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share   share     14821 Nov 28 17:55 davsec20011126.lzh
drwxr-x---   2 share   share        48 Nov 28 20:46 sample/ ←ディレクトリが作成されている
$
リスト4 MKCOLメソッドによるコレクション作成の様子 

対策:

COPYメソッド

脅威:

$ ls -l /home/davnoauth/
total 56
-rw-r-----   1 share   share     7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share   share     7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share   share    13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share   share     1155 Nov 28 17:55 FIG.txt
-rw-r-----   1 share   share      284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share   share    14821 Nov 28 17:55 davsec20011126.lzh
drwxr-x---   2 share   share       48 Nov 28 20:46 sample/
$ telnet localhost 80
(中略)
COPY /davnoauth/FIG.txt HTTP/1.1     ←コピー元指定
Accept-Language: ja, en-us;q=0.2
Destination: http://tripmachine/davnoauth/davsec20011126.lzh ←コピー先指定
Overwrite: T              ←上書き許可
Depth: infinity
Translate: f
User-Agent: Mage Hoge DAV 1.1
Host: tripmachine
Content-Length: 0
Connection: Keep-Alive

HTTP/1.1 204 No Content          ←レスポンス開始(成功)
Date: Wed, 28 Nov 2001 12:16:32 GMT
Server: Apache/1.3.22 (Unix) DAV/1.0.3
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/plain
                      ←レスポンス終了
Connection closed by foreign host.
$ ls -l /home/davnoauth/         ←その後どうなったか
total 44
-rw-r-----   1 share  share     7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share  share     7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share  share    13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share  share     1155 Nov 28 17:55 FIG.txt ←コピー元
-rw-r-----   1 share  share      284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share  share     1155 Nov 28 21:16 davsec20011126.lzh ←コピー先(コピー元の内容で上書きされた)
drwxr-x---   2 share  share       48 Nov 28 20:46 sample/
$
リスト5 リソースの上書きによる破壊

$ telnet localhost 80
(中略)
COPY /davnoauth/DAVSec_.lzh HTTP/1.1 ←コピー元指定
Accept-Language: ja, en-us;q=0.2
Destination: http://tripmachine/davnoauth/DAVSecure1.lzh ←コピー先指定
Overwrite: F
Depth: infinity
Translate: f
User-Agent: Mage Hoge DAV 1.1
Host: tripmachine
Content-Length: 0
Connection: Keep-Alive        ←リクエスト終了
                  
←空行(リターン)挿入
HTTP/1.1 201 Created         ←レスポンス開始
Date: Wed, 28 Nov 2001 12:02:57 GMT
Server: Apache/1.3.22 (Unix) DAV/1.0.3
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: text/html


11f
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>201 Created</TITLE>
</HEAD><BODY>
<H1>Created</H1>
Destination /davnoauth/DAVSecure1.lzh has been created.
<P><HR>
<ADDRESS>Apache/1.3.22 Server at tripmachine.ts.u.coe.nttdata.co.jp
 Port 80</ADDRESS>
</BODY></HTML>

0
                   ←レスポンス終了
COPY /davnoauth/DAVSec_.lzh HTTP/1.1 ←コピー元指定
Accept-Language: ja, en-us;q=0.2
Destination: http://tripmachine/davnoauth/DAVSecure2.lzh ←コピー先指定
Overwrite: F
Depth: infinity
Translate: f
User-Agent: Mage Hoge DAV 1.1
Host: tripmachine
Content-Length: 0
Connection: Keep-Alive        ←リクエスト終了
                 
←空行(リターン)挿入
HTTP/1.1 201 Created         ←レスポンス開始
(中略)
Content-Type: text/html

11f
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
(中略)
</BODY></HTML>

0
                   ←レスポンス終了
COPY /davnoauth/DAVSec_.lzh HTTP/1.1 ←コピー元指定
Accept-Language: ja, en-us;q=0.2
Destination: http://tripmachine/davnoauth/DAVSecure3.lzh ←コピー先指定
Overwrite: F
Depth: infinity
Translate: f
User-Agent: Mage Hoge DAV 1.1
Host: tripmachine
Content-Length: 0
Connection: Keep-Alive        ←リクエスト終了
                  
←空行(リターン)挿入
HTTP/1.1 201 Created         ←レスポンス開始
(中略)
Content-Type: text/html

11f
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
(中略)
</BODY></HTML>

0
                   ←レスポンス終了
Connection closed by foreign host.  ←タイムアウト
$
$ ls -l /home/davnoauth/       ←実際のディレクトリを見る
total 104
-rw-r-----   1 share   share     7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share   share     7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share   share    13880 Nov 28 17:55 DAVSec_.lzh ←コピー元
-rw-r-----   1 share   share    13880 Nov 28 21:03 DAVSecure1.lzh ←コピー先1
-rw-r-----   1 share   share    13880 Nov 28 21:03 DAVSecure2.lzh ←コピー先2
-rw-r-----   1 share   share    13880 Nov 28 21:03 DAVSecure3.lzh ←コピー先3
-rw-r-----   1 share   share     1155 Nov 28 17:55 FIG.txt
-rw-r-----   1 share   share      284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share   share    14821 Nov 28 17:55 davsec20011126.lzh
drwxr-x---   2 share   share       48 Nov 28 20:46 sample/
$
リスト6 COPYメソッドの繰り返しによるディスクフルの再現

 ほかにも、リソース名やコレクション名を変更されてしまうことで、コンテンツの依存関係が崩されるといった事態も考えられます。

対策:

補足:mod_dav-1.0.3-1.3.6で、クォータ制限にひっかかってコピーできない場合でもステータスコード507 Insufficient Storageを返すようになりました。

MOVEメソッド

脅威:

$ ls -l /home/davnoauth/     ←元の状態は?
total 56
-rw-r-----   1 share   share     7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share   share     7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share   share    13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share   share     1155 Nov 28 17:55 FIG.txt
-rw-r-----   1 share   share      284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share   share    14821 Nov 28 21:44 davsec20011126.lzh
drwxr-x---   2 share   share       48 Nov 28 20:46 sample/
$ telnet localhost 80
(中略)
MOVE /davnoauth/FIG.txt HTTP/1.1 ←FIG.txtというファイルを移動
Accept-Language: ja, en-us;q=0.2
Destination: http://tripmachine/davnoauth/davsec20011126.lzh ←移動先(上書き)
Overwrite: T           ←上書き許可
Depth: infinity
Translate: f
User-Agent: Mage Hoge DAV 1.1
Host: tripmachine
Content-Length: 0
Connection: Keep-Alive

HTTP/1.1 204 No Content      ←レスポンス開始(MOVE成功)
(中略)
Content-Type: text/plain
                  ←レスポンス終了
Connection closed by foreign host.
$ ls -l /home/davnoauth/     ←その後は?
(FIG.txtはMOVEされたため存在しない)

total 40
-rw-r-----   1 share   share     7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share   share     7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share   share    13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share   share      284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share   share     1155 Nov 28 17:55 davsec20011126.lzh ←FIG.txtのファイル内容に置き換わる
drwxr-x---   2 share   share       48 Nov 28 20:46 sample/
$
リスト7 MOVEメソッドを使ったコンテンツの破壊

 また、リソース名やコレクション名を変更されてしまうことで、コンテンツの依存関係が崩されるといった事態も考えられます。

対策:

DELETEメソッド

脅威:

$ ls -l /home/davnoauth/         ←メソッド発行前の様子は?
total 40
-rw-r-----   1 share   share     7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share   share     7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share   share    13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share   share      284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share   share     1155 Nov 28 17:55 davsec20011126.lzh ←存在する
drwxr-x---   2 share   share       48 Nov 28 20:46 sample/
$ telnet localhost 80
(中略)
DELETE /davnoauth/davsec20011126.lzh HTTP/1.1 ←リクエスト開始/davsec20011126.lzhを消してみる
Accept-Language: ja, en-us;q=0.2
Overwrite: T
Depth: infinity
Translate: f
User-Agent: Mage Hoge DAV 1.1
Host: tripmachine
Content-Length: 0             ←リクエスト終了
   
                 ←空行(リターン)入力
HTTP/1.1 204 No Content          ←レスポンス開始(成功)
(中略)
Content-Type: text/plain
                      ←レスポンス終了
Connection closed by foreign host.     ←タイムアウト
$ ls -l /home/davnoauth/ ←davsec20011126.lzhは消えている
total 36
-rw-r-----   1 share    share        7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share    share        7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share    share       13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share    share         284 Nov 28 17:55 FIG.txt~
drwxr-x---   2 share    share          48 Nov 28 20:46 sample/
$
リスト8 DELETEメソッドの発行によるファイルの削除

対策:

PROPPATCHメソッド

脅威:

 SkunkDAVクライアントで、改ざん前のデッドプロパティの値を表示している様子を画面3に、改ざんの様子をリスト9に、改ざん後のデッドプロパティの様子を画面4に示します。

画面3 PROPPATCHによるプロパティ変更例(画像をクリックすると拡大表示します)

$ telnet localhost 80
(中略)
PROPPATCH /davnoauth/DAVSec.txt HTTP/1.1
Host: tripmachine
Connection: close, TE
TE: trailers, deflate, gzip, compress
User-Agent: Skunkzilla/1.0 RPT-HTTPClient/0.3-2
Accept-Encoding: deflate, gzip, x-gzip , compress, x-compress
Content-type: application/octet-stream
Content-length: 200

<?xml version="1.0" ?><skunk:propertyupdate xmlns:skunk="DAV:"><skunk:set><skunk:prop>
<ns92:moge xmlns:ns92="http://teketou/xmlns">mage</ns92:moge> ←デッドプロパティの改ざん内容
</skunk:prop>
</skunk:set></skunk:propertyupdate>


HTTP/1.1 207 Multi-Status
Date: Wed, 28 Nov 2001 13:40:18 GMT
Server: Apache/1.3.22 (Unix) DAV/1.0.3
Connection: close
Transfer-Encoding: chunked
Content-Type: text/xml; charset="utf-8"

12a
<?xml version="1.0" encoding="utf-8"?>
<D:multistatus xmlns:D="DAV:" xmlns:ns1="http://teketou/xmlns"
 xmlns:ns0="DAV:">
(中略)
</D:multistatus>

0

Connection closed by foreign host.
$
リスト9 デッドプロパティの改ざん

画面4 改ざん後のデッドプロパティ(画像をクリックすると拡大表示します)

対策:

LOCKメソッド

脅威:

 cadaverを使ってロックをかけている様子をリスト10に、ロックをかけられたことを知らずにSkunkDAV経由でロックをかけようとした様子を画面5に示します。

dav:/davnoauth/> lock DAVSec.txt
Locking `DAVSec.txt': (reconnecting...done) succeeded.
dav:/davnoauth/>
リスト10 cadaverによるLOCKメソッドの使用

画面5 他者の操作ができない例(画像をクリックすると拡大表示します)

対策:

 また、すでにロックがかけられてしまった場合はロックデータベースファイルを削除する(リスト11)ことでロックを解除することが可能です。

# ls -al
total 16
drwxr-xr-x   2 share    share        4096 Nov 28 17:53 ./
drwxr-xr-x  13 root     root         4096 Nov 28 16:39 ../
-rw-r-----   1 share    share           0 Nov 28 17:53 DAVLock.dir
-rw-r-----   1 share    share        8192 Nov 28 23:17 DAVLock.pag
# rm DAVLock.*
rm: remove `DAVLock.dir'? y
rm: remove `DAVLock.pag'? y
# ls -al
total 8
drwxr-xr-x   2 share    share        4096 Nov 28 23:22 ./
drwxr-xr-x  13 root     root         4096 Nov 28 16:39 ../
#  ←ここで、画面6の操作を行う
# ls -l
total 8
-rw-r-----   1 share    share           0 Nov 28 23:23 DAVLock.dir ←再作成される
-rw-r-----   1 share    share        8192 Nov 28 23:23 DAVLock.pag ←再作成される
#
リスト11 ロックデータベースファイルの場所と削除

 この状態で、例えば新規にロックをかけた(画面6)場合、ロックデータベースファイルは新たに作成されます。

画面6 ロック操作の例(画像をクリックすると拡大表示します)

UNLOCKメソッド

脅威:

 LOCKメソッドでかけたロックをUNLOCKメソッドで開放するためには、Lockトークンが必要になります。対応するLockトークンは、LOCKリクエストに対応したレスポンス中で返却されますが、このトークンが不正に取得されてしまうとロックをかけた以外の人でもUNLOCKによるロック解除の実施が可能になります。画面6にてSkunkDAVでLOCKメソッドを発行しているときの通信内容をリスト12に示します。

LOCK /davnoauth/DAVSec.txt HTTP/1.1
(中略)
Content-type: text/xml..Content-length: 158

<?xml version="1.0" ?>
<lockinfo xmlns="DAV:">
  <lockscope>
    <exclusive/>
  </lockscope>
  <locktype>
    <write/>
  </locktype>
  <owner>
    <href>wakatono</href>
  </owner>
</lockinfo>


HTTP/1.1 200 OK
Date: Wed, 28 Nov 2001 14:33:49 GMT
Server: Apache/1.3.22 (Unix) DAV/1.0.3
Lock-Token: <opaquelocktoken:f04fe558-1dd1-11b2-8c12-8e456d58de06> ←Lockトークン
Connection: close
Transfer-Encoding: chunked
Content-Type: text/xml; charset="utf-8"

1b8
<?xml version="1.0" encoding="utf-8"?>
 <D:prop xmlns:D="DAV:">
 (中略)
<D:href>opaquelocktoken:f04fe558-1dd1-11b2-8c12-8e456d58de06</D:href> ←Lockトークン(HTTPヘッダに現れているものと同じ)
</D:locktoken>
</D:activelock>
</D:lockdiscovery>
</D:prop>
0
リスト12 LOCKメソッド実施中の通信内容

 上記の例では、Lockトークンは以下のような文字列になっています。

opaquelocktoken:f04fe558-1dd1-11b2-8c12-8e456d58de06

 この文字列をLockトークンに指定してUNLOCKリクエストを発行することで、ロックの解除が可能です。これを用いて不正にロックを解除している様子をリスト13に示します。

$ cadaver http://localhost/davnoauth/
Looking up hostname... Connecting to server... connected.
dav:/davnoauth/> ls
Listing collection `/davnoauth/': succeeded.
Coll:  sample                                  0  Nov 28 11:46
       DAVSec.txt                           7533  Nov 28 08:55
       DAVSec.txt~                          7659  Nov 28 08:55
       DAVSec_.lzh                         13880  Nov 28 08:55
       FIG.txt~                              284  Nov 28 08:55
dav:/davnoauth/> unlock DAVSec.txt
Unlocking `DAVSec.txt':Enter locktoken: opaquelocktoken:f04fe558-1dd1-11b2-8c12-8e456d58de06 ←自分ではLOCKトークンが分からないので聞いている
 succeeded. ←正しいLOCKトークンが入力され、ロックが解除された
dav:/davnoauth/>
リスト13 Lockトークンさえ分かればUNLOCKが可能

 また、ロックが解除されたことを知らないSkunkDAVからロックを解除しようとすると、画面7のような画面が表示がされます()。

画面7 SkunkDAVでロックを解除しようとすると表示される画面(画像をクリックすると拡大表示します)

:タイムアウトによるロック解除もあり得るので、ロックを解除した覚えがなくても解除されていることはあります。

対策:

 また、Lockトークンが奪取されること自体がよいことではないので、あまりにもLOCKが解除されるという状態が続いたら、ネットワークの不正盗聴などが行われている可能性も視野に入れてください。

PUTメソッド

脅威:

# telnet localhost 80
(中略)
PUT /davnoauth/putsample.txt HTTP/1.1 ←リクエスト開始/putsample.txtというファイルを作成
Host: tripmachine
Connection:  close, TE
TE: trailers, deflate, gzip, compress
User-Agent: Skunkzilla/1.0 RPT-HTTPClient/0.3-2
Accept-Encoding: deflate, gzip, x-gzip, compress, x-compress
Content-type: application/octet-stream
Content-length: 24

PUT Method Sample File.    ←putsample.txtの内容
              
←リクエスト終了
HTTP/1.1 201 Created     ←レスポンス開始(ファイル作成成功)
Date: Wed, 28 Nov 2001 14:50:59 GMT
Server: Apache/1.3.22 (Unix) DAV/1.0.3
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

11b
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<HTML><HEAD>
<TITLE>201 Created</TITLE>
</HEAD><BODY>
<H1>Created</H1>
Resource /davnoauth/putsample.txt has been created.
<P><HR>
<ADDRESS>Apache/1.3.22 Server at tripmachine.ts.u.coe.nttdata.co.jp
 Port 80</ADDRESS>
</BODY></HTML>

0
               ←レスポンス終了
Connection closed by foreign host.
# ls -l /home/davnoauth/
total 40
-rw-r-----   1 share    share        7533 Nov 28 17:55 DAVSec.txt
-rw-r-----   1 share    share        7659 Nov 28 17:55 DAVSec.txt~
-rw-r-----   1 share    share       13880 Nov 28 17:55 DAVSec_.lzh
-rw-r-----   1 share    share         284 Nov 28 17:55 FIG.txt~
-rw-r-----   1 share    share          23 Nov 28 23:51 putsample.txt ←新しくできているファイル
drwxr-x---   2 share    share          48 Nov 28 20:46 sample/
# cat /home/davnoauth/putsample.txt
PUT Method Sample File. ←PUTリクエストで入れた内容が入っている
#
リスト14 PUTメソッドによる新規ファイルの作成

# telnet localhost 80
(中略)
PUT /davnoauth/putsample.txt HTTP/1.1 ←リクエスト開始/リスト14で作成したファイルに上書き
Host: tripmachine
Overwrite: T                   ←上書き許可
Connection:  close, TE
TE: trailers, deflate, gzip, compress
User-Agent: Skunkzilla/1.0 RPT-HTTPClient/0.3-2
Accept-Encoding: deflate, gzip, x-gzip, compress, x-compress
Content-type: application/octet-stream
Content-length: 50

PUT Method Sample File alternative by WAKATONO. ←上書きする内容
                         ←リクエスト終了
HTTP/1.1 204 No Content          ←レスポンス開始(成功)
Date: Wed, 28 Nov 2001 14:57:14 GMT
Server: Apache/1.3.22 (Unix) DAV/1.0.3
Connection: close
Content-Type: text/plain
                         ←レスポンス終了
Connection closed by foreign host.
# cat /home/davnoauth/putsample.txt
PUT Method Sample File alternative by WAKATONO. ←上書きされている
#
リスト15 既存ファイルに対する上書き

対策:

後編の予告

 前編では、各メソッドの動作・危険性と、それに応じた対処方法を中心に解説しました。メソッドの動作を知ることで、防御方法が浮き彫りになったと思います。

 後編では、より包括的にセキュリティを確保する方法を紹介します。「ダイジェスト認証」を使ったより安全な認証方法やmod_dav固有の問題とその対策方法など、WebDAVの利点を生かしたままセキュリティを強化できることをお伝えします。