一次sql注入引发的多个mysql进程锁住的问题(针对myisam)

以前碰到过一个sql注入式攻击引发大量mysql进程被锁住的例子,现在分享给大家。当时数据表用的是myisam存储引擎。

 

基本知识点:

InnoDB存储引擎既支持行级锁(row-level locking),也支持表级锁,而MyISAM支持的是表级锁。

 

MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作;MyISAM表的读操作与写操作之间,以及写操作之间是串行的

 

模拟示例:

create table myisam_test(id int primary key not null auto_increment,

v1 varchar(64),

v2 varchar(64)) engine=myisam;

 

insert into myisam_test(v1,v2) values('a','b');

多次执行 insert into myisam_test(v1,v2) select concat(v1,'a'),concat(v2,'b') from myisam_test;

 

 

接下来大boss上场了,就是那段被注入的sql

 

select * from myisam_test  where (id=1000) xor(if(453=453,sleep(5),0)) limit 1;

 

由于程序没有过滤非法参数值(xor(if(453=453,sleep(5),0))),sql一直在执行中,但是读操作不会阻塞其他用户对同一个表的读请求因此执行另一条select后会立刻返回执行结果:

 

一次sql注入引发的多个mysql进程锁住的问题(针对myisam)

 

但是假如我们在此时执行写操作呢?见下图:

 

一次sql注入引发的多个mysql进程锁住的问题(针对myisam)

  


一次sql注入引发的多个mysql进程锁住的问题(针对myisam)
 

读操作会阻塞对同一表的写请求,而写操作会阻塞其他用户对同一表的读和写操作,因此在这里后续的updateselect语句都因为id=8的那个process而一直处于等待状态,无法返回结果。

 

我们kill掉那条被注入的sql执行进程,锁立刻释放,后续的sql立刻返回结果。

 一次sql注入引发的多个mysql进程锁住的问题(针对myisam)

Sql注入式攻击再配合myisam的特性,导致大量进程处于等待状态,因此我们编程时基本的安全意识还是要有的,如净化用户输入,如使用如下参数化查询而不是将参数拼接到sql语句中:

PreparedStatement prep = conn.prepareStatement("SELECT * FROM  myisam_test WHERE v1=? AND v2=?");

prep.setString(1, value1);

prep.setString(2, value2);

prep.executeQuery();