diff --git a/SoObjects/Mailer/SOGoDraftObject.m b/SoObjects/Mailer/SOGoDraftObject.m index 905efa103..0f55fb2b9 100644 --- a/SoObjects/Mailer/SOGoDraftObject.m +++ b/SoObjects/Mailer/SOGoDraftObject.m @@ -314,7 +314,7 @@ static NSString *userAgent = nil; - (void) setText: (NSString *) newText { - ASSIGN (text, newText); + ASSIGN (text, [newText stringWithoutHTMLInjection: NO]); } - (NSString *) text diff --git a/SoObjects/SOGo/NSString+Utilities.h b/SoObjects/SOGo/NSString+Utilities.h index 371666613..07867adbd 100644 --- a/SoObjects/SOGo/NSString+Utilities.h +++ b/SoObjects/SOGo/NSString+Utilities.h @@ -74,6 +74,8 @@ /* OpenSSL multiline DN */ - (NSArray *) componentsFromMultilineDN; +- (NSString *) stringWithoutHTMLInjection: (BOOL)stripHTMLCode; + #ifndef GNUSTEP_BASE_LIBRARY - (BOOL) boolValue; #endif diff --git a/SoObjects/SOGo/NSString+Utilities.m b/SoObjects/SOGo/NSString+Utilities.m index 14ae989e7..c8b63383f 100644 --- a/SoObjects/SOGo/NSString+Utilities.m +++ b/SoObjects/SOGo/NSString+Utilities.m @@ -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:@"" 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