Swift应用安全:新手必知的十大漏洞

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Swift 应用安全:初学者必知的十大漏洞

使用 Swift 开发移动和桌面应用不仅需要了解语法和框架,还需要理解网络安全的基础知识。即使是代码中的一个小错误也可能导致用户数据泄露或设备被入侵。在本文中,我们将分析初学者开发者常遇到的十大 Swift 应用常见漏洞,并展示如何避免它们。

1. 不安全的存储(Insecure Data Storage)

最常见的错误之一是将敏感信息(密码、令牌、API 密钥)保存在 UserDefaults 或普通文本文件中。这些数据在越狱设备上很容易被提取。

// 错误做法:在 UserDefaults 中存储密码
UserDefaults.standard.set("mySecretPassword", forKey: "userPassword")

// 正确做法:使用 Keychain
import Security
let password = "mySecretPassword"
let keychainItem = [
    kSecClass: kSecClassGenericPassword,
    kSecAttrAccount: "userPassword",
    kSecValueData: password.data(using: .utf8)!
] as CFDictionary
SecItemAdd(keychainItem, nil)

2. 针对 SQLite 和 Core Data 的注入

在数据库查询中使用未处理的字符串会为 SQL 注入打开大门。即使您使用 Core Data,不安全的谓词也可能受到攻击。

// 错误做法:直接替换
let username = "admin' OR '1'='1"
let query = "SELECT * FROM users WHERE name = '\(username)'"

// 正确做法:使用参数化查询(FMDB)
let query = "SELECT * FROM users WHERE name = ?"
db.executeQuery(query, withArgumentsIn: [username])

3. 缺少 HTTPS 和 SSL Pinning

使用 HTTP 而不是 HTTPS 会使应用容易受到中间人攻击(MITM)。即使使用 HTTPS,也建议使用 SSL Pinning 进行额外保护。

// 在 Info.plist 中配置 HTTPS
// <key>NSAppTransportSecurity</key>
// <dict>
//     <key>NSAllowsArbitraryLoads</key>
//     <false/>
// </dict>

// 使用 URLSession 实现 SSL Pinning
let pinnedKeys = ["yourPublicKeyHash"]
let delegate = URLSessionPinningDelegate(pinnedKeys: pinnedKeys)
let session = URLSession(configuration: .default, delegate: delegate, delegateQueue: nil)

4. 弱加密算法

使用过时的加密算法(MD5、SHA1)或自制的加密函数会使数据变得脆弱。始终使用现代库。

// 错误做法:MD5
let hash = MD5(string: "password")

// 正确做法:使用 CommonCrypto 的 SHA256
import CommonCrypto
func sha256(_ data: Data) -> Data {
    var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
    data.withUnsafeBytes {
        _ = CC_SHA256($0.baseAddress, CC_LONG(data.count), &hash)
    }
    return Data(hash)
}

5. 输入验证不足(Input Validation)

缺少对用户输入的验证可能导致 XSS 攻击(在 WebView 中)或数据损坏。请检查所有输入数据的长度、格式和内容。

// 错误做法:信任输入
let userInput = textField.text
webView.loadHTMLString(userInput!, baseURL: nil)

// 正确做法:清理输入
func sanitizeInput(_ input: String) -> String {
    return input
        .replacingOccurrences(of: "&", with: "&")
        .replacingOccurrences(of: "<", with: "<")
        .replacingOccurrences(of: ">", with: ">")
}

6. 通过日志和调试泄露数据

留在生产环境中的 print() 或 NSLog 可能会泄露敏感数据。请使用条件编译来处理调试消息。

// 错误做法:在生产环境中记录日志                

博客

书籍推荐