@@ -353,12 +353,32 @@ class Libxml2BadOption extends EnumConstant {
353353}
354354
355355/**
356- * A configuration for tracking XML objects and their states .
356+ * An XML library or interface .
357357 */
358- class XXEConfiguration extends DataFlow:: Configuration {
359- XXEConfiguration ( ) { this = "XXEConfiguration" }
358+ abstract class XmlLibrary extends string {
359+ bindingset [ this ]
360+ XmlLibrary ( ) { any ( ) } // required characteristic predicate
360361
361- override predicate isSource ( DataFlow:: Node node , string flowstate ) {
362+ /**
363+ * The source node for a potentially unsafe configuration object for this XML
364+ * library, along with `flowstate` representing its initial state.
365+ */
366+ abstract predicate configurationSource ( DataFlow:: Node node , string flowstate ) ;
367+
368+ /**
369+ * The sink node where an unsafe configuration object is used to interpret
370+ * XML.
371+ */
372+ abstract predicate configurationSink ( DataFlow:: Node node , string flowstate ) ;
373+ }
374+
375+ /**
376+ * The `XercesDOMParser` interface for the Xerces XML library.
377+ */
378+ class XercesDomParserLibrary extends XmlLibrary {
379+ XercesDomParserLibrary ( ) { this = "XercesDomParserLibrary" }
380+
381+ override predicate configurationSource ( DataFlow:: Node node , string flowstate ) {
362382 // source is the write on `this` of a call to the `XercesDOMParser`
363383 // constructor.
364384 exists ( CallInstruction call |
@@ -367,14 +387,46 @@ class XXEConfiguration extends DataFlow::Configuration {
367387 call .getThisArgument ( ) and
368388 encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
369389 )
370- or
390+ }
391+
392+ override predicate configurationSink ( DataFlow:: Node node , string flowstate ) {
393+ // sink is the read of the qualifier of a call to `parse`.
394+ exists ( Call call |
395+ call .getTarget ( ) instanceof ParseFunction and
396+ call .getQualifier ( ) = node .asConvertedExpr ( )
397+ ) and
398+ flowstate instanceof XercesFlowState and
399+ not encodeXercesFlowState ( flowstate , 1 , 1 ) // safe configuration
400+ }
401+ }
402+
403+ /**
404+ * The createLSParser interface for the Xerces XML library.
405+ */
406+ class CreateLSParserLibrary extends XmlLibrary {
407+ CreateLSParserLibrary ( ) { this = "CreateLSParserLibrary" }
408+
409+ override predicate configurationSource ( DataFlow:: Node node , string flowstate ) {
371410 // source is the result of a call to `createLSParser`.
372411 exists ( Call call |
373412 call .getTarget ( ) instanceof CreateLSParser and
374413 call = node .asExpr ( ) and
375414 encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
376415 )
377- or
416+ }
417+
418+ override predicate configurationSink ( DataFlow:: Node node , string flowstate ) {
419+ none ( ) // uses the existing sinks from `XercesDomParserLibrary`
420+ }
421+ }
422+
423+ /**
424+ * The SAXParser interface for the Xerces XML library.
425+ */
426+ class SaxParserLibrary extends XmlLibrary {
427+ SaxParserLibrary ( ) { this = "SaxParserLibrary" }
428+
429+ override predicate configurationSource ( DataFlow:: Node node , string flowstate ) {
378430 // source is the write on `this` of a call to the `SAXParser`
379431 // constructor.
380432 exists ( CallInstruction call |
@@ -383,18 +435,44 @@ class XXEConfiguration extends DataFlow::Configuration {
383435 call .getThisArgument ( ) and
384436 encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
385437 )
386- or
438+ }
439+
440+ override predicate configurationSink ( DataFlow:: Node node , string flowstate ) {
441+ none ( ) // uses the existing sinks from `XercesDomParserLibrary`
442+ }
443+ }
444+
445+ /**
446+ * The SAX2XMLReader interface for the Xerces XML library.
447+ */
448+ class Sax2XmlReaderLibrary extends XmlLibrary {
449+ Sax2XmlReaderLibrary ( ) { this = "Sax2XmlReaderLibrary" }
450+
451+ override predicate configurationSource ( DataFlow:: Node node , string flowstate ) {
387452 // source is the result of a call to `createXMLReader`.
388453 exists ( Call call |
389454 call .getTarget ( ) instanceof CreateXmlReader and
390455 call = node .asExpr ( ) and
391456 encodeXercesFlowState ( flowstate , 0 , 1 ) // default configuration
392457 )
393- or
394- // source is an `options` argument on a `libxml2` parse call that specifies
458+ }
459+
460+ override predicate configurationSink ( DataFlow:: Node node , string flowstate ) {
461+ none ( ) // uses the existing sinks from `XercesDomParserLibrary`
462+ }
463+ }
464+
465+ /**
466+ * The libxml2 XML library.
467+ */
468+ class LibXml2Library extends XmlLibrary {
469+ LibXml2Library ( ) { this = "LibXml2Library" }
470+
471+ override predicate configurationSource ( DataFlow:: Node node , string flowstate ) {
472+ // source is an `options` argument on a libxml2 parse call that specifies
395473 // at least one unsafe option.
396474 //
397- // note: we don't need to track an XML object for ` libxml2` , so we don't
475+ // note: we don't need to track an XML object for libxml2, so we don't
398476 // really need data flow. Nevertheless we jam it into this configuration,
399477 // with matching sources and sinks. This allows results to be presented by
400478 // the same query, in a consistent way as other results with flow paths.
@@ -409,22 +487,29 @@ class XXEConfiguration extends DataFlow::Configuration {
409487 )
410488 }
411489
412- override predicate isSink ( DataFlow:: Node node , string flowstate ) {
413- // sink is the read of the qualifier of a call to `parse`.
414- exists ( Call call |
415- call .getTarget ( ) instanceof ParseFunction and
416- call .getQualifier ( ) = node .asConvertedExpr ( )
417- ) and
418- flowstate instanceof XercesFlowState and
419- not encodeXercesFlowState ( flowstate , 1 , 1 ) // safe configuration
420- or
490+ override predicate configurationSink ( DataFlow:: Node node , string flowstate ) {
421491 // sink is the `options` argument on a `libxml2` parse call.
422492 exists ( Libxml2ParseCall call , Expr options |
423493 options = call .getOptions ( ) and
424494 node .asExpr ( ) = options and
425495 flowstate = "libxml2"
426496 )
427497 }
498+ }
499+
500+ /**
501+ * A configuration for tracking XML objects and their states.
502+ */
503+ class XXEConfiguration extends DataFlow:: Configuration {
504+ XXEConfiguration ( ) { this = "XXEConfiguration" }
505+
506+ override predicate isSource ( DataFlow:: Node node , string flowstate ) {
507+ any ( XmlLibrary l ) .configurationSource ( node , flowstate )
508+ }
509+
510+ override predicate isSink ( DataFlow:: Node node , string flowstate ) {
511+ any ( XmlLibrary l ) .configurationSink ( node , flowstate )
512+ }
428513
429514 override predicate isAdditionalFlowStep (
430515 DataFlow:: Node node1 , string state1 , DataFlow:: Node node2 , string state2
0 commit comments