SlideShare une entreprise Scribd logo
1  sur  34
Copyright©2013 JPCERT/CC All rights reserved.
「Javaアプリケーション脆弱性事例調査資料」について
この資料は、Javaプログラマである皆様に、脆弱性を身
近な問題として感じてもらい、セキュアコーディングの
重要性を認識していただくことを目指して作成していま
す。
「Javaセキュアコーディングスタンダード
CERT/Oracle版」と合わせて、セキュアコーディングに
関する理解を深めるためにご利用ください。
JPCERTコーディネーションセンター
セキュアコーディングプロジェクト
secure-coding@jpcert.or.jp
1
Japan Computer Emergency Response Team
Coordination Center
電子署名者 : Japan Computer Emergency Response Team Coordination Center
DN : c=JP, st=Tokyo, l=Chiyoda-ku, email=office@jpcert.or.jp, o=Japan Computer Emergency Response
Team Coordination Center, cn=Japan Computer Emergency Response Team Coordination Center
日付 : 2013.06.26 10:58:54 +09'00'
Apache Sling におけるサービス
運用妨害 (無限ループ) の脆弱性
CVE-2012-2138
JVNDB-2012-003033
2
Copyright©2013 JPCERT/CC All rights reserved.
Apache Sling とは
Webサイトのコンテンツ管理を目的としたオープンソー
スのWebフレームワーク
コンテンツの管理方式としてApache Jackrabbitと同様の
Javaコンテンツリポジトリ(JCR)を採用している。
3
property1:xxxx
property2:xxxx
property1:xxxx
property2:xxxx
property1:xxxx
property2:xxxx
Copyright©2013 JPCERT/CC All rights reserved.
JCR(Javaコンテンツリポジトリ)
4
• Javaコンテンツリポジトリはノードとプ
ロパティのツリーで構成される。
• ノード:ファイルシステムにおける
ファイルやフォルダ
• プロパティ:ノードの付属情報
ノード
ファイル
プロパティ
ノードとプロパティの関係
フォルダ
Type:Folder
Created:20xx/xx
Type:File
Created:20xx/xx
Copyright©2013 JPCERT/CC All rights reserved.5
Apache Slingのノード管理画面
ノードの一覧 index.htmlというノード(ファイル)の
プロパティ(付属情報)
JCR(Javaコンテンツリポジトリ)
Copyright©2013 JPCERT/CC All rights reserved.
Apache Sling のコンテンツ管理機能
—Slingにはノードの作成・編集・削除・コピー・移動などを
行う機能が存在する。
—コピー機能を使うと、指定されたノードと付随するプロパ
ティを特定のノード配下にコピーすることができる。
6
Property1:true
Default:100
Property1:false
DefaultStr:”test”
ノードA
(フォルダ)
Property1:false
DefaultStr:”test”
コピー機能のイメージ
ノードとノードに付随するプ
ロパティが特定のノード配下
にコピーされる
ノードB
(フォルダ)
ノードA
(フォルダ)
Copyright©2013 JPCERT/CC All rights reserved.
脆弱性の概要
—コピー機能にはサービス運用妨害(DoS)攻撃を受ける脆弱
性が存在する。
—コピーの際に、コピー元とコピー先に同一のファイルパス
を指定すると、無限ループが発生し、サービス運用妨害が
成立する。
7
Copyright©2013 JPCERT/CC All rights reserved.
脆弱性が悪用された場合のリスク
無限ループによりCPU/メモリリソースが枯渇し、サーバ
が応答しなくなる。
その結果、提供されているサービスが停止する。提供し
ているサービスによっては金銭的な被害が発生する可能
性がある。
8
node
node
node
無限ループ
その結果・・・・
サーバ、サービスの停止
Copyright©2013 JPCERT/CC All rights reserved.
通常の処理
9
コンテンツをコピーする際の処理フロー
① クライアントからリクエストが送信される。
② アプリケーションがリクエストを受信し、コピー元とコピー先のパスの
情報を取り出す。
③ CopyOperationクラスのCopy関数でコピー処理を行う。
④ 結果を含むレスポンスがクライアントへ送信される。
Copyright©2013 JPCERT/CC All rights reserved.
①クライアントからリクエストが送信される
10
ここでは、ノード「/content/page/foo」とその配下のノード「orz1」
「orz2」を「/content」配下のノード「bar」としてコピーするリクエ
ストが送られたとする。
content
bar
page
foo
orz1
orz2
orz1
orz1
コピー先
/content/bar
コピー元
/content/page/foo
Copyright©2013 JPCERT/CC All rights reserved.
①クライアントからリクエストが送信される
11
POST /content/bar HTTP/1.1
Host: localhost:8080
:
@CopyFrom=/content/page/foo
<form action=‘/content/bar’ method=‘POST’>
:
<input type=‘hidden’ name=‘@CopyFrom’ value=‘/content/page/foo’>
:
</form>
HTTPリクエスト
上記HTTPリクエストを送信するためのHTML
コンテンツのコピー元の
ノードをパラメータ
@CopyFromで指定する。
コンテンツのコピー先の
ノードをパスで指定する
Copyright©2013 JPCERT/CC All rights reserved.
②アプリケーションがリクエストを受信し、コピー処理を開始する
12
コピー処理はCopyOperationクラスのCopyメソッドで行われる。
POST /content/bar HTTP/1.1
Host: localhost:8080
:
@CopyFrom=/content/page/foo
HTTPリクエスト
public class CopyOperation extends
AbstractCopyMoveOperation{
:
static Item copy(Node src, Node dstParent, String name)
CopyOperation.java
SlingPostServlet.doPost()
ModifyOperation().run()
ModifyOperation.doRun()
ModifyOperation.processCopies()
ModifyOperation.processMovesCopiesInternal()
CopyOperation.copy()
経由するメソッド
/content/bar
/content/page/foo
Copyright©2013 JPCERT/CC All rights reserved.
③CopyOperationクラスのCopyメソッドでコピー処理を行う
13
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
return dst;
}
CopyOperation.java
CopyOperationクラスのCopyメ
ソッドでは下記の5つの処理が行わ
れる。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じメソッドが再帰的
に呼ばれる)
①
②
③
④
⑤
Copyright©2013 JPCERT/CC All rights reserved.
③CopyOperationクラスのCopyメソッドでコピー処理を行う
14
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
return dst;
}
CopyOperationクラスのCopyメ
ソッドでは下記の5つの処理が行わ
れる。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じ関数が再帰的に
呼ばれる)
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
} コンテンツのコピー先の
ノード名が指定される
コピー先
/content/bar
コピー元
/content/page/foo
コピー先のノード名(bar)
CopyOperation.java
Copyright©2013 JPCERT/CC All rights reserved.
CopyOperationクラスのCopyメ
ソッドでは下記の5つの処理が行わ
れる。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じ関数が再帰的に
呼ばれる)
③CopyOperationクラスのCopyメソッドでコピー処理を行う
15
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
return dst;
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
コピー先(/content/)に同
名のノード(bar)が存在
しないか確認し、存在す
れば削除する。
コピー先
/content/bar
コピー先のノード名
(bar)
CopyOperation.java
Copyright©2013 JPCERT/CC All rights reserved.
③CopyOperationクラスのCopyメソッドでコピー処理を行う
16
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
return dst;
}
CopyOperationクラスのCopyメ
ソッドでは下記の5つの処理が行わ
れる。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じ関数が再帰的に
呼ばれる)
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
コピー先(/content/)にnameで指
定されたノード(bar)を作成する。
コピー先
/content/bar
コピー先のノード名(bar)
CopyOperation.java
Copyright©2013 JPCERT/CC All rights reserved.
③CopyOperationクラスのCopyメソッドでコピー処理を行う
17
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
return dst;
}
CopyOperationクラスのCopyメ
ソッドでは下記の5つの処理が行わ
れる。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じメソッドが再帰
的に呼ばれる)
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
コピー元(/content/page/foo)のプロパティ
をコピー先(/content/bar)にコピーする。
ここで呼び出されているcopyメソッドは実
行中のメソッドとは別のオーバーロードさ
れたメソッド。
コピー元
/content/page/foo
コピー先
/content/bar
CopyOperation.java
Copyright©2013 JPCERT/CC All rights reserved.
CopyOperationクラスのCopyメ
ソッドでは下記の5つの処理が行わ
れる。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じメソッドが再帰
的に呼ばれる)
③CopyOperationクラスのCopyメソッドでコピー処理を行う
18
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
return dst;
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
コピー元に子ノードが存在する場合は再帰
的にcopyメソッドがコールされ、コピー処
理が行われる。
コピー元
/content/page/foo
コピー先
/content/bar
CopyOperation.java
Copyright©2013 JPCERT/CC All rights reserved.
③CopyOperationクラスのCopyメソッドでコピー処理を行う
19
■子ノードに対する再帰的なコピー処理
content
page
foo
orz1
orz2
bar
orz1
content
page
foo
orz1
orz2
bar
/content/page/foo が /content/bar にcopyメ
ソッドでコピーされる。
copyメソッド内で再帰的にcopyメソッドが呼
ばれ、 /content/page/fooの子ノードである
orz1が/content/bar/配下にコピーされる。
Copyright©2013 JPCERT/CC All rights reserved.
③CopyOperationクラスのCopyメソッドでコピー処理を行う
20
content
page
foo
orz1
orz2
bar
orz1
orz2
content
page
foo
orz1
orz2
bar
orz1
orz2
さらにcopyメソッド内で再帰的にcopyメソッ
ドが呼ばれ、 /content/page/fooの子ノードで
あるorz2が/content/bar/配下にコピーされる。
■子ノードに対する再帰的なコピー処理
/content/page/fooの全ての子ノードが
/content/bar/配下にコピーされて、再帰的な処
理が終了する。
Copyright©2013 JPCERT/CC All rights reserved.
④レスポンスがクライアントへ送信される。
21
コピー処理が終了し、結果をレスポンスとしてクライアントへ送信する。
Success!!
Copyright©2013 JPCERT/CC All rights reserved.
攻撃コード
22
■攻撃コードのポイント
コピー対象のノードに対し、自分自身の子ノード配下に
自身をコピーするように指定している。
(親ノード→子ノードのコピー)
POST /content/page/foo HTTP/1.1
Host: localhost:8080
:
@CopyFrom=/content/page/
<form action=‘/content/page/foo’ method=‘POST’>
:
<input type=‘hidden’ name=‘@CopyFrom’ value=‘/content/page/’>
:
</form>
攻撃コードのHTTPリクエスト
攻撃コードのHTTPリクエストを送信するためのHTML
コピー元ノード
コピー先ノード
content
page
foo
コピー元
コピー先
子ノードへのコピー
Copyright©2013 JPCERT/CC All rights reserved.
攻撃コード: 攻撃コードを受け取った際の処理
23
攻撃コードが実行された際の処理のフローは③のコピー処理にて無限
ループが発生する。
コンテンツをコピーする際の処理フロー
① クライアントからリクエストが送信される。
② アプリケーションがリクエストを受信し、コピー元とコピー先の値を取
り出す
③ コピー処理を行う。
④ 結果を含むレスポンスがクライアントへ送信される。
Copyright©2013 JPCERT/CC All rights reserved.
攻撃コード実行時
③CopyOperationクラスのCopyメソッドでコピー処理を行う
24
CopyOperationクラスのCopyメ
ソッドでは下記の5つの処理が行わ
れる。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じメソッドが再帰
的に呼ばれる)
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
// ensure destination name
if (name == null) {
name = src.getName();
}
// ensure new node creation
if (dstParent.hasNode(name)) {
dstParent.getNode(name).remove();
}
// create new node
Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName());
for (NodeType mix : src.getMixinNodeTypes()) {
dst.addMixin(mix.getName());
}
// copy the properties
for (PropertyIterator iter = src.getProperties(); iter.hasNext();) {
copy(iter.nextProperty(), dst, null);
}
// copy the child nodes
for (NodeIterator iter = src.getNodes(); iter.hasNext();) {
Node n = iter.nextNode();
if (!n.getDefinition().isProtected()) {
copy(n, dst, null);
}
}
return dst;
}
CopyOperation.java
copyメソッド内の5番目の処理で
ある、子ノードを再帰的にコピー
する処理でループが発生する!!
Copyright©2013 JPCERT/CC All rights reserved.
攻撃コード実行時
③CopyOperationクラスのCopyメソッドでコピー処理を行う
25
■コピー元に「/content/page/」、コピー先に「/content/page/foo」を指定した
際のコピー処理
content
page
foo
content
page
foo
foo
copyメソッドで/content/pageが
/content/page/fooとしてコピーされる。
たった今コピーされた/content/page/fooが
/content/pageの子ノードとして存在するため、
再帰的にコピー処理が実施されてしまう!!
無限ループの始まり!!
Copyright©2013 JPCERT/CC All rights reserved.26
■コピー元に「/content/page/」、コピー先に「/content/page/foo」を指定した
際のコピー処理
content
page
foo
foo
再帰的にコピー処理が繰り返されること
でループし続け、DoS攻撃が成立する!!
foo
foo
攻撃コード実行時
③CopyOperationクラスのCopyメソッドでコピー処理を行う
Copyright©2013 JPCERT/CC All rights reserved.
問題点とその対策
 今回のアプリケーションにおける具体的な問題点
copyメソッドではメソッドの引数を検証せずにコピー処
理を行っていた。
以下のコーディングガイドに違反している!!
「MET00-J メソッドの引数を検証する」
 問題点に対してどうすべきだったか。
処理対象のデータ構造(今回の場合はツリー構造)を考
慮して、copyメソッドの引数であるdstParentノードが
src以下のノードでないことを確認した上で、コピー処理
を行うべきだった。
27
Copyright©2013 JPCERT/CC All rights reserved.
修正版コード
28
ループが発生するコピー処理のコードが
修正されている。
コンテンツをコピーする際の処理フロー
① クライアントからリクエストが送信される。
② アプリケーションがリクエストを受信し、コピー元とコピー先の値を取
り出す
③ コピー処理を行う。
④ 結果を含むレスポンスがクライアントへ送信される。
脆弱性はバージョン2.1.3にて修正が適用されている
Copyright©2013 JPCERT/CC All rights reserved.
修正前/修正後の処理比較
③CopyOperationクラスのCopyメソッドでコピー処理を行う
29
CopyOperationクラスのCopyメソッ
ドでは下記6つの処理が行われる。
isAncestorOrSameNode関数でコ
ピー元とコピー先が同じツリーで
ないことを確認する
① コピー先のノード名を確認
② コピー先に既に同様の名前のノー
ドが存在しないかを確認し、存在
すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先の
ノードへプロパティ情報をコピー
⑤ コピー元の子ノードをコピー先に
コピー(同じメソッドが再帰的に
呼ばれる)
CopyOperationクラスのCopyメ
ソッドでは下記5つの処理が行われ
る。
① コピー先のノード名を確認
② コピー先に既に同様の名前の
ノードが存在しないかを確認し、
存在すれば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先
のノードへプロパティ情報をコ
ピー
⑤ コピー元の子ノードをコピー先
にコピー(同じメソッドが再帰
的に呼ばれる)
修正前の処理 修正後の処理
0
Copyright©2013 JPCERT/CC All rights reserved.
修正版コード
③CopyOperationクラスのCopyメソッドでコピー処理を行う
30
static Item copy(Node src, Node dstParent, String name)
throws RepositoryException {
if(isAncestorOrSameNode(src, dstParent)) {
throw new RepositoryException(
"Cannot copy ancestor " + src.getPath() + " to descendant " +
dstParent.getPath());
}
// ensure destination name
if (name == null) {
name = src.getName();
}
:
}
CopyOperation.java
CopyOperationクラスのCopyメソッ
ドでは下記6つの処理が行われる。
isAncestorOrSameNode関数でコ
ピー元とコピー先が同じツリーでな
いことを確認する
① コピー先のノード名を確認
② コピー先に既に同様の名前のノード
が存在しないかを確認し、存在すれ
ば削除
③ コピー先のノード作成
④ コピー元のノードからコピー先の
ノードへプロパティ情報をコピー
⑤ コピー元の子ノードをコピー先にコ
ピー(同じ関数が再帰的に呼ばれ
る)
if(isAncestorOrSameNode(src, dstParent)) {
throw new RepositoryException(
"Cannot copy ancestor " + src.getPath() + " to descendant " +
dstParent.getPath());
}
コピー先
のノード情報
コピー元
のノード情報
0
Copyright©2013 JPCERT/CC All rights reserved.31
static boolean isAncestorOrSameNode(Node src, Node dest) throws
RepositoryException {
if(src.getPath().equals("/")) {
return true;
} else if(src.getPath().equals(dest.getPath())) {
return true;
} else if(dest.getPath().startsWith(src.getPath() + "/")) {
return true;
}
return false;
}
isAncestorOrSameNodeメソッド
①コピー元がルートディレクト
リでないか
②コピー元とコピー先が同一の
パスでないか
③コピー元とコピー先が同一の
ツリーでないか
■isAncestorOrSameNodeメソッドではコピー元とコピー先のノードに対
して3つのチェックを行っている。
修正版コード
③CopyOperationクラスのCopyメソッドでコピー処理を行う
Copyright©2013 JPCERT/CC All rights reserved.32
■isAncestorOrSameNodeメソッドでのチェック内容のまとめ
下記の3つのチェックにより、無限ループが発生するようなコピー元/コピー先
の組み合わせが指定されていたら、エラーとして処理する。
① コピー元がルートディレクトリでないか
② コピー元とコピー先が同一のパスでないか
③ コピー元とコピー先が同一のツリーでないか
■修正版コードに攻撃コードを実行するとどうなるか
コピー元に「/content/page/」、コピー先に「/content/page/foo」が指定され
ている
↓
上記②のチェックでエラーとなり、無限ループは発生しな
い!!
修正版コード
③CopyOperationクラスのCopyメソッドでコピー処理を行う
Copyright©2013 JPCERT/CC All rights reserved.
まとめ
33
■この脆弱性から学べるプログラミングの注意点
• アプリケーションの処理内容や、扱うデータ構造に応じ
た引数の検証をすべき
• 今回のコピー処理は再帰的な動作であり、コピー対
象の指定の仕方によっては無限ループが発生する可能
性があることを考慮すべきであった。
■上記への対策
• 再帰的な処理を実装する場合、無限ループにならない条
件(あるいは無限ループになる条件)を明確にし、その条件
を確認するコードを必ず入れる
Copyright©2013 JPCERT/CC All rights reserved.
著作権・引用や二次利用について
本資料の著作権はJPCERT/CCに帰属します。
本資料あるいはその一部を引用・転載・再配布する際は、引用元名、資料名および URL の明示をお
願いします。
記載例
引用元:一般社団法人JPCERTコーディネーションセンター
Java アプリケーション脆弱性事例解説資料
Apache Sling におけるサービス運用妨害(無限ループ)の脆弱性
https://www.jpcert.or.jp/research/materials-java-casestudies/No.1_Apache_Sling.pdf
本資料を引用・転載・再配布をする際は、引用先文書、時期、内容等の情報を、JPCERT コーディ
ネーションセンター広報(office@jpcert.or.jp)までメールにてお知らせください。なお、この連絡に
より取得した個人情報は、別途定めるJPCERT コーディネーションセンターの「プライバシーポリ
シー」に則って取り扱います。
本資料の利用方法等に関するお問い合わせ
JPCERTコーディネーションセンター
広報担当
E-mail:office@jpcert.or.jp
34
本資料の技術的な内容に関するお問い合わせ
JPCERTコーディネーションセンター
セキュアコーディング担当
E-mail:secure-coding@jpcert.or.jp

Contenu connexe

Tendances

脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)JPCERT Coordination Center
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!Shinpei Ohtani
 
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)JPCERT Coordination Center
 
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」JPCERT Coordination Center
 
JBoss Application Server におけるディレクトリトラバーサルの脆弱性
JBoss Application Server におけるディレクトリトラバーサルの脆弱性JBoss Application Server におけるディレクトリトラバーサルの脆弱性
JBoss Application Server におけるディレクトリトラバーサルの脆弱性JPCERT Coordination Center
 
クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策JPCERT Coordination Center
 
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性JPCERT Coordination Center
 
Spring fest2020 spring-security
Spring fest2020 spring-securitySpring fest2020 spring-security
Spring fest2020 spring-security土岐 孝平
 
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetupこれで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
これで怖くない!?コードリーディングで学ぶSpring Security #中央線MeetupMasatoshi Tada
 
Use JWT access-token on Grails REST API
Use JWT access-token on Grails REST APIUse JWT access-token on Grails REST API
Use JWT access-token on Grails REST APIUehara Junji
 
JNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについて
JNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについてJNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについて
JNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについてKenji Urushima
 
安全なPHPアプリケーションの作り方2014
安全なPHPアプリケーションの作り方2014安全なPHPアプリケーションの作り方2014
安全なPHPアプリケーションの作り方2014Hiroshi Tokumaru
 
いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)
いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)
いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)Kenji Urushima
 
Javascript で暗号化
Javascript で暗号化Javascript で暗号化
Javascript で暗号化suno88
 
とある診断員とSQLインジェクション
とある診断員とSQLインジェクションとある診断員とSQLインジェクション
とある診断員とSQLインジェクションzaki4649
 
Keycloak拡張入門
Keycloak拡張入門Keycloak拡張入門
Keycloak拡張入門Hiroyuki Wada
 
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccPivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccMasatoshi Tada
 
Active Directory 侵害と推奨対策
Active Directory 侵害と推奨対策Active Directory 侵害と推奨対策
Active Directory 侵害と推奨対策Yurika Kakiuchi
 
はまる!JPA(初学者向けライト版)
はまる!JPA(初学者向けライト版)はまる!JPA(初学者向けライト版)
はまる!JPA(初学者向けライト版)Masatoshi Tada
 

Tendances (20)

脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (KOF2014)
 
Struts2を始めよう!
Struts2を始めよう!Struts2を始めよう!
Struts2を始めよう!
 
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
脆弱性事例に学ぶセキュアコーディング「SSL/TLS証明書検証」編 (JavaDayTokyo2015)
 
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
デブサミ2015 事例から学ぶAndroidアプリのセキュアコーディング「SSL/TLS証明書検証の現状と対策」
 
JBoss Application Server におけるディレクトリトラバーサルの脆弱性
JBoss Application Server におけるディレクトリトラバーサルの脆弱性JBoss Application Server におけるディレクトリトラバーサルの脆弱性
JBoss Application Server におけるディレクトリトラバーサルの脆弱性
 
クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策クロスサイトリクエストフォージェリ(CSRF)とその対策
クロスサイトリクエストフォージェリ(CSRF)とその対策
 
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
Android Platform の URLConnection に HTTP ヘッダインジェクションの脆弱性
 
Spring fest2020 spring-security
Spring fest2020 spring-securitySpring fest2020 spring-security
Spring fest2020 spring-security
 
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetupこれで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
これで怖くない!?コードリーディングで学ぶSpring Security #中央線Meetup
 
Use JWT access-token on Grails REST API
Use JWT access-token on Grails REST APIUse JWT access-token on Grails REST API
Use JWT access-token on Grails REST API
 
JNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについて
JNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについてJNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについて
JNSA電子署名WG勉強会 2013.09.30 jsrsasignとjsjwsについて
 
安全なPHPアプリケーションの作り方2014
安全なPHPアプリケーションの作り方2014安全なPHPアプリケーションの作り方2014
安全なPHPアプリケーションの作り方2014
 
いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)
いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)
いろいろなSSL/TLS設定ガイドライン (JNSA電子署名WG 実世界の暗号・認証技術勉強会資料)
 
Javascript で暗号化
Javascript で暗号化Javascript で暗号化
Javascript で暗号化
 
とある診断員とSQLインジェクション
とある診断員とSQLインジェクションとある診断員とSQLインジェクション
とある診断員とSQLインジェクション
 
Java EE8 Report
Java EE8 ReportJava EE8 Report
Java EE8 Report
 
Keycloak拡張入門
Keycloak拡張入門Keycloak拡張入門
Keycloak拡張入門
 
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_cccPivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
Pivotal認定講師によるSpring Framework 5.1 & Spring Boot 2.1ハンズオン! #jjug_ccc
 
Active Directory 侵害と推奨対策
Active Directory 侵害と推奨対策Active Directory 侵害と推奨対策
Active Directory 侵害と推奨対策
 
はまる!JPA(初学者向けライト版)
はまる!JPA(初学者向けライト版)はまる!JPA(初学者向けライト版)
はまる!JPA(初学者向けライト版)
 

Similaire à Apache Sling におけるサービス運用妨害(無限ループ)の脆弱性

分散ストリーム処理フレームワーク Apache S4
分散ストリーム処理フレームワーク Apache S4分散ストリーム処理フレームワーク Apache S4
分散ストリーム処理フレームワーク Apache S4AdvancedTechNight
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejsTakayoshi Tanaka
 
2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!
2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!
2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!Midori Oge
 
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成Kiyoshi Sawada
 
20140612_Docker上でCloudStackを動かしてみる!!
20140612_Docker上でCloudStackを動かしてみる!!20140612_Docker上でCloudStackを動かしてみる!!
20140612_Docker上でCloudStackを動かしてみる!!Midori Oge
 
マスタリング DEA/NG 第2版
マスタリング DEA/NG 第2版マスタリング DEA/NG 第2版
マスタリング DEA/NG 第2版i_yudai
 
Android起動周りのノウハウ
Android起動周りのノウハウAndroid起動周りのノウハウ
Android起動周りのノウハウchancelab
 
React Native GUIDE
React Native GUIDEReact Native GUIDE
React Native GUIDEdcubeio
 
10分で作る Node.js Auto Scale 環境 with CloudFormation
10分で作る Node.js Auto Scale 環境 with CloudFormation10分で作る Node.js Auto Scale 環境 with CloudFormation
10分で作る Node.js Auto Scale 環境 with CloudFormationKazuyuki Honda
 
Nodejuku01 ohtsu
Nodejuku01 ohtsuNodejuku01 ohtsu
Nodejuku01 ohtsuNanha Park
 
TripleOの光と闇
TripleOの光と闇TripleOの光と闇
TripleOの光と闇Manabu Ori
 
Androidの通信周りのコーディングについて
Androidの通信周りのコーディングについてAndroidの通信周りのコーディングについて
Androidの通信周りのコーディングについてShoichi Takagi
 
Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Shotaro Suzuki
 
Mastodonインスタンスをセットアップできるスタートアップスクリプトについて
MastodonインスタンスをセットアップできるスタートアップスクリプトについてMastodonインスタンスをセットアップできるスタートアップスクリプトについて
Mastodonインスタンスをセットアップできるスタートアップスクリプトについてさくらインターネット株式会社
 
WebRTC meetup Tokyo 1
WebRTC meetup  Tokyo 1WebRTC meetup  Tokyo 1
WebRTC meetup Tokyo 1mganeko
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトKiyoshi Sawada
 
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方linzhixing
 
Kai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / ErlangKai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / ErlangTakeru INOUE
 

Similaire à Apache Sling におけるサービス運用妨害(無限ループ)の脆弱性 (20)

分散ストリーム処理フレームワーク Apache S4
分散ストリーム処理フレームワーク Apache S4分散ストリーム処理フレームワーク Apache S4
分散ストリーム処理フレームワーク Apache S4
 
13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs13016 n分で作るtype scriptでnodejs
13016 n分で作るtype scriptでnodejs
 
2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!
2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!
2013OSC関西@京都_CloudStackとCloudFoundaryがまるわかり!
 
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成
EWD 3トレーニング・コース #4 ewd-xpressのインストールと構成
 
20140612_Docker上でCloudStackを動かしてみる!!
20140612_Docker上でCloudStackを動かしてみる!!20140612_Docker上でCloudStackを動かしてみる!!
20140612_Docker上でCloudStackを動かしてみる!!
 
マスタリング DEA/NG 第2版
マスタリング DEA/NG 第2版マスタリング DEA/NG 第2版
マスタリング DEA/NG 第2版
 
Android起動周りのノウハウ
Android起動周りのノウハウAndroid起動周りのノウハウ
Android起動周りのノウハウ
 
DeclarativeSql
DeclarativeSqlDeclarativeSql
DeclarativeSql
 
React Native GUIDE
React Native GUIDEReact Native GUIDE
React Native GUIDE
 
10分で作る Node.js Auto Scale 環境 with CloudFormation
10分で作る Node.js Auto Scale 環境 with CloudFormation10分で作る Node.js Auto Scale 環境 with CloudFormation
10分で作る Node.js Auto Scale 環境 with CloudFormation
 
Nodejuku01 ohtsu
Nodejuku01 ohtsuNodejuku01 ohtsu
Nodejuku01 ohtsu
 
TripleOの光と闇
TripleOの光と闇TripleOの光と闇
TripleOの光と闇
 
Androidの通信周りのコーディングについて
Androidの通信周りのコーディングについてAndroidの通信周りのコーディングについて
Androidの通信周りのコーディングについて
 
Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...Building React, Flutter and Blazor development and debugging environment with...
Building React, Flutter and Blazor development and debugging environment with...
 
Mastodonインスタンスをセットアップできるスタートアップスクリプトについて
MastodonインスタンスをセットアップできるスタートアップスクリプトについてMastodonインスタンスをセットアップできるスタートアップスクリプトについて
Mastodonインスタンスをセットアップできるスタートアップスクリプトについて
 
WebRTC meetup Tokyo 1
WebRTC meetup  Tokyo 1WebRTC meetup  Tokyo 1
WebRTC meetup Tokyo 1
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
 
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
Alfresco勉強会20120829: やさしいShareダッシュレットの作り方
 
ScalaMatsuri 2016
ScalaMatsuri 2016ScalaMatsuri 2016
ScalaMatsuri 2016
 
Kai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / ErlangKai = (Dynamo + memcache API) / Erlang
Kai = (Dynamo + memcache API) / Erlang
 

Plus de JPCERT Coordination Center

いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~JPCERT Coordination Center
 
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)JPCERT Coordination Center
 
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』JPCERT Coordination Center
 
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)JPCERT Coordination Center
 
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)JPCERT Coordination Center
 
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...JPCERT Coordination Center
 
ソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデルソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデルJPCERT Coordination Center
 
Lessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL VulnerabilitiesLessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL VulnerabilitiesJPCERT Coordination Center
 
Blojsom におけるクロスサイトスクリプティングの脆弱性
Blojsom におけるクロスサイトスクリプティングの脆弱性Blojsom におけるクロスサイトスクリプティングの脆弱性
Blojsom におけるクロスサイトスクリプティングの脆弱性JPCERT Coordination Center
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説JPCERT Coordination Center
 
Javaセキュアコーディングセミナー東京第4回演習の解説
Javaセキュアコーディングセミナー東京第4回演習の解説Javaセキュアコーディングセミナー東京第4回演習の解説
Javaセキュアコーディングセミナー東京第4回演習の解説JPCERT Coordination Center
 
Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義JPCERT Coordination Center
 
Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習JPCERT Coordination Center
 

Plus de JPCERT Coordination Center (16)

いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
いま改めて製品開発者の脆弱性対応について考える ~情報セキュリティ早期警戒パートナーシップを運用する調整機関の視点から~
 
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
安全なプラグインに必要なこと: 脆弱性届出状況に見る傾向と対策 (WordCampTokyo 2017)
 
DLL読み込みの問題を読み解く
DLL読み込みの問題を読み解くDLL読み込みの問題を読み解く
DLL読み込みの問題を読み解く
 
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
WordBench東京 7月勉強会「夏のLT大会!」『WordPress とバックアップの話』
 
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
CERT コーディングスタンダードご紹介 (OSC2017@Osaka)
 
脆弱性情報はこうしてやってくる
脆弱性情報はこうしてやってくる脆弱性情報はこうしてやってくる
脆弱性情報はこうしてやってくる
 
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
OWASP ASVS と Cheat Sheet シリーズ (日本語版) のご紹介 (OSC2016Hokkaido)
 
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
Case Studies and Lessons Learned from SSL/TLS Certificate Verification Vulner...
 
ソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデルソフトウェアセキュリティ保証成熟度モデル
ソフトウェアセキュリティ保証成熟度モデル
 
Lessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL VulnerabilitiesLessons (to be) Learned from Handling OpenSSL Vulnerabilities
Lessons (to be) Learned from Handling OpenSSL Vulnerabilities
 
Android Secure Coding
Android Secure CodingAndroid Secure Coding
Android Secure Coding
 
Blojsom におけるクロスサイトスクリプティングの脆弱性
Blojsom におけるクロスサイトスクリプティングの脆弱性Blojsom におけるクロスサイトスクリプティングの脆弱性
Blojsom におけるクロスサイトスクリプティングの脆弱性
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説
 
Javaセキュアコーディングセミナー東京第4回演習の解説
Javaセキュアコーディングセミナー東京第4回演習の解説Javaセキュアコーディングセミナー東京第4回演習の解説
Javaセキュアコーディングセミナー東京第4回演習の解説
 
Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義Javaセキュアコーディングセミナー東京第4回講義
Javaセキュアコーディングセミナー東京第4回講義
 
Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習Javaセキュアコーディングセミナー東京第3回演習
Javaセキュアコーディングセミナー東京第3回演習
 

Apache Sling におけるサービス運用妨害(無限ループ)の脆弱性

  • 1. Copyright©2013 JPCERT/CC All rights reserved. 「Javaアプリケーション脆弱性事例調査資料」について この資料は、Javaプログラマである皆様に、脆弱性を身 近な問題として感じてもらい、セキュアコーディングの 重要性を認識していただくことを目指して作成していま す。 「Javaセキュアコーディングスタンダード CERT/Oracle版」と合わせて、セキュアコーディングに 関する理解を深めるためにご利用ください。 JPCERTコーディネーションセンター セキュアコーディングプロジェクト secure-coding@jpcert.or.jp 1 Japan Computer Emergency Response Team Coordination Center 電子署名者 : Japan Computer Emergency Response Team Coordination Center DN : c=JP, st=Tokyo, l=Chiyoda-ku, email=office@jpcert.or.jp, o=Japan Computer Emergency Response Team Coordination Center, cn=Japan Computer Emergency Response Team Coordination Center 日付 : 2013.06.26 10:58:54 +09'00'
  • 2. Apache Sling におけるサービス 運用妨害 (無限ループ) の脆弱性 CVE-2012-2138 JVNDB-2012-003033 2
  • 3. Copyright©2013 JPCERT/CC All rights reserved. Apache Sling とは Webサイトのコンテンツ管理を目的としたオープンソー スのWebフレームワーク コンテンツの管理方式としてApache Jackrabbitと同様の Javaコンテンツリポジトリ(JCR)を採用している。 3 property1:xxxx property2:xxxx property1:xxxx property2:xxxx property1:xxxx property2:xxxx
  • 4. Copyright©2013 JPCERT/CC All rights reserved. JCR(Javaコンテンツリポジトリ) 4 • Javaコンテンツリポジトリはノードとプ ロパティのツリーで構成される。 • ノード:ファイルシステムにおける ファイルやフォルダ • プロパティ:ノードの付属情報 ノード ファイル プロパティ ノードとプロパティの関係 フォルダ Type:Folder Created:20xx/xx Type:File Created:20xx/xx
  • 5. Copyright©2013 JPCERT/CC All rights reserved.5 Apache Slingのノード管理画面 ノードの一覧 index.htmlというノード(ファイル)の プロパティ(付属情報) JCR(Javaコンテンツリポジトリ)
  • 6. Copyright©2013 JPCERT/CC All rights reserved. Apache Sling のコンテンツ管理機能 —Slingにはノードの作成・編集・削除・コピー・移動などを 行う機能が存在する。 —コピー機能を使うと、指定されたノードと付随するプロパ ティを特定のノード配下にコピーすることができる。 6 Property1:true Default:100 Property1:false DefaultStr:”test” ノードA (フォルダ) Property1:false DefaultStr:”test” コピー機能のイメージ ノードとノードに付随するプ ロパティが特定のノード配下 にコピーされる ノードB (フォルダ) ノードA (フォルダ)
  • 7. Copyright©2013 JPCERT/CC All rights reserved. 脆弱性の概要 —コピー機能にはサービス運用妨害(DoS)攻撃を受ける脆弱 性が存在する。 —コピーの際に、コピー元とコピー先に同一のファイルパス を指定すると、無限ループが発生し、サービス運用妨害が 成立する。 7
  • 8. Copyright©2013 JPCERT/CC All rights reserved. 脆弱性が悪用された場合のリスク 無限ループによりCPU/メモリリソースが枯渇し、サーバ が応答しなくなる。 その結果、提供されているサービスが停止する。提供し ているサービスによっては金銭的な被害が発生する可能 性がある。 8 node node node 無限ループ その結果・・・・ サーバ、サービスの停止
  • 9. Copyright©2013 JPCERT/CC All rights reserved. 通常の処理 9 コンテンツをコピーする際の処理フロー ① クライアントからリクエストが送信される。 ② アプリケーションがリクエストを受信し、コピー元とコピー先のパスの 情報を取り出す。 ③ CopyOperationクラスのCopy関数でコピー処理を行う。 ④ 結果を含むレスポンスがクライアントへ送信される。
  • 10. Copyright©2013 JPCERT/CC All rights reserved. ①クライアントからリクエストが送信される 10 ここでは、ノード「/content/page/foo」とその配下のノード「orz1」 「orz2」を「/content」配下のノード「bar」としてコピーするリクエ ストが送られたとする。 content bar page foo orz1 orz2 orz1 orz1 コピー先 /content/bar コピー元 /content/page/foo
  • 11. Copyright©2013 JPCERT/CC All rights reserved. ①クライアントからリクエストが送信される 11 POST /content/bar HTTP/1.1 Host: localhost:8080 : @CopyFrom=/content/page/foo <form action=‘/content/bar’ method=‘POST’> : <input type=‘hidden’ name=‘@CopyFrom’ value=‘/content/page/foo’> : </form> HTTPリクエスト 上記HTTPリクエストを送信するためのHTML コンテンツのコピー元の ノードをパラメータ @CopyFromで指定する。 コンテンツのコピー先の ノードをパスで指定する
  • 12. Copyright©2013 JPCERT/CC All rights reserved. ②アプリケーションがリクエストを受信し、コピー処理を開始する 12 コピー処理はCopyOperationクラスのCopyメソッドで行われる。 POST /content/bar HTTP/1.1 Host: localhost:8080 : @CopyFrom=/content/page/foo HTTPリクエスト public class CopyOperation extends AbstractCopyMoveOperation{ : static Item copy(Node src, Node dstParent, String name) CopyOperation.java SlingPostServlet.doPost() ModifyOperation().run() ModifyOperation.doRun() ModifyOperation.processCopies() ModifyOperation.processMovesCopiesInternal() CopyOperation.copy() 経由するメソッド /content/bar /content/page/foo
  • 13. Copyright©2013 JPCERT/CC All rights reserved. ③CopyOperationクラスのCopyメソッドでコピー処理を行う 13 static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } return dst; } CopyOperation.java CopyOperationクラスのCopyメ ソッドでは下記の5つの処理が行わ れる。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じメソッドが再帰的 に呼ばれる) ① ② ③ ④ ⑤
  • 14. Copyright©2013 JPCERT/CC All rights reserved. ③CopyOperationクラスのCopyメソッドでコピー処理を行う 14 static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } return dst; } CopyOperationクラスのCopyメ ソッドでは下記の5つの処理が行わ れる。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じ関数が再帰的に 呼ばれる) static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } コンテンツのコピー先の ノード名が指定される コピー先 /content/bar コピー元 /content/page/foo コピー先のノード名(bar) CopyOperation.java
  • 15. Copyright©2013 JPCERT/CC All rights reserved. CopyOperationクラスのCopyメ ソッドでは下記の5つの処理が行わ れる。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じ関数が再帰的に 呼ばれる) ③CopyOperationクラスのCopyメソッドでコピー処理を行う 15 static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } return dst; } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } コピー先(/content/)に同 名のノード(bar)が存在 しないか確認し、存在す れば削除する。 コピー先 /content/bar コピー先のノード名 (bar) CopyOperation.java
  • 16. Copyright©2013 JPCERT/CC All rights reserved. ③CopyOperationクラスのCopyメソッドでコピー処理を行う 16 static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } return dst; } CopyOperationクラスのCopyメ ソッドでは下記の5つの処理が行わ れる。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じ関数が再帰的に 呼ばれる) // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } コピー先(/content/)にnameで指 定されたノード(bar)を作成する。 コピー先 /content/bar コピー先のノード名(bar) CopyOperation.java
  • 17. Copyright©2013 JPCERT/CC All rights reserved. ③CopyOperationクラスのCopyメソッドでコピー処理を行う 17 static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } return dst; } CopyOperationクラスのCopyメ ソッドでは下記の5つの処理が行わ れる。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じメソッドが再帰 的に呼ばれる) // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } コピー元(/content/page/foo)のプロパティ をコピー先(/content/bar)にコピーする。 ここで呼び出されているcopyメソッドは実 行中のメソッドとは別のオーバーロードさ れたメソッド。 コピー元 /content/page/foo コピー先 /content/bar CopyOperation.java
  • 18. Copyright©2013 JPCERT/CC All rights reserved. CopyOperationクラスのCopyメ ソッドでは下記の5つの処理が行わ れる。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じメソッドが再帰 的に呼ばれる) ③CopyOperationクラスのCopyメソッドでコピー処理を行う 18 static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } return dst; } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } コピー元に子ノードが存在する場合は再帰 的にcopyメソッドがコールされ、コピー処 理が行われる。 コピー元 /content/page/foo コピー先 /content/bar CopyOperation.java
  • 19. Copyright©2013 JPCERT/CC All rights reserved. ③CopyOperationクラスのCopyメソッドでコピー処理を行う 19 ■子ノードに対する再帰的なコピー処理 content page foo orz1 orz2 bar orz1 content page foo orz1 orz2 bar /content/page/foo が /content/bar にcopyメ ソッドでコピーされる。 copyメソッド内で再帰的にcopyメソッドが呼 ばれ、 /content/page/fooの子ノードである orz1が/content/bar/配下にコピーされる。
  • 20. Copyright©2013 JPCERT/CC All rights reserved. ③CopyOperationクラスのCopyメソッドでコピー処理を行う 20 content page foo orz1 orz2 bar orz1 orz2 content page foo orz1 orz2 bar orz1 orz2 さらにcopyメソッド内で再帰的にcopyメソッ ドが呼ばれ、 /content/page/fooの子ノードで あるorz2が/content/bar/配下にコピーされる。 ■子ノードに対する再帰的なコピー処理 /content/page/fooの全ての子ノードが /content/bar/配下にコピーされて、再帰的な処 理が終了する。
  • 21. Copyright©2013 JPCERT/CC All rights reserved. ④レスポンスがクライアントへ送信される。 21 コピー処理が終了し、結果をレスポンスとしてクライアントへ送信する。 Success!!
  • 22. Copyright©2013 JPCERT/CC All rights reserved. 攻撃コード 22 ■攻撃コードのポイント コピー対象のノードに対し、自分自身の子ノード配下に 自身をコピーするように指定している。 (親ノード→子ノードのコピー) POST /content/page/foo HTTP/1.1 Host: localhost:8080 : @CopyFrom=/content/page/ <form action=‘/content/page/foo’ method=‘POST’> : <input type=‘hidden’ name=‘@CopyFrom’ value=‘/content/page/’> : </form> 攻撃コードのHTTPリクエスト 攻撃コードのHTTPリクエストを送信するためのHTML コピー元ノード コピー先ノード content page foo コピー元 コピー先 子ノードへのコピー
  • 23. Copyright©2013 JPCERT/CC All rights reserved. 攻撃コード: 攻撃コードを受け取った際の処理 23 攻撃コードが実行された際の処理のフローは③のコピー処理にて無限 ループが発生する。 コンテンツをコピーする際の処理フロー ① クライアントからリクエストが送信される。 ② アプリケーションがリクエストを受信し、コピー元とコピー先の値を取 り出す ③ コピー処理を行う。 ④ 結果を含むレスポンスがクライアントへ送信される。
  • 24. Copyright©2013 JPCERT/CC All rights reserved. 攻撃コード実行時 ③CopyOperationクラスのCopyメソッドでコピー処理を行う 24 CopyOperationクラスのCopyメ ソッドでは下記の5つの処理が行わ れる。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じメソッドが再帰 的に呼ばれる) static Item copy(Node src, Node dstParent, String name) throws RepositoryException { // ensure destination name if (name == null) { name = src.getName(); } // ensure new node creation if (dstParent.hasNode(name)) { dstParent.getNode(name).remove(); } // create new node Node dst = dstParent.addNode(name, src.getPrimaryNodeType().getName()); for (NodeType mix : src.getMixinNodeTypes()) { dst.addMixin(mix.getName()); } // copy the properties for (PropertyIterator iter = src.getProperties(); iter.hasNext();) { copy(iter.nextProperty(), dst, null); } // copy the child nodes for (NodeIterator iter = src.getNodes(); iter.hasNext();) { Node n = iter.nextNode(); if (!n.getDefinition().isProtected()) { copy(n, dst, null); } } return dst; } CopyOperation.java copyメソッド内の5番目の処理で ある、子ノードを再帰的にコピー する処理でループが発生する!!
  • 25. Copyright©2013 JPCERT/CC All rights reserved. 攻撃コード実行時 ③CopyOperationクラスのCopyメソッドでコピー処理を行う 25 ■コピー元に「/content/page/」、コピー先に「/content/page/foo」を指定した 際のコピー処理 content page foo content page foo foo copyメソッドで/content/pageが /content/page/fooとしてコピーされる。 たった今コピーされた/content/page/fooが /content/pageの子ノードとして存在するため、 再帰的にコピー処理が実施されてしまう!! 無限ループの始まり!!
  • 26. Copyright©2013 JPCERT/CC All rights reserved.26 ■コピー元に「/content/page/」、コピー先に「/content/page/foo」を指定した 際のコピー処理 content page foo foo 再帰的にコピー処理が繰り返されること でループし続け、DoS攻撃が成立する!! foo foo 攻撃コード実行時 ③CopyOperationクラスのCopyメソッドでコピー処理を行う
  • 27. Copyright©2013 JPCERT/CC All rights reserved. 問題点とその対策  今回のアプリケーションにおける具体的な問題点 copyメソッドではメソッドの引数を検証せずにコピー処 理を行っていた。 以下のコーディングガイドに違反している!! 「MET00-J メソッドの引数を検証する」  問題点に対してどうすべきだったか。 処理対象のデータ構造(今回の場合はツリー構造)を考 慮して、copyメソッドの引数であるdstParentノードが src以下のノードでないことを確認した上で、コピー処理 を行うべきだった。 27
  • 28. Copyright©2013 JPCERT/CC All rights reserved. 修正版コード 28 ループが発生するコピー処理のコードが 修正されている。 コンテンツをコピーする際の処理フロー ① クライアントからリクエストが送信される。 ② アプリケーションがリクエストを受信し、コピー元とコピー先の値を取 り出す ③ コピー処理を行う。 ④ 結果を含むレスポンスがクライアントへ送信される。 脆弱性はバージョン2.1.3にて修正が適用されている
  • 29. Copyright©2013 JPCERT/CC All rights reserved. 修正前/修正後の処理比較 ③CopyOperationクラスのCopyメソッドでコピー処理を行う 29 CopyOperationクラスのCopyメソッ ドでは下記6つの処理が行われる。 isAncestorOrSameNode関数でコ ピー元とコピー先が同じツリーで ないことを確認する ① コピー先のノード名を確認 ② コピー先に既に同様の名前のノー ドが存在しないかを確認し、存在 すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先の ノードへプロパティ情報をコピー ⑤ コピー元の子ノードをコピー先に コピー(同じメソッドが再帰的に 呼ばれる) CopyOperationクラスのCopyメ ソッドでは下記5つの処理が行われ る。 ① コピー先のノード名を確認 ② コピー先に既に同様の名前の ノードが存在しないかを確認し、 存在すれば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先 のノードへプロパティ情報をコ ピー ⑤ コピー元の子ノードをコピー先 にコピー(同じメソッドが再帰 的に呼ばれる) 修正前の処理 修正後の処理 0
  • 30. Copyright©2013 JPCERT/CC All rights reserved. 修正版コード ③CopyOperationクラスのCopyメソッドでコピー処理を行う 30 static Item copy(Node src, Node dstParent, String name) throws RepositoryException { if(isAncestorOrSameNode(src, dstParent)) { throw new RepositoryException( "Cannot copy ancestor " + src.getPath() + " to descendant " + dstParent.getPath()); } // ensure destination name if (name == null) { name = src.getName(); } : } CopyOperation.java CopyOperationクラスのCopyメソッ ドでは下記6つの処理が行われる。 isAncestorOrSameNode関数でコ ピー元とコピー先が同じツリーでな いことを確認する ① コピー先のノード名を確認 ② コピー先に既に同様の名前のノード が存在しないかを確認し、存在すれ ば削除 ③ コピー先のノード作成 ④ コピー元のノードからコピー先の ノードへプロパティ情報をコピー ⑤ コピー元の子ノードをコピー先にコ ピー(同じ関数が再帰的に呼ばれ る) if(isAncestorOrSameNode(src, dstParent)) { throw new RepositoryException( "Cannot copy ancestor " + src.getPath() + " to descendant " + dstParent.getPath()); } コピー先 のノード情報 コピー元 のノード情報 0
  • 31. Copyright©2013 JPCERT/CC All rights reserved.31 static boolean isAncestorOrSameNode(Node src, Node dest) throws RepositoryException { if(src.getPath().equals("/")) { return true; } else if(src.getPath().equals(dest.getPath())) { return true; } else if(dest.getPath().startsWith(src.getPath() + "/")) { return true; } return false; } isAncestorOrSameNodeメソッド ①コピー元がルートディレクト リでないか ②コピー元とコピー先が同一の パスでないか ③コピー元とコピー先が同一の ツリーでないか ■isAncestorOrSameNodeメソッドではコピー元とコピー先のノードに対 して3つのチェックを行っている。 修正版コード ③CopyOperationクラスのCopyメソッドでコピー処理を行う
  • 32. Copyright©2013 JPCERT/CC All rights reserved.32 ■isAncestorOrSameNodeメソッドでのチェック内容のまとめ 下記の3つのチェックにより、無限ループが発生するようなコピー元/コピー先 の組み合わせが指定されていたら、エラーとして処理する。 ① コピー元がルートディレクトリでないか ② コピー元とコピー先が同一のパスでないか ③ コピー元とコピー先が同一のツリーでないか ■修正版コードに攻撃コードを実行するとどうなるか コピー元に「/content/page/」、コピー先に「/content/page/foo」が指定され ている ↓ 上記②のチェックでエラーとなり、無限ループは発生しな い!! 修正版コード ③CopyOperationクラスのCopyメソッドでコピー処理を行う
  • 33. Copyright©2013 JPCERT/CC All rights reserved. まとめ 33 ■この脆弱性から学べるプログラミングの注意点 • アプリケーションの処理内容や、扱うデータ構造に応じ た引数の検証をすべき • 今回のコピー処理は再帰的な動作であり、コピー対 象の指定の仕方によっては無限ループが発生する可能 性があることを考慮すべきであった。 ■上記への対策 • 再帰的な処理を実装する場合、無限ループにならない条 件(あるいは無限ループになる条件)を明確にし、その条件 を確認するコードを必ず入れる
  • 34. Copyright©2013 JPCERT/CC All rights reserved. 著作権・引用や二次利用について 本資料の著作権はJPCERT/CCに帰属します。 本資料あるいはその一部を引用・転載・再配布する際は、引用元名、資料名および URL の明示をお 願いします。 記載例 引用元:一般社団法人JPCERTコーディネーションセンター Java アプリケーション脆弱性事例解説資料 Apache Sling におけるサービス運用妨害(無限ループ)の脆弱性 https://www.jpcert.or.jp/research/materials-java-casestudies/No.1_Apache_Sling.pdf 本資料を引用・転載・再配布をする際は、引用先文書、時期、内容等の情報を、JPCERT コーディ ネーションセンター広報(office@jpcert.or.jp)までメールにてお知らせください。なお、この連絡に より取得した個人情報は、別途定めるJPCERT コーディネーションセンターの「プライバシーポリ シー」に則って取り扱います。 本資料の利用方法等に関するお問い合わせ JPCERTコーディネーションセンター 広報担当 E-mail:office@jpcert.or.jp 34 本資料の技術的な内容に関するお問い合わせ JPCERTコーディネーションセンター セキュアコーディング担当 E-mail:secure-coding@jpcert.or.jp