fix(security): Security fix for WSTG-INPV-02. Add XSS protection on folders and mail title / content

This commit is contained in:
smizrahi
2022-11-14 14:36:41 +01:00
parent 967479335c
commit 714acfc838
9 changed files with 91 additions and 8 deletions
+1 -1
View File
@@ -314,7 +314,7 @@ static NSString *userAgent = nil;
- (void) setText: (NSString *) newText
{
ASSIGN (text, newText);
ASSIGN (text, [newText stringWithoutHTMLInjection: NO]);
}
- (NSString *) text
+2
View File
@@ -74,6 +74,8 @@
/* OpenSSL multiline DN */
- (NSArray *) componentsFromMultilineDN;
- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode;
#ifndef GNUSTEP_BASE_LIBRARY
- (BOOL) boolValue;
#endif
+81
View File
@@ -891,4 +891,85 @@ static int cssEscapingCount;
return result;
}
/**
* Get the safe string avoiding HTML injection
* @param stripHTMLCode Remove all HTML code from content
* @return A safe string
*/
- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode
{
NSString *result, *text;
NSScanner *theScanner;
NSError *error;
NSRegularExpression *regex;
text = nil;
error = nil;
regex = nil;
result = [NSString stringWithString: self];
if (stripHTMLCode) {
// Author : https://www.codercrunch.com/question/1251681838/how-remove-html-tags-string-ios
theScanner = [NSScanner scannerWithString: result];
while ([theScanner isAtEnd] == NO) {
// find start of tag
[theScanner scanUpToString: @"<" intoString: NULL];
// find end of tag
[theScanner scanUpToString: @">" intoString: &text];
// replace the found tag with a space
//(you can filter multi-spaces out later if you wish)
result = [result stringByReplacingOccurrencesOfString:
[NSString stringWithFormat: @"%@>", text]
withString: @" "];
}
} else {
// Clean XSS
// Examples of injection : https://cheatsheetseries.owasp.org/cheatsheets/XSS_Filter_Evasion_Cheat_Sheet.html#xss-locator-polygot
result = [self stringByReplacingOccurrencesOfString:@"<script" withString:@""];
result = [result stringByReplacingOccurrencesOfString:@"</script>" withString:@""];
// Remove javascript:
regex = [NSRegularExpression regularExpressionWithPattern:@"j[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*a[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*v[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*a[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*s[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*c[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*i[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*p[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*t[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*:"
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@""];
// Remove vbscript:
regex = [NSRegularExpression regularExpressionWithPattern:@"v[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*b[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*s[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*i[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*p[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*t[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*:"
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@""];
// Remove livescript:
regex = [NSRegularExpression regularExpressionWithPattern:@"l[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*i[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*v[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*e[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*s[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*c[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*i[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*p[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*t[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*:"
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@""];
// Remove <script
regex = [NSRegularExpression regularExpressionWithPattern:@"<[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*s[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*c[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*i[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*p[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*t"
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"<scr***"];
// Remove </script
regex = [NSRegularExpression regularExpressionWithPattern:@"<[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*/[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*s[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*c[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*i[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*p[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*t"
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"</scr***"];
// Remove <iframe
regex = [NSRegularExpression regularExpressionWithPattern:@"<[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*i[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*f[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*r[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*a[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*m[\\s\\u200B&#x09;&#x0A;&#x0D;\\\\0]*e"
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"<ifr***"];
// Remove onload
regex = [NSRegularExpression regularExpressionWithPattern:@"onload="
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"onl***="];
// Remove onmouseover
regex = [NSRegularExpression regularExpressionWithPattern:@"onmouseover="
options: NSRegularExpressionCaseInsensitive error:&error];
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@"onmouseo***="];
}
return result;
}
@end
+1 -1
View File
@@ -61,7 +61,7 @@
request = [context request];
params = [[request contentAsString] objectFromJSONString];
name = [params objectForKey: @"name"];
name = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES];
nameInContainer = nil;
if ([name length] > 0)
+1 -1
View File
@@ -198,7 +198,7 @@
return [NSDictionary dictionaryWithObjectsAndKeys:
[self className], @"type",
type, @"contentType",
[[self generateResponse] contentAsString], @"content",
[[[self generateResponse] contentAsString] stringWithoutHTMLInjection: NO], @"content",
[self filenameForDisplay], @"filename",
[self preferredPathExtension], @"extension",
[[self sizeFormatter] stringForObjectValue: [bodyInfo objectForKey: @"size"]], @"size",
+2 -2
View File
@@ -76,7 +76,7 @@
request = [context request];
params = [[request contentAsString] objectFromJSONString];
folderName = [params objectForKey: @"name"];
folderName = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES];
if ([folderName length] > 0)
{
encodedFolderName = [folderName stringByEncodingImap4FolderName];
@@ -142,7 +142,7 @@
// Retrieve new folder name from JSON payload
request = [context request];
params = [[request contentAsString] objectFromJSONString];
newFolderName = [params objectForKey: @"name"];
newFolderName = [[params objectForKey: @"name"] stringWithoutHTMLInjection: YES];
if (!newFolderName || [newFolderName length] == 0)
{
+1 -1
View File
@@ -976,7 +976,7 @@
[msg addObject: [NSNumber numberWithBool: [self isMessageFlagged]]];
// Subject
[msg addObject: [self messageSubject]];
[msg addObject: [[self messageSubject] stringWithoutHTMLInjection: YES]];
// From
from = [[message objectForKey: @"envelope"] from];
+1 -1
View File
@@ -347,7 +347,7 @@ static NSString *mailETag = nil;
if ([self formattedDate])
[data setObject: [self formattedDate] forKey: @"date"];
if ([self messageSubject])
[data setObject: [self messageSubject] forKey: @"subject"];
[data setObject: [[self messageSubject] stringWithoutHTMLInjection: YES] forKey: @"subject"];
if ((addresses = [addressFormatter dictionariesForArray: [co fromEnvelopeAddresses]]))
[data setObject: addresses forKey: @"from"];
if ((addresses = [addressFormatter dictionariesForArray: [co toEnvelopeAddresses]]))
+1 -1
View File
@@ -182,7 +182,7 @@ _intValueFromHex (NSString *hexString)
fActiveTasks = [folder activeTasks];
[calendar setObject: folderName forKey: @"id"];
[calendar setObject: fDisplayName forKey: @"name"];
[calendar setObject: [fDisplayName stringWithoutHTMLInjection: YES] forKey: @"name"];
[calendar setObject: [folder calendarColor] forKey: @"color"];
isActive = [NSNumber numberWithBool: [folder isActive]];
[calendar setObject: isActive forKey: @"active"];