[iOS] 在iOS裡操作SQLite筆記 –SQLite 的SQL injection 隱碼攻擊 防範方式 (四)

  • 5185
  • 0
  • iOS
  • 2014-09-12

摘要:[iOS] 在iOS裡操作SQLite筆記 –SQLite 的SQL injection 隱碼攻擊 防範方式 (四)

在你的App當中使用SQLite資料庫,大多的情形就是一個App一個使用者,然後裡面包含一個SQLite資料庫。

不會像網站上的資料庫,有許多不同的使用者來連結資料庫。在網站上被對應到的資料庫,SQL injection的課題的重要性可能就不需要多提了。

放在App中的SQLite對於SQL injection這個議題防範到底重不重要?可能就是每個人自己評估了,因為除非故意,

自己去刪掉自己資料庫裡面的東西機率看起來也不大,不過這一篇還是稍微來介紹一下在SQLite資料庫裡面的防範資料庫隱碼攻擊的方法。

至少避免使用者幹掉自己的資料庫,還很XX的來Challenge你程式寫的爛….

 

在前幾個範例之中,我都是用使用者輸入的資訊來組合出我們要下的SQL指令,在這樣的方法中,就會有遭隱碼攻擊的弱點。

例如:

在之前的範例中,我用底下的方式來合成查詢條件,


NSString *sql2 = [NSString stringWithFormat:@"select * from country where engname = %@",self.mytitle.text];

正常的情況下,我預期他組合出來的資料庫指令要如下:

select * from country where engname = 1

但是在隱碼攻擊的時候,可能使用者輸入的資料會讓我組成下方的語法,進而幫助你手刃你的資料庫。

select * from country where engname = 1;DROP TABLE country;--

 

 

不管是對資料庫的增刪改查哪一種指令,只要是利用使用者輸入的字串來組合SQL指令都會有這些風險,

在SQLite裡面提供我們使用參數查詢(parameterized queries)來解決這個問題,在SQLite3,可以使用

parameterized queries來置換SQL statement裡面的 ?  字元。以上面討論的新增資料進資料庫,我們要做底下的修改。

 

首先假設你要修改資料庫的一筆欄位值,需要準備下方的語法。


NSString* safeSqlString = @"UPDATE record SET name=? where id=?";

 

接下執行這個SQL語法來建立SQLStatment


sqlite3_stmt* statement;

if(sqlite3_prepare(database, [safeSqlString UTF8String], -1, &statement, NULL) != SQLITE_OK)

{

  // Add your error handling code here

}

 

最後則是用綁定的方式,把真正要寫入資料庫的值或者是你的查詢條件的欄位值,傳給SQL指令執行.


if(sqlite3_bind_text(statement, 1, [record.name UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK)

{

  // Add your error handling code here

}

 

那來看一下這樣的指令在上一個章節的部分,程式碼要怎麼來修改?先來看新增資料的指令    


 sqlite3_stmt *stmt;

    //建立新增指令

    char *sql = "INSERT INTO country (engname,chname) VALUES (?,?);";

    if (sqlite3_prepare_v2(db, sql, -1, &stmt, nil) == SQLITE_OK) {

            //真正建立資料庫的指令

            NSString * engname = self.mytitle.text;

            NSString * chname = self.mydetail.text;

            //綁定真正要寫入資料庫的值

            sqlite3_bind_text(stmt, 1, [engname UTF8String], -1, NULL);

            sqlite3_bind_text(stmt, 2, [chname UTF8String], -1, NULL);


            if (sqlite3_step(stmt) != SQLITE_DONE) // ALWAYS RETURNS Error: NULL

                NSLog(@"Error updating table: %s", sqlite3_errmsg(db));

            sqlite3_reset(stmt);

    }

        //清除sqlite3_stmt物件

        sqlite3_finalize(stmt);

 

這樣修改就完成了新增資料的部分。

 

在查詢子句中我們也要做一些修正,


- (IBAction)querydata:(id)sender{

    //建立查詢語法

    NSString* safeSqlString =[NSString stringWithFormat:@"select * from country where engname = ?"];

    //建立條件參數

    NSString* engname = [NSString stringWithFormat:@"%@",self.mytitle.text];

    //建立sqlite3_stmt物件

    sqlite3_stmt* statement;

    if (sqlite3_prepare_v2(db, [safeSqlString UTF8String], -1, &statement,nil) == SQLITE_OK) {

        //置換綁定的參數值

        if(sqlite3_bind_text(statement, 1, [engname UTF8String], -1, NULL) != SQLITE_OK)

        {//Error Handling Code

            NSAssert1(0,@"code1%s",sqlite3_errmsg(db));

            sqlite3_finalize(statement);

            return;

        }

        sqlite3_reset(statement);

        TabelDatas = [self statementtoMSarray:statement];

        [self.mytable reloadData];

    } else {

        NSLog(@"%s",sqlite3_errmsg(db));

    }

    sqlite3_finalize(statement);

}

 

 

參考資料

How to prevent SQL Injection in iOS apps?

http://technet.weblineindia.com/mobile/how-to-prevent-sql-injection-in-ios-apps/2/

iOS Quick Tips: Avoiding SQL injection attacks with parameterized queries in sqlite3

http://code-ninja.org/blog/2012/02/19/ios-quick-tips-avoiding-sql-injection-attacks-with-parameterized-queries-in-sqlite3/