=htp #17067 port XXE fixes and tests from spray/spray#1024
This commit is contained in:
parent
71df8f810a
commit
0018bc2cda
4 changed files with 126 additions and 18 deletions
|
|
@ -5,6 +5,7 @@
|
|||
package akka.http.scaladsl.marshallers.xml
|
||||
|
||||
import java.io.{ ByteArrayInputStream, InputStreamReader }
|
||||
import javax.xml.parsers.{ SAXParserFactory, SAXParser }
|
||||
import scala.collection.immutable
|
||||
import scala.xml.{ XML, NodeSeq }
|
||||
import akka.stream.FlowMaterializer
|
||||
|
|
@ -26,15 +27,38 @@ trait ScalaXmlSupport {
|
|||
def nodeSeqUnmarshaller(ranges: ContentTypeRange*)(implicit fm: FlowMaterializer): FromEntityUnmarshaller[NodeSeq] =
|
||||
Unmarshaller.byteArrayUnmarshaller.forContentTypes(ranges: _*).mapWithCharset { (bytes, charset) ⇒
|
||||
if (bytes.length > 0) {
|
||||
val parser = XML.parser
|
||||
try parser.setProperty("http://apache.org/xml/properties/locale", java.util.Locale.ROOT)
|
||||
catch { case e: org.xml.sax.SAXNotRecognizedException ⇒ /* property is not needed */ }
|
||||
val reader = new InputStreamReader(new ByteArrayInputStream(bytes), charset.nioCharset)
|
||||
XML.withSAXParser(parser).load(reader): NodeSeq // blocking call! Ideally we'd have a `loadToFuture`
|
||||
XML.withSAXParser(createSAXParser()).load(reader): NodeSeq // blocking call! Ideally we'd have a `loadToFuture`
|
||||
} else NodeSeq.Empty
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a SAXParser for the NodeSeqUnmarshaller to use. Override to provide a custom SAXParser implementation.
|
||||
* Will be called once for for every request to be unmarshalled. The default implementation calls [[ScalaXmlSupport.createSaferSAXParser]].
|
||||
* @return
|
||||
*/
|
||||
protected def createSAXParser(): SAXParser = ScalaXmlSupport.createSaferSAXParser()
|
||||
}
|
||||
object ScalaXmlSupport extends ScalaXmlSupport {
|
||||
val nodeSeqContentTypes: immutable.Seq[ContentType] = List(`text/xml`, `application/xml`, `text/html`, `application/xhtml+xml`)
|
||||
val nodeSeqContentTypeRanges: immutable.Seq[ContentTypeRange] = nodeSeqContentTypes.map(ContentTypeRange(_))
|
||||
|
||||
/** Creates a safer SAXParser. */
|
||||
def createSaferSAXParser(): SAXParser = {
|
||||
val factory = SAXParserFactory.newInstance()
|
||||
import com.sun.org.apache.xerces.internal.impl.Constants
|
||||
import javax.xml.XMLConstants
|
||||
|
||||
factory.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE, false)
|
||||
factory.setFeature(Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE, false)
|
||||
factory.setFeature(Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE, true)
|
||||
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true)
|
||||
val parser = factory.newSAXParser()
|
||||
try {
|
||||
parser.setProperty("http://apache.org/xml/properties/locale", java.util.Locale.ROOT)
|
||||
} catch {
|
||||
case e: org.xml.sax.SAXNotRecognizedException ⇒ // property is not needed
|
||||
}
|
||||
parser
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue