一、输入验证
1.1 sql注入
SQL Injection
Abstract
通过不可信来源的输入构建动态 SQL 指令,攻击者就能够修改指令的含义或者执行任意 SQL 命令。
Explanation
SQL injection 错误在以下情况下发生:
1. 数据从一个不可信赖的数据源进入程序。
2. 数据用于动态地构造一个 SQL 查询。
例 1:以下代码动态地构造并执行了一个 SQL 查询,该查询可以搜索与指定名称相匹配的项。该查询仅会显
示条目所有者与被授予权限的当前用户一致的条目。
- ...String userName = ctx.getAuthenticatedUserName();String itemName = request.getParameter("itemName");String query = "SELECT * FROM items WHERE owner = '"+ userName + "' AND itemname = '"+ itemName + "'";ResultSet rs = stmt.execute(query);...
这一代码所执行的查询遵循如下方式:
- SELECT * FROM itemsWHERE owner =AND itemname = ;
但是,由于这个查询是动态构造的,由一个不变的基查询字符串和一个用户输入字符串连接而成,因此只有在 itemName 不包含单引号字符时,才会正确执行这一查询。如果一个用户名为 wiley 的攻击者为itemName 输入字符串“name’ OR ‘a’='a”,那么查询就会变成:
- SELECT * FROM itemsWHERE owner = 'wiley'AND itemname = 'name' OR 'a'='a';
附加条件 OR ‘a’='a’ 会使 where 从句永远评估为 true,因此该查询在逻辑上将等同于一个更为简化的查询:
- SELECT * FROM items;
这种查询的简化会使攻击者绕过查询只返回经过验证的用户所拥有的条目的要求;而现在的查询则会直接返回所有储存在 items 表中的条目,不论它们的所有者是谁。
例 2:这个例子指出了将不同的恶意数值传递给在例 1 中构造和执行的查询时所带来的各种影响。如果一个用户名为 wiley 在 itemName 中输入字符串“name’; DELETE FROM items; –”,则该查询将会变为以下两个:
- SELECT * FROM items WHERE owner = 'wiley'AND itemname = 'name';DELETE FROM items;--'
众多数据库服务器,其中包括 Microsoft(R) SQL Server 2000,都可以一次性执行多条用分号分隔的 SQL 指令。对于那些不允许运行用分号分隔的批量指令的数据库服务器,比如 Oracle 和其他数据库服务器,攻击者输入的这个字符串只会导致错误;但是在那些支持这种操作的数据库服务器上,攻击者可能会通过执行多条指令而在数据库上执行任意命令。注意成对的连字符 (–);这在大多数数据库服务器上都表示下面的语句将作为注释使用,而不能加以执行 [4]。在这种情况下,注释字符的作用就是删除修改的查询指令中遗留的最后一个单引号。而在那些不允许这样加注注释的数据库中,通常攻击者可以如例 1 那样来攻击。如果攻击者输入字符串“name’); DELETE
FROM items; SELECT * FROM items WHERE ‘a’='a”就会创建如下三个有效指令:
- SELECT * FROM items WHERE owner = 'wiley' AND itemname = 'name';DELETE FROM items;SELECT * FROM items WHERE 'a'='a';
有些人认为在移动世界中,典型的 Web 应用程序漏洞(如 SQL injection)是无意义的 – 为什么用户要攻击自己?但是,谨记移动平台的本质是从各种来源下载并在相同设备上运行的应用程序。恶意软件在银行应用程序附近运行的可能性很高,它们会强制扩展移动应用程序的攻击面(包括跨进程通信)。
示例 3:以下代码对示例 1 进行调整,使其适用于 Android 平台。
- ...PasswordAuthentication pa = authenticator.getPasswordAuthentication();String userName = pa.getUserName();String itemName = this.getIntent().getExtras().getString("itemName");String query = "SELECT * FROM items WHERE owner = '"+ userName + "' AND itemname = '"+ itemName + "'";SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE,null);Cursor c = db.rawQuery(query, null);
避免 SQL