如何在sqlite查询中从NSString中删除'

时间:2019-01-03 13:19:38

标签: ios objective-c xcode sqlite

试图从这句话中删除“嘿,我明天来”。也尝试过stringByReplacingOccurrencesOfString,但不起作用。请帮助寻找解决方案,因为我已经在此浪费了超过半天的时间。以下是查询以及我尝试过的内容以及输出,请检查

 NSMutableString *msql = [[NSMutableString alloc] initWithFormat:@"insert into %@ ", tableName];
        for (int i=0; i<[arrArguments count]; i++){
            NSMutableArray *marrArgum = [arrArguments objectAtIndex:i];

            if (i==0){
[msql appendFormat:@"SELECT '%@' AS 'id', '%@' AS 'UserID', '%@' AS 'MessageID', '%@' AS 'ActualMessage', '\%@\' AS 'MessageType', '%@' AS 'MessageIsOld', '%@' AS 'MessageSentBySelf', '%@' AS 'Timestamp', '%@' AS 'MessageRead', '%@' AS 'MessageToUser' ", [marrArgum objectAtIndex:0], [marrArgum objectAtIndex:1], [marrArgum objectAtIndex:2], [marrArgum objectAtIndex:3], [marrArgum objectAtIndex:4], [marrArgum objectAtIndex:5], [marrArgum objectAtIndex:6], [marrArgum objectAtIndex:7], [marrArgum objectAtIndex:8], [marrArgum objectAtIndex:9]];

}
            else{
                [msql appendFormat:@"UNION ALL SELECT '%@', '%@', '%@', '\%@\', '%@', '%@', '%@', '%@', '%@', '%@' ", [marrArgum objectAtIndex:0], [marrArgum objectAtIndex:1], [marrArgum objectAtIndex:2], [marrArgum objectAtIndex:3], [marrArgum objectAtIndex:4], [marrArgum objectAtIndex:5], [marrArgum objectAtIndex:6], [marrArgum objectAtIndex:7], [marrArgum objectAtIndex:8], [marrArgum objectAtIndex:9]];
            }

NSString *sql = [NSString stringWithFormat: @"%@", msql];
DBLog(@"INSERT SQL QUERY: %@", sql);
        METHOD_CALLER;
        int intQcheck = sqlite3_exec(sqliteDB, [sql UTF8String], NULL, NULL, &err);
        DBLog(@"intQcheck = %d", intQcheck);
        if (intQcheck!= SQLITE_OK) {
            if ([self targetAppIsUsingDevProfile])
                NSAssert(0, @"Error in Insertion Query(intQcheck=%d): %@", intQcheck, strMsql);
            success = NO;
        }

我尝试过的是:

NSString *strMsql = [sql stringByReplacingOccurrencesOfString:@"'" withString:@"\'"];

但是它不起作用。输出仍然与先前的相同:

i’ll see u you

请指导。谢谢。

1 个答案:

答案 0 :(得分:1)

为什么要赞成准备好的陈述

当您自己创建SQL查询作为字符串时,它们几乎总是包含用户输入的一部分。攻击者可以例如通过使用'巧妙地更改查询的语义,从而获得对数据的未授权访问或破坏数据来利用此优势。

这称为SQL注入,是最严重的关键安全风险之一,请参见此处: https://www.owasp.org/images/7/72/OWASP_Top_10-2017_%28en%29.pdf.pdf

防御

  

将准备好的语句与变量绑定(也称为参数化查询)一起使用是如何首先教所有开发人员如何编写数据库查询的方法。

https://www.owasp.org/index.php/SQL_Injection_Prevention_Cheat_Sheet#Defense_Option_1:_Prepared_Statements_.28with_Parameterized_Queries.29

如何在SQLite和iOS上使用准备好的语句

有关准备好的语句,请参见https://www.sqlite.org/c3ref/stmt.html

基本步骤是:

  • 创建准备好的语句
  • 将值绑定到参数
  • 运行SQL
  • 销毁对象以避免资源泄漏

这是一个简单的例子:

-(BOOL)insertValue:(NSString *)value intoDB:(sqlite3 *)db {
    sqlite3_stmt *stmt = NULL;
    NSString *insertStmt = @"insert into SomeTable (sometext) values (?)";
    //create the prepared statement
    if(SQLITE_OK == sqlite3_prepare_v2(db, insertStmt.UTF8String, -1, &stmt, NULL)) {
        //bind values to parameters
        if(SQLITE_OK == sqlite3_bind_text(stmt, 1, value.UTF8String, -1, SQLITE_STATIC)) {
            //run the SQL
            if(SQLITE_DONE != sqlite3_step(stmt)) {
                return NO;
            }
        }
        else {
            return NO;
        }
        //destroy the object to avoid resource leaks
        sqlite3_finalize(stmt);
    }
    else {
        return NO;
    }
    return YES;
}

将为您的示例字符串i'll see u you调用,如下所示:

sqlite3 *db;
if(SQLITE_OK == sqlite3_open(dbURL.absoluteString.UTF8String, &db)) {
    NSString *someValue = @"i'll see u you";
    if (![self insertValue:someValue intoDB:db]) {
        NSLog(@"insert failed: '%s'", sqlite3_errmsg(db));
    }
    sqlite3_close(db);
}
else {
    NSLog(@"open db failed: '%s'", sqlite3_errmsg(db));
}

因此这里使用'例如来自用户输入的内容不会造成任何伤害,因为我们使用了准备好的语句。

演示

如果您在数据库实用程序中查看数据,则在此插入语句之后看起来像这样:

screenshot