質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
DOM

DOMは、Document Object Modelの略で、HTML文書やXML文書をアプリケーションから利用するためのAPIです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

1回答

1931閲覧

DOMを利用して再帰的に走査する/HTMLを再構築する方法につきまして

pegy

総合スコア243

DOM

DOMは、Document Object Modelの略で、HTML文書やXML文書をアプリケーションから利用するためのAPIです。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2021/05/12 16:21

編集2021/05/12 16:25

やりたいことと試したこと

HTMLの構造を把握し、中身をチェックした上で改めて適切なHTMLを再構築したいと考えております。
調査した結果、そのための手段としてDOMを利用することが考えられることがわかり、例えば以下のようなコードを実行してみました。

html

1<!--$dataの中身--> 2<div id="wrapper"> 3 <p class="hoge" style="color:black;" onclick="js_alert()">aa<span style="background-color:hsl(60, 75%, 60%);">bb</span>aaa</p> 4 <img src="javascript:alert('​XSS!');"> 5 <p class="piyo"> 6 <script>alert("​XSS!")</script> 7 </p> 8</div>

php

1 $dom = new DOMDocument(); 2 $dom -> loadHTML($data); 3 $childNodes = $dom->getElementById('wrapper')->childNodes; 4 foreach ($childNodes as $key) { 5 var_dump($key->textContent);//aabbaaa 6 echo "<br>"; 7 var_dump($key->tagName); 8 if($key->tagName==="script"){ 9    //無害化 10    } 11 echo "<br>"; 12 var_dump($key->attributes); 13    if($key->tagName==="img" && substr($key->getAttribute('src'),0,4)==="java") 14    { 15    //無害化 16    } 17 echo "<br>"; 18 //再帰的な処理をして繰り返す 19 var_dump($key->childNodes); 20 }

問題点

ここに来て、いくつか解決すべき問題点に2つに気がつきました。

  1. 実際にHTMLの構造は深いものもあり、上記の自前で用意したHTMLではどこまでchildNodesを追跡すれば良いのか全貌がわかっているので対応できるのですが、HTML構造を事前に知らない場合など、DOMを利用してどのような方法で再帰的に走査することが一般的なのでしょうか? DomdocumentクラスのchildNodesプロパティで取得できる事は分かったのですが、NULLになるまで繰り返すようなやり方はしないと思うので、アドバイスをいただきたいです。

  2. また、構造に関連してvar_dump($key->textContent);//aabbaaaについて、テキストノードの中に要素ノードが混ざる場合でも、どの位置に要素ノードが入るかが示されず、textContentではaabbaaaを返してきます。このようなケースではDOMを利用してどのようにテキストと要素ノードの順番を解釈すれば良いのでしょうか?特にこの問題があるため↓#3のHTMLの再構築が非常に困難と感じています。

  3. 一般的に、DOMを利用して、上記のように解析した結果を踏まえてHTMLを再構築する場合、どのようなアプローチが取られるのでしょうか? まだ、無知な私には上記の走査を通じて、再構築しやすいような連想配列やJSON形式のデータを用意して、そこから一定のルールでechoしていくようなことくらいしか思いつかないのですが、一般的に採られる方法についてアドバイスを頂ければと思います。例えば、再構築目的の連想配列は以下のようなイメージです。あくまでイメージで、、全くとるべきアプローチとして間違っているのであればご指摘いただきたいです。。

php

1$ary = 2[ 3 [ 4 "tag"=>"p", 5 "attr"=> 6 ["class","style"], //onclickは消毒済み 7 "content1"=>"aa", 8 "content2"=>"aaa", 9 "insertTag"=> 10 [ 11 "tag"=>"span", 12 "attr"=>"class", 13 "content1"=>"bbb" 14 "insertTag" => NULL 15 ] 16 ] 17 18 [ 19 "tag"=>"img",//以下省略 20 ] 21]

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hoshi-takanori

2021/05/12 16:48

どんな環境で何のために再構築したいかによりますが、getElementById ってことはすでにブラウザで表示されてるものに対して操作するということで、その段階で「無害化」してもすでに手遅れでは…。
pegy

2021/05/12 21:42

夜分にコメントを頂き、有難うございます。 実際にはWYSIWYGから受け付けるHTML構造ですが、上記の$dataの例は飽くまで質問等のために作り出した構築になります。 宜しくお願い申し上げます。
chatii

2021/05/13 05:55

やりたいことって、 「DOMの再構築」じゃなくて「入力されたHTMLからXSSの脅威を取り除く」 じゃないんですか? DOMの再構築自体が目的になっているなら無視してもらっていいです
pegy

2021/05/13 07:44

コメントありがとうございます。 当初の目的は「入力されたHTMLからXSSの脅威を取り除く」で過去に質問を差し上げたのですが、結果的にDOMを走査して再構築する事で対応すべきというところで調べ、手を動かした結果、今回の質問に行き着きました。
guest

回答1

0

ベストアンサー

DOMXPathを利用すればよいのでは?

投稿2021/05/13 06:29

yambejp

総合スコア114583

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問