Swift站在前沿:为什么安全不是选项,而是必需
\n您用Swift编写代码,为性能和代码美观而自豪。但您是否想过,您的应用对攻击有多脆弱?SQL注入和XSS(跨站脚本攻击)不仅仅是教科书上的恐怖故事。它们是真实的威胁,可能让您付出用户数据、声誉和金钱的代价。
\n在本文中,我们将探讨如何保护Swift应用(无论是iOS客户端还是基于Vapor的服务器端)免受这两种最危险的攻击类型。没有废话——只有实用示例、现成解决方案和真实代码。开始吧!
\n\nSwift中的SQL注入:黑客如何“欺骗”数据库
\n想象一下:用户在文本框中输入'; DROP TABLE Users; --。如果您直接将这个字符串拼接到SQL查询中,数据库将执行删除命令。经典案例。
在Swift中,这种漏洞最常见于服务器端框架(Vapor、Kitura)或在使用Core Data和SQLite通过不安全的封装时。
\n\n危险示例:错误做法
\nimport SQLite\n\nlet username = userInput.text // "admin' OR '1'='1"\nlet query = "SELECT * FROM users WHERE name = '\\(username)'"\ntry db.execute(query) // 威胁!被篡改的查询\n\n这段代码就像斗牛的红布。攻击者可以访问任何数据或删除表。
\n\n正确方法:参数化查询
\n黄金法则:永远不要将用户数据直接插入查询字符串。使用参数化。
\nimport SQLite\n\nlet db = try Connection("path/to/db.sqlite3")\nlet users = Table("users")\nlet name = Expression<String>("name")\n\nlet username = userInput.text // "admin' OR '1'='1"\nlet query = users.filter(name == username) // 安全\nlet result = try db.prepare(query)\n\nSQLite.swift库会自动转义特殊字符。对于使用Fluent的Vapor,请使用模型和过滤器:
\nimport Fluent\nimport Vapor\n\nstruct UserController: RouteCollection {\n func login(req: Request) async throws -> String {\n let input = try req.content.decode(LoginRequest.self)\n // Fluent自动参数化查询\n let user = try await User.query(on: req.db)\n .filter(\\.$name == input.username)\n .first()\n return user?.name ?? "Not found"\n }\n}\n\n重要:即使在Vapor中使用raw SQL,也要使用SQLBind绑定参数。
ORM和Core Data:安全的假象
\n许多开发者认为Core Data或Fluent会自动防止注入。这是真的——只要您不使用带字符串格式化的NSExpression或raw SQL。但请记住:任何通过字符串插值构建的NSPredicate都存在风险。
// 危险\nlet predicate = NSPredicate(format: "name == %@", userInput) // 安全?\n// 不!如果userInput包含'%',可能通过替换发生注入。\n\n始终使用带变量的%@,而不是带键的%K,并且永远不要通过\\()插入字符串。
Swift中的XSS攻击:当攻击者注入JavaScript
\nXSS是一种攻击,恶意脚本在用户浏览器中执行。对于iOS应用,当使用WKWebView显示HTML内容(例如新闻流或聊天)时,XSS是相关的。
真实场景:带HTML格式的聊天
\n用户输入:Привет! <script>alert('XSS')</script>。如果您未经处理就在WebView中显示此消息——脚本将执行。
// 危险\nlet html = "<div>\\(message.text)</div>"\nwebView.loadHTMLString(html, baseURL: nil)\n