试图从这句话中删除“嘿,我明天来”。也尝试过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
请指导。谢谢。
答案 0 :(得分:1)
为什么要赞成准备好的陈述
当您自己创建SQL查询作为字符串时,它们几乎总是包含用户输入的一部分。攻击者可以例如通过使用'
巧妙地更改查询的语义,从而获得对数据的未授权访问或破坏数据来利用此优势。
这称为SQL注入,是最严重的关键安全风险之一,请参见此处: https://www.owasp.org/images/7/72/OWASP_Top_10-2017_%28en%29.pdf.pdf
防御
将准备好的语句与变量绑定(也称为参数化查询)一起使用是如何首先教所有开发人员如何编写数据库查询的方法。
如何在SQLite和iOS上使用准备好的语句
有关准备好的语句,请参见https://www.sqlite.org/c3ref/stmt.html。
基本步骤是:
这是一个简单的例子:
-(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));
}
因此这里使用'
例如来自用户输入的内容不会造成任何伤害,因为我们使用了准备好的语句。
演示
如果您在数据库实用程序中查看数据,则在此插入语句之后看起来像这样: