Skip to content
This repository has been archived by the owner on Dec 26, 2020. It is now read-only.

Commit

Permalink
Add supports for OLE package into Word detector.
Browse files Browse the repository at this point in the history
  • Loading branch information
righettod committed Feb 27, 2016
1 parent c55b8a8 commit 0a16ef9
Show file tree
Hide file tree
Showing 22 changed files with 12,903 additions and 589 deletions.
4 changes: 0 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ The reason why Aspose API have been used into this POC are the following:

* Trial version of the APIs can be used for detection only and it's seems that there not license limitation about this type of specific usage (see links below and don't hesitate to ping me if i'm wrong :smiley: ).

# TODO

* Add detection of OLE packages into Word / Excel documents.

# Information links

* http://www.aspose.com/community/forums/thread/335727/what-are-the-trial-limitation-of-aspose.words.net.aspx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
import com.aspose.words.Document;
import com.aspose.words.FileFormatInfo;
import com.aspose.words.FileFormatUtil;
import com.aspose.words.NodeCollection;
import com.aspose.words.NodeType;
import com.aspose.words.Shape;

/**
* Implementation of the detector for Microsoft Word document.
Expand All @@ -29,8 +32,7 @@ public class WordDocumentDetectorImpl implements DocumentDetector {
* We reject MHTML file because:<br>
* <ul>
* <li>API cannot detect macro into this format</li>
* <li>Is not normal to use this format to represent a Word file (there
* plenty of others supported format)</li>
* <li>Is not normal to use this format to represent a Word file (there plenty of others supported format)</li>
* </ul>
*/
private static final List<String> ALLOWED_FORMAT = Arrays.asList(new String[] { "doc", "docx", "docm", "wml", "dot", "dotm" });
Expand All @@ -40,6 +42,7 @@ public class WordDocumentDetectorImpl implements DocumentDetector {
*
* @see eu.righettod.poc.detector.DocumentDetector#isSafe(java.io.File)
*/
@SuppressWarnings("rawtypes")
@Override
public boolean isSafe(File f) {
boolean safeState = false;
Expand All @@ -53,9 +56,30 @@ public boolean isSafe(File f) {
Document document = new Document(f.getAbsolutePath());
// Get safe state from Macro presence
safeState = !document.hasMacros();
// If document is safe then we pass to OLE objects analysis
if (safeState) {
// Get all shapes of the document
NodeCollection shapes = document.getChildNodes(NodeType.SHAPE, true);
Shape shape = null;
// Search OLE objects in all shapes
int totalOLEObjectCount = 0;
for (int i = 0; i < shapes.getCount(); i++) {
shape = (Shape) shapes.get(i);
// Check if the current shape has OLE object
if (shape.getOleFormat() != null) {
totalOLEObjectCount++;
}
}
// Update safe status flag according to number of OLE object found
if (totalOLEObjectCount != 0) {
safeState = false;
}

}
}
}
} catch (Exception e) {
}
catch (Exception e) {
safeState = false;
LOG.warn("Error during Word file analysis !", e);
}
Expand Down
27 changes: 19 additions & 8 deletions src/main/java/eu/righettod/poc/web/DocumentUpload.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@
import eu.righettod.poc.detector.ExcelDocumentDetectorImpl;
import eu.righettod.poc.detector.PdfDocumentDetectorImpl;
import eu.righettod.poc.detector.WordDocumentDetectorImpl;
import eu.righettod.poc.sanitizer.DocumentSanitizer;
import eu.righettod.poc.sanitizer.ImageDocumentSanitizerImpl;

/**
* Servlet to receive the uploaded file.<br>
* It verify if the uploaded document is safe and if it's OK then continue processing...<br>
* For Excel/Word/Pdf document: It verify if the uploaded document is safe and if it's OK then continue processing...<br>
* For Image: Try to sanitize the uploaded document and if it succeed to sanitize it then continue processing...<br>
* Try to use, as much as possible, file upload feature provided by JEE >= 7
*
*/
Expand Down Expand Up @@ -64,37 +67,45 @@ protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws S
}

// Write a temporary file with uploaded file
tmpFile = File.createTempFile("detector", null);
tmpFile = File.createTempFile("uploaded-", null);
tmpPath = tmpFile.toPath();
long copiedBytesCount = Files.copy(filePart.getInputStream(), tmpPath, StandardCopyOption.REPLACE_EXISTING);
if (copiedBytesCount != filePart.getSize()) {
throw new IOException(String.format("Error during stream copy to temporary disk (copied: %s / expected: %s !", copiedBytesCount, filePart.getSize()));
}

/* Step 2: Initialize a detector for the target file type and perform validation */
// Instanciate the dedicated detector implementation
/* Step 2: Initialize a detector/sanitizer for the target file type and perform validation */
// Init the safety state flag
boolean isSafe = false;

// Instanciate the dedicated detector/sanitizer implementation and apply detection/sanitizing
DocumentDetector documentDetector = null;
DocumentSanitizer documentSanitizer = null;
switch (fileType) {
case "PDF":
documentDetector = new PdfDocumentDetectorImpl();
isSafe = documentDetector.isSafe(tmpFile);
break;
case "WORD":
documentDetector = new WordDocumentDetectorImpl();
isSafe = documentDetector.isSafe(tmpFile);
break;
case "EXCEL":
documentDetector = new ExcelDocumentDetectorImpl();
isSafe = documentDetector.isSafe(tmpFile);
break;
case "IMAGE":
documentSanitizer = new ImageDocumentSanitizerImpl();
isSafe = documentSanitizer.madeSafe(tmpFile);
break;
default:
throw new IllegalArgumentException("Unknow file type specified !");
}

// Apply detection
boolean isSafe = documentDetector.isSafe(tmpFile);

/* Step 3 : Take decision based on sfa status detected */
// Take action is the file is not safe
if (!isSafe) {
LOG.warn("Detection of a unsafe file upload !");
LOG.warn("Detection of a unsafe file upload or cannot sanitize uploaded document !");
// Remove temporary file
safelyRemoveFile(tmpPath);
// Return error
Expand Down
37 changes: 19 additions & 18 deletions src/main/webapp/index.jsp
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<title>POC</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
File format:
<select id="fileType" name="fileType">
<option value="WORD">Microsoft Office Word</option>
<option value="EXCEL">Microsoft Office Excel</option>
<option value="PDF">Adobe PDF</option>
</select><br>
Select file to upload: <input type="file" name="fileContent" id="fileContent"><br><input type="submit" value="Upload file" name="submit">
</form>
</body>
</html>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<title>POC</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
File format:
<select id="fileType" name="fileType">
<option value="WORD">Microsoft Office Word</option>
<option value="EXCEL">Microsoft Office Excel</option>
<option value="PDF">Adobe PDF</option>
<option value="IMAGE">Image</option>
</select><br>
Select file to upload: <input type="file" name="fileContent" id="fileContent"><br><input type="submit" value="Upload file" name="submit">
</form>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,22 @@ public void testUnSafeXLTDocumentWithOLE() throws IOException {
Assert.assertFalse(safeState);
}

/**
* Test case for XLTM format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeXLTMDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.xltm");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for XLTX format with OLE object.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,4 +225,132 @@ public void testUnSafeDOTMDocument() throws IOException {
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for DOC format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeDOCDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.doctest-with-ole-object.doc");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for DOCM format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeDOCMDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.doctest-with-ole-object.docm");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for DOCX format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeDOCXDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.doctest-with-ole-object.docx");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for DOT format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeDOTDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.doctest-with-ole-object.dot");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for DOTM format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeDOTMDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.doctest-with-ole-object.dotm");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for DOTX format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeDOTXDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.doctest-with-ole-object.dotx");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for MTHML format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeMTHMLDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object.doctest-with-ole-object.mht");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}

/**
* Test case for WordML format with OLE object.
*
* @throws IOException
*
*/
@Test
public void testUnSafeWordMLDocumentWithOLE() throws IOException {
// Prepare test
File sample = new File(SAMPLES_DIRECTORY, "test-with-ole-object-word2003xml.xml");
// Run test
boolean safeState = this.victim.isSafe(sample);
// Validate test
Assert.assertFalse(safeState);
}
}
Binary file not shown.
Binary file modified src/test/resources/excel/test-without-macro.xls
Binary file not shown.
Binary file modified src/test/resources/excel/test-without-macro.xlsb
Binary file not shown.
Binary file modified src/test/resources/excel/test-without-macro.xlsm
Binary file not shown.
Loading

0 comments on commit 0a16ef9

Please sign in to comment.