Copyright©2013 JPCERT/CC All rights reserved.「Javaアプリケーション脆弱性事例調査資料」についてこの資料は、Javaプログラマである皆様に、脆弱性を身近な問題として感じてもらい、セキュアコーディン...
Apache Sling におけるサービス運用妨害 (無限ループ) の脆弱性CVE-2012-2138JVNDB-2012-0030332
Copyright©2013 JPCERT/CC All rights reserved.Apache Sling とはWebサイトのコンテンツ管理を目的としたオープンソースのWebフレームワークコンテンツの管理方式としてApache Jack...
Copyright©2013 JPCERT/CC All rights reserved.JCR(Javaコンテンツリポジトリ)4• Javaコンテンツリポジトリはノードとプロパティのツリーで構成される。• ノード:ファイルシステムにおけるファ...
Copyright©2013 JPCERT/CC All rights reserved.5Apache Slingのノード管理画面ノードの一覧 index.htmlというノード(ファイル)のプロパティ(付属情報)JCR(Javaコンテンツリポ...
Copyright©2013 JPCERT/CC All rights reserved.Apache Sling のコンテンツ管理機能—Slingにはノードの作成・編集・削除・コピー・移動などを行う機能が存在する。—コピー機能を使うと、指定さ...
Copyright©2013 JPCERT/CC All rights reserved.脆弱性の概要—コピー機能にはサービス運用妨害(DoS)攻撃を受ける脆弱性が存在する。—コピーの際に、コピー元とコピー先に同一のファイルパスを指定すると、無...
Copyright©2013 JPCERT/CC All rights reserved.脆弱性が悪用された場合のリスク無限ループによりCPU/メモリリソースが枯渇し、サーバが応答しなくなる。その結果、提供されているサービスが停止する。提供して...
Copyright©2013 JPCERT/CC All rights reserved.通常の処理9コンテンツをコピーする際の処理フロー① クライアントからリクエストが送信される。② アプリケーションがリクエストを受信し、コピー元とコピー先の...
Copyright©2013 JPCERT/CC All rights reserved.①クライアントからリクエストが送信される10ここでは、ノード「/content/page/foo」とその配下のノード「orz1」「orz2」を「/cont...
Copyright©2013 JPCERT/CC All rights reserved.①クライアントからリクエストが送信される11POST /content/bar HTTP/1.1Host: localhost:8080:@CopyFro...
Copyright©2013 JPCERT/CC All rights reserved.②アプリケーションがリクエストを受信し、コピー処理を開始する12コピー処理はCopyOperationクラスのCopyメソッドで行われる。POST /co...
Copyright©2013 JPCERT/CC All rights reserved.③CopyOperationクラスのCopyメソッドでコピー処理を行う13static Item copy(Node src, Node dstParen...
Copyright©2013 JPCERT/CC All rights reserved.③CopyOperationクラスのCopyメソッドでコピー処理を行う14static Item copy(Node src, Node dstParen...
Copyright©2013 JPCERT/CC All rights reserved.CopyOperationクラスのCopyメソッドでは下記の5つの処理が行われる。① コピー先のノード名を確認② コピー先に既に同様の名前のノードが存在し...
Copyright©2013 JPCERT/CC All rights reserved.③CopyOperationクラスのCopyメソッドでコピー処理を行う16static Item copy(Node src, Node dstParen...
Copyright©2013 JPCERT/CC All rights reserved.③CopyOperationクラスのCopyメソッドでコピー処理を行う17static Item copy(Node src, Node dstParen...
Copyright©2013 JPCERT/CC All rights reserved.CopyOperationクラスのCopyメソッドでは下記の5つの処理が行われる。① コピー先のノード名を確認② コピー先に既に同様の名前のノードが存在し...
Copyright©2013 JPCERT/CC All rights reserved.③CopyOperationクラスのCopyメソッドでコピー処理を行う19■子ノードに対する再帰的なコピー処理contentpagefooorz1orz2...
Copyright©2013 JPCERT/CC All rights reserved.③CopyOperationクラスのCopyメソッドでコピー処理を行う20contentpagefooorz1orz2barorz1orz2content...
Copyright©2013 JPCERT/CC All rights reserved.④レスポンスがクライアントへ送信される。21コピー処理が終了し、結果をレスポンスとしてクライアントへ送信する。Success!!
Copyright©2013 JPCERT/CC All rights reserved.攻撃コード22■攻撃コードのポイントコピー対象のノードに対し、自分自身の子ノード配下に自身をコピーするように指定している。(親ノード→子ノードのコピー)P...
Copyright©2013 JPCERT/CC All rights reserved.攻撃コード: 攻撃コードを受け取った際の処理23攻撃コードが実行された際の処理のフローは③のコピー処理にて無限ループが発生する。コンテンツをコピーする際の...
Copyright©2013 JPCERT/CC All rights reserved.攻撃コード実行時③CopyOperationクラスのCopyメソッドでコピー処理を行う24CopyOperationクラスのCopyメソッドでは下記の5つ...
Copyright©2013 JPCERT/CC All rights reserved.攻撃コード実行時③CopyOperationクラスのCopyメソッドでコピー処理を行う25■コピー元に「/content/page/」、コピー先に「/co...
Copyright©2013 JPCERT/CC All rights reserved.26■コピー元に「/content/page/」、コピー先に「/content/page/foo」を指定した際のコピー処理contentpagefoofo...
Copyright©2013 JPCERT/CC All rights reserved.問題点とその対策 今回のアプリケーションにおける具体的な問題点copyメソッドではメソッドの引数を検証せずにコピー処理を行っていた。以下のコーディングガ...
Copyright©2013 JPCERT/CC All rights reserved.修正版コード28ループが発生するコピー処理のコードが修正されている。コンテンツをコピーする際の処理フロー① クライアントからリクエストが送信される。② ア...
Copyright©2013 JPCERT/CC All rights reserved.修正前/修正後の処理比較③CopyOperationクラスのCopyメソッドでコピー処理を行う29CopyOperationクラスのCopyメソッドでは下...
Copyright©2013 JPCERT/CC All rights reserved.修正版コード③CopyOperationクラスのCopyメソッドでコピー処理を行う30static Item copy(Node src, Node ds...
Copyright©2013 JPCERT/CC All rights reserved.31static boolean isAncestorOrSameNode(Node src, Node dest) throwsRepositoryEx...
Copyright©2013 JPCERT/CC All rights reserved.32■isAncestorOrSameNodeメソッドでのチェック内容のまとめ下記の3つのチェックにより、無限ループが発生するようなコピー元/コピー先の組...
Copyright©2013 JPCERT/CC All rights reserved.まとめ33■この脆弱性から学べるプログラミングの注意点• アプリケーションの処理内容や、扱うデータ構造に応じた引数の検証をすべき• 今回のコピー処理は再帰...
Copyright©2013 JPCERT/CC All rights reserved.著作権・引用や二次利用について本資料の著作権はJPCERT/CCに帰属します。本資料あるいはその一部を引用・転載・再配布する際は、引用元名、資料名および ...
Upcoming SlideShare
Loading in …5
×

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

675 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
675
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
0
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

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

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

×