NSPredicate - predicateWithFormat 不安全

Posted

技术标签:

【中文标题】NSPredicate - predicateWithFormat 不安全【英文标题】:NSPredicate - predicateWithFormat insecure 【发布时间】:2018-06-27 11:02:57 【问题描述】:

我在核心数据库中有一个查询谓词,但我不知道验证其参数的正确方法是什么?

- (void) queryToDatabaseWithStoreId:(NSInteger) storeId 
   [NSPredicate predicateWithFormat:@"store.storeId = %d", storeId];

我的问题是如何验证 storeId 参数或我需要使用什么来消除该漏洞?

如果我有一个清单:

- (void) queryToDataBaseWithListStore:(NSArray<Store *> *) storeList 
   [NSPredicate predicateWithFormat:@"store.storeId IN %@", [storeList valueForObject:@"storeId"]];

https://developer.apple.com/library/archive/documentation/Security/Conceptual/SecureCodingGuide/Articles/ValidatingInput.html#//apple_ref/doc/uid/TP40007246-SW3

我需要避免这种情况:

以下常用函数和方法容易受到格式字符串攻击:

标准 C

printf(3) 手册页中列出的 printf 和其他函数 sscanf 和 scanf(3) 手册页上列出的其他函数 syslog 和 vsyslog

AEBuildDesc 和 vAEBuildDesc AEBuildParameters 和 vAEBuildParameters AEBuildAppleEvent 和 vAEBuildAppleEvent 核心基础 CFStringCreateWithFormat CFStringCreateWithFormatAndArguments CFStringAppendFormat CFStringAppendFormatAndArguments

可可

stringWithFormat:、initWithFormat: 和其他将格式化字符串作为参数的 NSString 方法 appendFormat:在 NSMutableString 类中 alertWithMessageText:defaultButton:alternateButton:otherButton:informativeTextWithFormat: 在 NSAlert predicateWithFormat:、predicateWithFormat:arguments: 和 predicateWithFormat:argumentArray: 在 NSPredicate 中 raise:format: 和 raise:format:arguments: 在 NSException NSRunAlertPanel 和其他创建或返回面板或工作表的 AppKit 函数

避免这种攻击的最佳方法是什么?

【问题讨论】:

您在问题中发布的代码中没有漏洞。阅读您发布的链接。它清楚地解释了在什么条件下字符串格式可能会出现问题。您的使用不是其中之一。 安全审计报告我说:predicate = [NSPredicate predicateWithFormat:@"sectionId = %d", [binnacleNote.sectionId intValue]];我认为该变量可以在执行时间上发生变化,但我不确定。 当您无法控制实际的格式字符串时,格式中的任何漏洞都会出现。由于您已将特定格式字符串硬编码到谓词中,因此没有问题。 他的建议是:验证数据的格式、长度、类型和范围,但我不确定,因为如果攻击者可以修改我的变量,那么攻击者也可以修改验证。 嗯嗯好的,谢谢!当攻击者可以通过 predicateWithFormat 做某事时,你能举个例子吗? 【参考方案1】:

我已经编写了这门课,但我不知道是否足够。

@implementation StringUtils

+ (BOOL) isEmpty:(id) text 
    if ([text isKindOfClass:[NSNull class]]) 
        return YES;
     else 
        if (text) 
            if ([text isKindOfClass:[NSString class]]) 
                NSString *textStr = [NSString stringWithFormat:@"%@", text];
                return [textStr isEqualToString:@""];
            
            return YES;
         else 
            return YES;
        
    


+ (NSString *) validateField:(id) text 

    NSInteger numErrors = 0;
    NSString *pattern = @"[^A-Za-z0-9-]+";
    NSError *error = nil;

    NSString *textValidated = @"";
    if ([text isKindOfClass:[NSNumber class]]) 
        textValidated = [text stringValue];
     else if ([text isKindOfClass:[NSString class]]) 
        textValidated = text;
     else 
        @try 
            textValidated = [text stringValue];
         @catch (NSException *exception) 
            numErrors=+1;
        
    

    //Only numbers && chars && -
    NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
    NSRange textRange = NSMakeRange(0, textValidated.length);
    NSRange matchRange = [regex rangeOfFirstMatchInString:textValidated options:NSMatchingReportProgress range:textRange];
    if (matchRange.location != NSNotFound) 
        numErrors+=1;
    

    //Not empty string
    if ([StringUtils isEmpty:textValidated]) 
        numErrors+=1;
    

    if (numErrors == 0) 
        return textValidated;
    
    return @"";


+ (NSArray *) validateArrayFields:(NSArray *) list 

    NSInteger *numErrors = 0;
    for (id obj in list) 
        if ([StringUtils isEmpty:[StringUtils validateField:obj]]) 
            numErrors+=1;
        
    

    if (numErrors == 0) 
        return list;
    

    return [[NSArray alloc] init];


@end

正常使用:

[NSPredicate predicateWithFormat:@"store.storeId = %@", [StringUtils validateField:storeId]];

用于数组:

[NSPredicate predicateWithFormat:@"store.storeId IN %@", [StringUtils validateArrayFields:storeId]];

【讨论】:

以上是关于NSPredicate - predicateWithFormat 不安全的主要内容,如果未能解决你的问题,请参考以下文章

NSPredicate

NSPredicate 谓词

子查询中的 NSPredicate

NSPredicate 问题

NSPredicate 字符串

NSPredicate == 查询