发布时测试 Scala Play 行为 DTD/XXE XML

Testing Scala Play behaviour when posting DTD/XXE XML

我正在尝试通过单元测试来测试我的 Scala Play 应用程序,但是我在测试中遇到的行为与我在通过 Postman 向我的路由发送 POST 请求时遇到的行为不同。

我正在尝试测试 Scala Play 应用程序是否可以处理任何包含 DTD 的 XML,因为我正在尝试证明我可以免受 XXE 攻击。根据 James Roper,Play 被修补为拒绝 XML 由于潜在漏洞而默认包含 DTD。

我的问题是,当我到达我的路线时,由于 Play 应用程序捕获 DTD,我收到了预期的 400: Bad Request 错误。但是,当我尝试通过我的单元测试走路线时,我得到了 200: Ok,因此测试的行为与实际的 Play 应用程序不同。

这是我的控制器代码:

def handlePost(): Action[NodeSeq] = Action.async(parse.xml) {
  implicit request =>
    Future.successful(Ok(request.body))
}

在幕后的某个时候,POST连接到此控制器似乎在 Action.async(parse.xml) 失败。我还将 request.body 换成其他一些随机 XML 以验证它是否在我的代码中触及请求正文之前失败。

我的测试用例:

class RoutesSpec extends PlaySpec with GuiceOneAppPerSuite {
  "The POST route" must {
    "not handle XXE XML" in {
      val xml: Elem = scala.xml.XML.loadString(
        """<?xml version="1.0" encoding="utf-8"?>
          |<!DOCTYPE foo [
          |<!ELEMENT foo (bar)>
          | <!ELEMENT bar (#PCDATA)>
          |]>
          |<foo>
          | <bar>string</bar>
          |</foo>
        """.stripMargin)
      val Some(result) = route(app, FakeRequest(POST_REQUEST, "/my-route")
        .withXmlBody(xml))
      status(result) mustEqual 400 // currently returns 200
    }
  }
}

我有两个问题:

  1. 有谁知道如何影响我的测试,使其表现得更像我的应用程序?

  1. 我知道 XML.loadString 也容易受到攻击,并且知道如何修复它。我的测试是否在这一行行为不当,如果是这样,是否有另一种方法可以盲目地将 XML 传递给我的测试方法而不对其进行评估和解释 DTD?

scala.xml.Unparsed 似乎可以完成这项工作。我认为是 scala.xml.XML.loadString 中的漏洞让我感到困惑。

class RoutesSpec extends PlaySpec with GuiceOneAppPerSuite {
  "The POST route" must {
    "not handle XXE XML" in {
      val xml = scala.xml.Unparsed(
        """<?xml version="1.0" encoding="utf-8"?>
          |<!DOCTYPE foo [
          |<!ELEMENT foo (bar)>
          | <!ELEMENT bar (#PCDATA)>
          |]>
          |<foo>
          | <bar>string</bar>
          |</foo>
        """.stripMargin)

      val Some(result) = route(app, FakeRequest(POST_REQUEST, "/my-route")
        .withXmlBody(xml))

      status(result) mustEqual 400
      contentAsString(result) mustBe """{"statusCode":400,"message":"bad request"}"""
    }
  }
}