Swift安全:SQL注入与XSS——如何保护代码

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

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

开始课程

Swift站在前沿:为什么安全不是选项,而是必需

\n

您用Swift编写代码,为性能和代码美观而自豪。但您是否想过,您的应用对攻击有多脆弱?SQL注入和XSS(跨站脚本攻击)不仅仅是教科书上的恐怖故事。它们是真实的威胁,可能让您付出用户数据、声誉和金钱的代价。

\n

在本文中,我们将探讨如何保护Swift应用(无论是iOS客户端还是基于Vapor的服务器端)免受这两种最危险的攻击类型。没有废话——只有实用示例、现成解决方案和真实代码。开始吧!

\n\n

Swift中的SQL注入:黑客如何“欺骗”数据库

\n

想象一下:用户在文本框中输入'; DROP TABLE Users; --。如果您直接将这个字符串拼接到SQL查询中,数据库将执行删除命令。经典案例。

\n

在Swift中,这种漏洞最常见于服务器端框架(Vapor、Kitura)或在使用Core Data和SQLite通过不安全的封装时。

\n\n

危险示例:错误做法

\n
import 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

黄金法则:永远不要将用户数据直接插入查询字符串。使用参数化。

\n
import 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
\n

SQLite.swift库会自动转义特殊字符。对于使用Fluent的Vapor,请使用模型和过滤器:

\n
import 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绑定参数。

\n\n

ORM和Core Data:安全的假象

\n

许多开发者认为Core Data或Fluent会自动防止注入。这是真的——只要您不使用带字符串格式化的NSExpression或raw SQL。但请记住:任何通过字符串插值构建的NSPredicate都存在风险。

\n
// 危险\nlet predicate = NSPredicate(format: "name == %@", userInput) // 安全?\n// 不!如果userInput包含'%',可能通过替换发生注入。\n
\n

始终使用带变量的%@,而不是带键的%K,并且永远不要通过\\()插入字符串。

\n\n

Swift中的XSS攻击:当攻击者注入JavaScript

\n

XSS是一种攻击,恶意脚本在用户浏览器中执行。对于iOS应用,当使用WKWebView显示HTML内容(例如新闻流或聊天)时,XSS是相关的。

\n\n

真实场景:带HTML格式的聊天

\n

用户输入:Привет! <script>alert('XSS')</script>。如果您未经处理就在WebView中显示此消息——脚本将执行。

\n
// 危险\nlet html = "<div>\\(message.text)</div>"\nwebView.loadHTMLString(html, baseURL: nil)\n

博客

书籍推荐