codeigniter 防 sql 注入靠 query builder 和 escape() 等机制,而非数据库配置;ar 自动转义值,但表名、字段名等结构化部分需白名单校验。

CodeIgniter 本身不靠数据库配置项来防止 SQL 注入,$db['default']['hostname']、$db['default']['username'] 这类配置只管连库,跟 SQL 构造完全无关。真正起防护作用的是你写查询时用的那套机制——配置再严,$this->db->query("SELECT * FROM users WHERE id = {$_GET['id']}") 一样被秒。
用 AR(Query Builder)代替 raw query 是最基础防线
AR 内部对传入的值自动调用 escape_str(),数值、字符串、NULL、布尔值都按类型处理,比如:
$this->db->where('status', $input_status)->get('users');
即使 $input_status 是 "1 OR 1=1",最终生成的 WHERE 子句也是 WHERE status = '1 OR 1=1',不会触发逻辑绕过。
- 所有 CRUD 操作优先走
insert()、update()、delete()、get()等方法,别图省事拼 SQL 字符串 -
where()接收数组或键值对时才安全;若写成where("id = '$id'"),就等于放弃 AR 防护,和裸写 query 无异 - 复杂查询必须用原生 SQL 时,所有外部输入必须显式过
$this->db->escape()或$this->db->escape_str()
手动拼接 WHERE 条件时,escape() 和 escape_str() 的区别不能混淆
escape() 会自动加单引号、处理 NULL/bool,适合直接塞进 SQL 字符串;escape_str() 只做转义不加引号,适合拼在已带引号的上下文中。
- 错误示范:
"WHERE name = " . $this->db->escape_str($name)→ 缺少引号,变成WHERE name = admin'--就可能被截断利用 - 正确写法:
"WHERE name = " . $this->db->escape($name)→ 输出WHERE name = 'admin\'--' - 数值型字段别偷懒:虽然
escape(123)返回'123',但数据库通常接受无引号数字;为免意外,建议先is_numeric()校验再拼接
全局 XSS 开关对 SQL 注入无效,别误信“开它就安全”
$config['global_xss_filtering'] = TRUE 只影响 $_GET/$_POST/$_COOKIE 的输出内容过滤(如移除 <script></script>),对数据库查询构造零作用。
- 它不会修改传给
where()或query()的变量值 - 哪怕开了这个,
$this->db->query("DELETE FROM logs WHERE ip = '{$_GET['ip']}'")依然高危 - 真正该做的:所有用户输入在进 SQL 前,要么走 AR,要么过
escape(),要么自己intval()/preg_replace()严格清洗
最易被忽略的一点:AR 的防护只覆盖你明确传进去的值,不覆盖表名、字段名、ORDER BY 子句这类结构化部分。如果业务真需要动态表名(比如分表),$this->db->get($table_name) 中的 $table_name 必须白名单校验,绝不能来自用户输入。











