説明
信頼できないXMLの解析でDTDや外部エンティティ参照を許可すると、ローカルファイルの読み取り、内部・外部アドレスへのリクエスト、エンティティ展開によるリソース消費を引き起こされるおそれがあります。
JAXPの XMLConstants.FEATURE_SECURE_PROCESSING を明示的に false にすると、実装のセキュリティ制限が無効になります。JDKのAPIで true を設定すると処理量と外部アクセスが制限されますが、実装やランタイムが異なる環境もあるため、この機能だけで完全なXXE対策とは考えないでください。DTDの使用と外部DTD・スキーマへのアクセスも個別に制限してください。
XMLReaderFactory はJava 9から非推奨のため、新しいコードには SAXParserFactory を使ってください。ただし、古いAPIの使用自体が脆弱性を意味するわけではありません。実際の保護設定と信頼境界を確認してください。
想定される影響
- 機密ファイルの漏えい: アプリケーションが読み取れるローカルファイルが露出する可能性があります。
- サーバーサイドリクエストフォージェリ(SSRF): 内部サービスや攻撃者のサーバーへリクエストを送られるおそれがあります。
- サービス拒否: エンティティ展開やXML処理によって、CPUやメモリを使い果たす可能性があります。
対処方法
- 不要なDTDを拒否してください。 JDK 25ではJAXP設定またはJVMシステムプロパティの
jdk.xml.dtd.support=denyを優先してください。パーサー単位ではhttp://apache.org/xml/features/disallow-doctype-declをtrueに設定します。 - 安全な処理と外部アクセス制限を明示してください。
XMLConstants.FEATURE_SECURE_PROCESSINGをtrueにし、XMLConstants.ACCESS_EXTERNAL_DTDとXMLConstants.ACCESS_EXTERNAL_SCHEMAを空文字列にして外部プロトコルを拒否してください。 - DTDが必要なら許可範囲を絞ってください。 外部一般エンティティ、外部パラメーターエンティティ、外部DTDの読み込みを無効にしてください。必要なリソースだけをローカルXMLカタログや確認済みリゾルバーで解決し、有限の処理制限を維持してください。
例
変更前
java
import java.io.InputStream;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;
public final class UnsafeXXE {
static void parse(InputStream xml) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, false);
SAXParser parser = factory.newSAXParser();
parser.parse(xml, new DefaultHandler());
}
}
安全な処理の制限を明示的に無効にし、DTDや外部アクセスも制限せずに入力を解析しています。
ローカルな保護設定を省略したインライン解析も確認してください。
java
import jakarta.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilderFactory;
public final class InlineServletXXE {
static void parse(HttpServletRequest request) throws Exception {
DocumentBuilderFactory.newInstance()
.newDocumentBuilder()
.parse(request.getInputStream());
}
}
ファクトリーの作成から解析までが一つの式にまとまり、途中でファクトリーやパーサーを設定する箇所がありません。ただし、デプロイ全体のJAXP設定でDTDと外部アクセスを拒否していれば、実行時には保護される場合があります。
変更後
java
import java.io.InputStream;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.helpers.DefaultHandler;
public final class SafeXXE {
static void parse(InputStream xml) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature(
"http://apache.org/xml/features/disallow-doctype-decl",
true
);
SAXParser parser = factory.newSAXParser();
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, "");
parser.setProperty(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
parser.parse(xml, new DefaultHandler());
}
}
DTDが不要な場合の例です。安全な処理を有効にするだけでなく、DOCTYPE を拒否し、外部DTDとスキーマへのアクセスも明示的に遮断します。
参考資料
- Oracle Java 25 JAXP Security Guide
- Oracle Java 25
XMLConstants - Oracle Java 25
DocumentBuilderFactory - Oracle Java 25
SAXParserFactory - Oracle Java 25
XMLReaderFactory - OWASP XML External Entity Prevention Cheat Sheet
- OWASP ASVS 5.0.0 V1.5.1
- CWE-611: Improper Restriction of XML External Entity Reference