sql注入

来源:互联网 发布:flyme账户登录网络异常 编辑:程序博客网 时间:2024/05/10 02:11

3.编码原则

SQL注射是由于程序中对使用到的SQL没有做到数据和结构分离导致程序的SQL能被恶意用户控制,从而引发的数据库信息泄漏,修改,服务器被入侵等一系列严重后果。

注入攻击的本质,是把用户输入的数据当作代码执行。这里有两个关键条件,

1) 第一个是用户能够控制输入 2) 第二个是原本程序要执行的代码,拼接了用户输入的数据

 

 


4. SQL语法规范

复制代码
1. 少用空值作为查询条件。原因有两个: 1) 空值将不能用上索引,会影响到数据库性能,尽量在缺省值,在插入数据时自动让数据库填上缺省值 2) 容易产生空值永真、从而触发拦截规则例:原语句: select * from employee where flag is null;改进后语句: select * from employee where flag=0(让数据库自动缺省为0)
复制代码

 

复制代码
2. 对数字型的SQL查询采用明确的数字型强制类型转换,原因有2点: 1) 原来的业务逻辑本身就是数字INT型,强制转换后并不影响正常的业务 2) 对数字型的参数进行数字型强制类型转换后,能防止攻击者输入除数字之外的额外的参数进行注入攻击例:原语句:        $id = $_GET['id']; "select * from employee where id=$id";改进后语句:        $id = intval($_GET['id']); "select * from employee where id=$id";
复制代码

 

复制代码
3. 对字符型的SQL查询采用对应编码转义操作,原因有2点: 1) 原来的业务逻辑本身就是纯字符STRING型,转义后不会影响到业务的运行 2) 对字符型的参数进行转义后,能防止攻击者输入单引号、双引号、反斜线等"闭合类字符"进行闭合注入,是一种有效防御注入的方法例:原语句:        $name = $_GET['name']; "select * from employee where name='$name'";改进后语句:        $name = mysql_real_escape_string($_GET['id']); "select * from employee where name=$name";Ps: 1. 使用转义函数的时候一定要注意当前脚本语言的编码格式和数据库的编码格式是否一致,例如PHP和Mysql的编码同时为GBK、或同时为UTF8时,转义函数才能有效地对注入攻击进行防御,否则存在被绕过的可能 2. 在连接数据库的时候,需要执行以下语句,进行编码统一: //例如你的数据库采用的是GBK的编码,则你的连接代码应该写成类似如下的格式 $mysqli = new mysqli("localhost", "root", "111", "test", 3306);$mysqli->set_charset('gbk'); //例如你的数据库采用的是UTF8的编码,则你的连接代码应该写成类似如下的格式 $mysqli = new mysqli("localhost", "root", "111", "test", 3306);$mysqli->set_charset('utf8');
复制代码

 

4. 避免在SQL中出现永真永真条件常常被黑客用来进行注入探测,黑客可以利用永真条件的执行情况来判断当前WEB应用是否存在被注入的可能性

 

复制代码
5. 在SQL中强烈推荐使用参数化查询对程序中使用到的SQL语句,使用变量绑定的方式进行数据和结构的分离是一种很好的防御SQL注入的方法  问题代码示例: <?php    $id=$_GET['id'];    $conn = mysql_connect("localhost","root","") or die ("wrong!");    $sel=mysql_select_db("mydb",$conn);    $sql="select * from user where id = ".id    $que=mysql_query($sql,$conn); ?> 修复范例: <?php    $id=$_GET['id'];    $conn = mysql_connect("localhost","root","") or die ("wrong!");    $sel=mysql_select_db("mydb",$conn);    $sql="select * from user where id = :id" $stmt = $conn->prepare($sql);     $stmt->execute(array(':id'=>$id)); ?>
复制代码

 

 

 


5. 案例、场景

复制代码
1. 不允许访问系统表合理的SQL语句 1) select * from information_schema.COLUMNS;这条语句druid认为是合法的,因为这条语句没有注入点的存在,SQL语句本身的唯一目的就是查询系统表,说明用户在进行正常的业务操作不合理的SQL语句 1) SELECT idFROM adminWHERE id = 1 AND 5 = 6 UNIONSELECT concat(0x5E252421, COUNT(8), 0x2A5B7D2F)FROM (SELECT `column_name`, `data_type`, `character_set_name`    FROM `information_schema`.`COLUMNS`    WHERE TABLE_NAME = 0x73696E6765725F616C62756D AND TABLE_SCHEMA = 0x796971696C61695F757466 ) t这条语句druid认为是非法的注入攻击,因为SQL在子句(可能是注入点的地方)采取了union拼接,进行了连接系统表的查询的操作
复制代码

 

复制代码
2. 不允许访问系统变量合理的SQL语句 1) select @@basedir;这条语句druid不做拦截,因为这里没有注入点的存在,也就不可能是黑客的注入攻击,应该归类于业务的正常需要不合理的SQL语句 2) SELECT * FROM cnp_news where id='23' and len(@@version)>0 and '1'='1' 这条语句druid会做拦截,攻击者在子句中利用逻辑表达式进行非法的探测注入 
复制代码

 

复制代码
3. 不允许访问系统函数合理的SQL语句 1) select load_file('\\etc\\passwd');druid不会拦截这条语句,还是同样的道理,SQL注入的关键在于注入点,这条语句没有注入点的存在,所以只能是用户正常的业务需求不合理的SQL语句 1) select * from admin where id =(SELECT 1 FROM (SELECT SLEEP(0))A);   druid会智能地检测出这个敏感函数出现在"where子句节点"中,而"where子句节点"经常被黑客用来当作一个SQL注入点,故druid拦截之
复制代码

 

复制代码
4. 禁止永真条件合理的SQL语句 1) 正常的业务语句SELECT F1, F2 FROM ADMIN WHERE 1 = 1;        -- 允许SELECT F1, F2 FROM ADMIN WHERE 0 = 0;        -- 允许SELECT F1, F2 FROM ADMIN WHERE 1 != 0;        -- 允许SELECT F1, F2 FROM ADMIN WHERE 1 != 2;        -- 允许不合理的SQL语句 1) 有攻击性的SQL语句 select * from admin where id =-1 OR 17-7=10;             -- 拦截 select * from admin where id =-1 and 1=2 -- 拦截 select * from admin where id =-1 and 2>1 -- 拦截 select * from admin where id =-1 and 'a'!='b' -- 拦截 select * from admin where id =-1 and char(32)>char(31)        -- 拦截 select * from admin where id =-1 and '1' like '1' -- 拦截 select * from admin where id =-1 and 17-1=10 -- 拦截 select * from admin where id =-1 and NOT (1 != 2 AND 2 != 2)    --拦截 select * from admin where id =-1 and id like '%%' -- 拦截 select * from admin where id =-1 and length('abcde') >= 5 -- 拦截
复制代码

 

 

 


6. 技术FAQ

对任何防御系统来说,在有效拦截和误拦截之前的分界线总是一个不断优化的过程。因此,可能会出现一些本身正常的业务SQL语句,由于触发了我们的拦截规则从而导致被误拦截,以下列出一些可能会被拦截的SQL语句样例:

复制代码
1. 0x1 1) SQL语句SELECT COUNT( * ) FROM (SELECT header.id, header.tenant_id, header.create_date header_create_date, header.modify_date header_modify_date, header.supplier_id, header_detail.amount header_amount, header_detail.sku_id header_sku_idFROM purchase_order_header headerINNER JOIN purchase_order_detail header_detail ON ( header.id = header_detail.pid ) WHERE approve =1 )headerLEFT JOIN (SELECT arrive.id arrive_id, arrive.create_date arrive_create_date, arrive.modify_date arrive_modify_date, arrive_detail.qty arrive_qty, arrive_detail.sku_id arrive_sku_id, arrive.pid arrive_pidFROM purchase_arrive_order_header arriveINNER JOIN purchase_arrive_order_detail arrive_detail ON ( arrive.id = arrive_detail.pid ) WHERE approve =1 )arrive ON (header.id = arrive_pidAND header_sku_id = arrive_sku_id)LEFT JOIN (SELECT return_detail.amount return_amount, return_detail.qty return_qty, return_header.id return_id, return_header.tenant_id return_tenant_id, return_detail.sku_id return_sku_id, return_header.supplier_id return_supplier_id, return_header.create_date return_create_date, return_header.modify_date return_modify_dateFROM purchase_return_order_header return_headerINNER JOIN purchase_return_order_detail return_detail ON ( return_header.id = return_detail.pid ) WHERE approve =1 )return_header ON (tenant_id = return_tenant_idAND supplier_id = return_supplier_idAND return_sku_id = header_sku_id)WHERE 1 =1 OR header_modify_date >= '2014-03-13 07:53:30' OR arrive_create_date >= '2014-03-13 07:53:30' OR return_create_date >= '2014-03-13 07:53:30' OR header_modify_date < '2014-03-13 08:04:00' OR arrive_modify_date < '2014-03-13 08:04:00' OR return_modify_date < '2014-03-13 08:04:00' 2) 拦截原因WHERE 1=1的永真违反了规则 select alway true condition not allow
复制代码

 

复制代码
2. 0x2 1) SQL语句SELECT id, name, IFNULL( parentId, 0 ) parentId, isParentFROM goods_categoryWHERE companyId =17 UNION ALL SELECT 0 , '所有分类', NULL , NULL FROM dual 2) 拦截原因UNION ALL SELECT 0 , '所有分类', NULL , NULL FROM dual这句话违反了子查询注入规则UNION ALL query not contains 'from clause'
复制代码

 

复制代码
3. 0x3:   DELETE FROM tds_permission; INSERT INTO tds_permission( id, name, memo, permission_key ) VALUES ( 1, '首页', NULL , NULL ) , ( 2, '店铺诊断', NULL , NULL ) , ( 3, '店铺监控', NULL , NULL ) , ( 4, '订单中心', NULL , NULL ) , ( 5, '营销活动', NULL , NULL ) , ( 6, '促销管理', NULL , NULL ) , ( 7, '客户管理', NULL , NULL ) , ( 8, '系统管理', NULL , NULL ) ; DELETE FROM tb_role; INSERT INTO tb_role( id, name, memo ) VALUES ( 100000, '管理员', NULL ) , ( 100001, '普通用户', NULL ); -- 角色_权限.普通用户比管理员少一个"系统管理"权限DELETE FROM tb_role_permission; INSERT INTO tb_role_permission( role_id, permission_id ) VALUES ( 100000, 1 ) , ( 100000, 2 ) , ( 100000, 3 ) , ( 100000, 4 ) , ( 100000, 5 ) , ( 100000, 6 ) , ( 100000, 7 ) , ( 100000, 8 ) , ( 100001, 1 ) , ( 100001, 2 ) , ( 100001, 3 ) , ( 100001, 4 ) , ( 100001, 5 ) , ( 100001, 6 ) , ( 100001, 7 ) ; 2) 拦截原因 2.1) -- 角色_权限.普通用户比管理员少一个"系统管理"权限: SQL语句中出现注释 2.2) 一次SQL请求中包含了多条SQL语句,即堆叠查询,这是黑客常用的攻击方式
0 0
原创粉丝点击