use super::builder::*;
pub fn zip_bomb() -> Vec<u8> {
let mut sheet = String::with_capacity(20_000_048);
sheet.push_str("<worksheet><sheetData><row r=\"1\"><c r=\"A1\" t=\"str\"><v>");
sheet.extend(std::iter::repeat_n('A', 20_000_000));
sheet.push_str("</v></c></row></sheetData></worksheet>");
build_zip(&[
(
"xl/_rels/workbook.xml.rels",
rels_xml(&[
("rId1", "worksheet", "worksheets/sheet1.xml"),
("rId2", "styles", "styles.xml"),
])
.as_bytes(),
),
(
"xl/workbook.xml",
workbook_xml(&[("Sheet1", "rId1", None)]).as_bytes(),
),
("xl/styles.xml", DEFAULT_STYLES_XML),
("xl/worksheets/sheet1.xml", sheet.as_bytes()),
])
}
pub fn sparse_merge_bounding_box_amplification() -> Vec<u8> {
const NUM_FILLER_MERGES: usize = 19_999;
const NUM_DATA_CELLS: usize = 300_000;
let mut merges = String::new();
for i in 0..NUM_FILLER_MERGES {
let col = (i % 16_384) + 1;
let row = 2 + (i / 16_384);
let a1 = format!("{}{row}", column_letters(col as u32));
merges.push_str(&format!("<mergeCell ref=\"{a1}:{a1}\"/>"));
}
merges.push_str("<mergeCell ref=\"XFD1048576:XFD1048576\"/>");
let merge_cells_xml = format!(
"<mergeCells count=\"{}\">{merges}</mergeCells>",
NUM_FILLER_MERGES + 1
);
let mut rows = String::new();
for i in 0..NUM_DATA_CELLS {
let col = (i % 16_384) + 1;
let row = 500_000 + (i / 16_384);
rows.push_str(&format!(
"<row r=\"{row}\"><c r=\"{}{row}\" s=\"0\"><v>1</v></c></row>\n",
column_letters(col as u32)
));
}
build_zip(&[
(
"xl/_rels/workbook.xml.rels",
rels_xml(&[
("rId1", "worksheet", "worksheets/sheet1.xml"),
("rId2", "styles", "styles.xml"),
])
.as_bytes(),
),
(
"xl/workbook.xml",
workbook_xml(&[("Sheet1", "rId1", None)]).as_bytes(),
),
("xl/styles.xml", DEFAULT_STYLES_XML),
(
"xl/worksheets/sheet1.xml",
worksheet_xml(&rows, &merge_cells_xml).as_bytes(),
),
])
}
fn column_letters(mut n: u32) -> String {
let mut buf = Vec::new();
while n > 0 {
let rem = ((n - 1) % 26) as u8;
buf.push(b'A' + rem);
n = (n - 1) / 26;
}
buf.reverse();
String::from_utf8(buf).unwrap()
}
pub fn zip_slip() -> Vec<u8> {
let rows = r#"<row r="1"><c r="A1"><v>1</v></c></row>"#;
build_zip(&[
(
"xl/_rels/workbook.xml.rels",
rels_xml(&[
("rId1", "worksheet", "worksheets/sheet1.xml"),
("rId2", "styles", "styles.xml"),
])
.as_bytes(),
),
(
"xl/workbook.xml",
workbook_xml(&[("Sheet1", "rId1", None)]).as_bytes(),
),
("xl/styles.xml", DEFAULT_STYLES_XML),
(
"xl/worksheets/sheet1.xml",
worksheet_xml(rows, "").as_bytes(),
),
(
"../../../../../../../tmp/evil.txt",
b"planted by a Zip Slip attack",
),
])
}
pub fn xxe_attack() -> Vec<u8> {
let malicious_workbook = br#"<?xml version="1.0"?>
<!DOCTYPE workbook [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<workbook xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships">
<sheets>
<sheet name="Sheet1" sheetId="1" r:id="rId1"/>
</sheets>
</workbook>"#;
let rows = r#"<row r="1"><c r="A1"><v>1</v></c></row>"#;
build_zip(&[
(
"xl/_rels/workbook.xml.rels",
rels_xml(&[
("rId1", "worksheet", "worksheets/sheet1.xml"),
("rId2", "styles", "styles.xml"),
])
.as_bytes(),
),
("xl/workbook.xml", malicious_workbook),
("xl/styles.xml", DEFAULT_STYLES_XML),
(
"xl/worksheets/sheet1.xml",
worksheet_xml(rows, "").as_bytes(),
),
])
}