首页 > 解决方案 > 在发布 DTD/XXE XML 时测试 Scala Play 行为

问题描述

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

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

400: Bad Request我的问题是,当我到达我的路线时,由于 Play 应用程序捕获了 DTD ,我得到了预期的错误。但是,当我尝试通过单元测试完成路线时,我得到一个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也很脆弱,并且知道如何修复它。我的测试在这一行是否行为不端,如果是这样,是否有另一种方法可以在不评估和解释 DTD 的情况下盲目地将 XML 传递给我的测试方法?

标签: xmlscalatestingplayframeworkxxe

解决方案


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"}"""
    }
  }
}

推荐阅读