mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-05-23 04:15:26 +00:00
fix(security): Security fix for WSTG-INPV-02. Add XSS protection on folders and mail title / content
This commit is contained in:
@@ -314,7 +314,7 @@ static NSString *userAgent = nil;
|
||||
|
||||
- (void) setText: (NSString *) newText
|
||||
{
|
||||
ASSIGN (text, newText);
|
||||
ASSIGN (text, [newText stringWithoutHTMLInjection: NO]);
|
||||
}
|
||||
|
||||
- (NSString *) text
|
||||
|
||||
@@ -74,6 +74,8 @@
|
||||
/* OpenSSL multiline DN */
|
||||
- (NSArray *) componentsFromMultilineDN;
|
||||
|
||||
- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode;
|
||||
|
||||
#ifndef GNUSTEP_BASE_LIBRARY
|
||||
- (BOOL) boolValue;
|
||||
#endif
|
||||
|
||||
@@ -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	

\\\\0]*a[\\s\\u200B	

\\\\0]*v[\\s\\u200B	

\\\\0]*a[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*c[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*i[\\s\\u200B	

\\\\0]*p[\\s\\u200B	

\\\\0]*t[\\s\\u200B	

\\\\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	

\\\\0]*b[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*i[\\s\\u200B	

\\\\0]*p[\\s\\u200B	

\\\\0]*t[\\s\\u200B	

\\\\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	

\\\\0]*i[\\s\\u200B	

\\\\0]*v[\\s\\u200B	

\\\\0]*e[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*c[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*i[\\s\\u200B	

\\\\0]*p[\\s\\u200B	

\\\\0]*t[\\s\\u200B	

\\\\0]*:"
|
||||
options: NSRegularExpressionCaseInsensitive error:&error];
|
||||
result = [regex stringByReplacingMatchesInString:result options:0 range:NSMakeRange(0, [result length]) withTemplate:@""];
|
||||
|
||||
// Remove <script
|
||||
regex = [NSRegularExpression regularExpressionWithPattern:@"<[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*c[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*i[\\s\\u200B	

\\\\0]*p[\\s\\u200B	

\\\\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	

\\\\0]*/[\\s\\u200B	

\\\\0]*s[\\s\\u200B	

\\\\0]*c[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*i[\\s\\u200B	

\\\\0]*p[\\s\\u200B	

\\\\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	

\\\\0]*i[\\s\\u200B	

\\\\0]*f[\\s\\u200B	

\\\\0]*r[\\s\\u200B	

\\\\0]*a[\\s\\u200B	

\\\\0]*m[\\s\\u200B	

\\\\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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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]]))
|
||||
|
||||
@@ -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"];
|
||||
|
||||
Reference in New Issue
Block a user