package fuzion24.device.vulnerability.vulnerabilities.framework.zip; import android.content.Context; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipException; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import fuzion24.device.vulnerability.util.CPUArch; import fuzion24.device.vulnerability.vulnerabilities.VulnerabilityTest; public class ZipBug8219321 implements VulnerabilityTest { @Override public List<CPUArch> getSupportedArchitectures() { ArrayList<CPUArch> archs = new ArrayList<>(); archs.add(CPUArch.ALL); return archs; } public String getCVEorID(){ return "CVE-2013-4787"; } private static void replaceBytes(byte[] original, byte[] replacement, byte[] buffer) throws Exception { // Gotcha here: original and replacement must be the same length if(original.length != replacement.length) throw new Exception("Original Length is not equal to replacement length"); boolean found; for(int i=0; i < buffer.length - original.length; i++) { found = false; if (buffer[i] == original[0]) { found = true; for (int j=0; j < original.length; j++) { if (buffer[i+j] != original[j]) { found = false; break; } } } if (found) { for (int j=0; j < original.length; j++) { buffer[i+j] = replacement[j]; } } } } /** * Make sure we don't fail silently for duplicate entries. * b/8219321 */ public boolean isVulnerable(Context context) throws Exception { String entryName = "test_file_name1"; String tmpName = "test_file_name2"; // create the template data ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); ZipOutputStream out = new ZipOutputStream(bytesOut); ZipEntry ze1 = new ZipEntry(tmpName); out.putNextEntry(ze1); out.closeEntry(); ZipEntry ze2 = new ZipEntry(entryName); out.putNextEntry(ze2); out.closeEntry(); out.close(); // replace the bytes we don't like byte[] buf = bytesOut.toByteArray(); replaceBytes(tmpName.getBytes(), entryName.getBytes(), buf); // write the result to a file File outputDir = context.getCacheDir(); File badZip = File.createTempFile("prefix", "extension", outputDir); badZip.deleteOnExit(); FileOutputStream outstream = new FileOutputStream(badZip); outstream.write(buf); outstream.close(); // see if we can still handle it try (ZipFile bad = new ZipFile(badZip)) { return true; } catch (ZipException expected) { if(expected.getMessage().contains("Duplicate entry name")) return false; else throw expected; } } }