蓝盟IT小贴士,来喽!
注释掉后面的limit语句,禁用分页条件,并返回所有数据。 攻击者可以通过这个漏洞一次获取所有数据。
动态排序这个功能本来是个好主意,但有注入sql的风险。 幸运的是,这次我们很快发现了问题,及时解决了。 没有任何损失。
但是,几年前在老东家的时候,没那么幸运。
一次sql注入直接中断了我们的支付服务。
1 .恢复事故现场
有一天,运营姐姐跑过来说很多用户付不起钱。 这个支付服务是旧系统,转了三个人。 一直很稳定,没问题。
我什么也没说就开始了定位的问题。 首先查看服务器日志,发现了很多数据库连接过多的异常。 由于支付功能太重要了,当时为了保证支付功能的迅速恢复,首先找了运维重新启动了支付服务的两个节点。
5分钟后暂时恢复正常。
我继续重新安排理由。 根据当时的经验,一般来说数据库连接过多,可能是因为连接被忘记关闭了。 但是,仔细检查代码没有发现问题。 我们使用的数据库连接池会自动回收空闲连接,从而消除了这种可能性。
过了一会儿,另一个节点上发生了数据库连接过多的问题。
但是这个时候,还没找到原因,没办法,只能让运维重启服务,但是这次增大了数据库的最大连接数,默认为100,是我们当时设置的500,后面变成了1000。 (实际上,现在大部分分支机构都将该参数设定为1000 )
也可以检查当前的连接状态以标识有问题的查询语句。 (特别需要说明的是上图是我给的一个例子,在线的真实结果不是这样)。
标识线程标识
用户执行sql的帐户
运行hostSQL的数据库的ip和管脚号
数据库名称
命令执行命令,如Daemon、Query和Sleep。
Time执行sql所需的时间
状态执行状态
信息组织执行信息。 可能包含sql信息。
果然,发现了异常的查询sql,运行了约1个小时,还没有运行完。
dba复制了那个sql,发给了我。 然后kill -9杀死了那个运行非常花时间的sql线程。
之后,数据库连接过多的问题就消失了。
拿到那个sql后仔细分析,发现一个订单查询句被攻击者注入了较长的sql。 一定是高手写的。 根据语法的不同,我没有见过。但毫无疑问,可以确认是注入了人sql。
从那个sql的信息中,我很快找到了相关代码,在查询数据时找到了用于参数的Statment,而不是PrepareStatement的预编译机制。
知道原因后更容易处理,将查询数据的位置改为preparestatement的预编译机制后,问题最终得到了解决。
2 .为什么数据库连接太多?
很多同学看到这里,相信会有sql注入为什么会导致数据库连接过剩的疑问。
攻击者sql注入了这样的参数:-1锁定表文--。
其中; 上一个查询语句先被执行了。
---因为下面的语句将被注释,所以下面只执行锁定的表语句,然后锁定表。
如果在成功从数据库连接池中获取连接后需要对表进行操作,则常规业务请求将尝试获取表锁,但在超时之前无法获取。 请注意,这里占用了大量的数据库连接,可能无法及时返回。
数据库连接池不足,没有空闲连接。
新业务请求无法从数据库连接池获取连接,并报告数据库连接异常。
sql注入引起了数据库连接过多的问题,根本原因是长时间锁定表。
3 .预编译为什么能防止注入sql?
preparestatement预编译机制在执行sql语句之前进行语法分析、编译和优化。 其中,参数的位置是否使用占位符? 代替了
在实际运行时,传递的参数将被视为纯文本,不重新编译,也不被视为sql指令。
5 .特殊场景怎么办?
如果java使用mybatis作为持久框架,而mapper.xml文件使用#直通值,则会使用预编译机制。
6 .表情信息是如何泄漏的?
一些谨慎的同学可能会在上面的锁表的例子中提出攻击者是如何获得表信息的问题。
方法1 :盲猜
是推测攻击者根据常识可能存在的表名。
文/上海蓝盟 IT外包专家