这几天有套应用发生了匪夷所思的现象,数据库信息频繁被篡改,一开始我们怀疑可能是应用被攻击了,但依然没有可靠的证据,接连几天找不到原因,今天下午应用人员告诉我说很多用户都登陆不了系统了,数据库是不是出问题了,下面是今天的分析过程。
数据库信息
数据库负载为 2 左右,对于 8 核的机器来说还不算高,IO,CPU使用率在合理范围之内。
主机层面查看当前会话
1 2 3 4 5 6 7 8 9 10 11 12 13 14
|
[postgres@db](mailto:postgres@db)> ps -ef | grep UPDATE postgres 393 3708 0 Nov12 ? 00:01:24 postgres: mpc_db_account mpc_db_account 192.168.104.50(38165) UPDATE waiting postgres 403 3708 0 Nov12 ? 00:01:23 postgres: mpc_db_account mpc_db_account 192.168.104.50(38172) UPDATE waiting postgres 465 3708 0 Nov12 ? 00:01:24 postgres: mpc_db_account mpc_db_account 192.168.104.50(45733) UPDATE waiting postgres 478 3708 0 Nov12 ? 00:01:30 postgres: mpc_db_account mpc_db_account 192.168.104.50(45740) UPDATE waiting postgres 516 3708 0 Nov12 ? 00:01:29 postgres: mpc_db_account mpc_db_account 192.168.104.50(45747) UPDATE waiting postgres 8114 3708 0 15:06 ? 00:00:00 postgres: mpc_db_account mpc_db_account xxx.xxx.xxx.xx(40477) UPDATE waiting postgres 8236 3708 0 15:08 ? 00:00:00 postgres: mpc_db_account mpc_db_account xxx.xxx.xxx.xx(51622) UPDATE waiting postgres 8781 8319 0 15:19 pts/0 00:00:00 grep UPDATE postgres 15199 3708 0 Nov13 ? 00:00:46 postgres: mpc_db_account mpc_db_account xxx.xxx.xxx.xx(50177) UPDATE waiting postgres 15207 3708 0 Nov13 ? 00:05:28 postgres: mpc_db_account mpc_db_account xxx.xxx.xxx.xx(50184) UPDATE postgres 15215 3708 0 Nov13 ? 00:00:59 postgres: mpc_db_account mpc_db_account xxx.xxx.xxx.xx(50190) UPDATE waiting postgres 15223 3708 0 Nov13 ? 00:00:48 postgres: mpc_db_account mpc_db_account xxx.xxx.xxx.xx(50197) UPDATE waiting postgres 23476 3708 0 Nov12 ? 00:01:13 postgres: mpc_db_account mpc_db_account xxx.xxx.xxx.xx(43681) UPDATE waiting
|
备注:这里发现有十几个 update 会话处于等待状态,只有会话 15207 在执行,猜想可能是这个会话有问题。
查看 15207 会话详细信息
1 2 3 4 5 6 7 8 9
|
postgres=# select datname,current_query,query_start,client_a from pg_stat_activity where current_query !='<IDLE>' and procpid=15207; datname |current_query | query_start | client_addr | client_port ----------------+------------------------------------------------------------------------------------------------------------------- mpc_db_account | update tmp_table set column1 = '[?au]..v..<<kool-boy>>...', sex = 1, birthday = '1994-11-24', mobile = '', province = '', city = '', signature = 'sunlei '--', head_icon = 30, country_code = 286 where user_id = 139957561 | 2011-11-14 14:51:07.147826+08 | xxx.xxx.xxx.xx | 50184 (1 row)
|
备注:根据执行时间( query_start )来看,这个会话跑了有 30 分钟左右了还没跑完,这个 update 语句是带where 条件的,应该只更新一条记录,为什么执行了这么久还没跑完呢?觉得非常奇怪, 接下来想进一步分析,但业务因为部分用户登陆不了系统,项目经理建议先重启业务,回头再查原因。
出现转机
业务重启后,应用恢复正常,接着开发人员在测试环境上进行了测试,幸运的是他们带来了意外的发现,他们发现在修改字段值时,加上单引号,再加上注释符 – 后,表上所有的记录都被更新了,正如上面的 signature 字段值全被更新成 sunlei 了,后来了解了下情况,目前业务上基本上没有对客户端用户输入的信息做处理,没对特殊字符做转义。接下来详细测试下。
模拟测试
创建测试表并插入数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
skytf=> create table test_66 (id integer, name varchar(32)); CREATE TABLE skytf=> insert into test_66 select generate_series(1,10),'a'; INSERT 0 10
skytf=> select * from test_66; id | name ----+------ 1 | a 2 | a 3 | a 4 | a 5 | a 6 | a 7 | a 8 | a 9 | a 10 | a (10 rows)
|
更新数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
skytf=> update test_66 set name='aaa '--' where id=1; UPDATE 10
skytf=> select * from test_66; id | name ----+------ 1 | aaa 2 | aaa 3 | aaa 4 | aaa 5 | aaa 6 | aaa 7 | aaa 8 | aaa 9 | aaa 10 | aaa (10 rows)
|
备注:虽然带有 where 条件的更新,却全表更新了表数据,原因是注释符 “–” 后面的语句被注释掉了,如果此时程序发送分号,那么语句被执行,全表数据被更新。
测试结论
上面证实了本文的问题属于软件问题,没对对客户端输入的文字进行合法性检查,也没有对特殊字符进行转义处理,同时这也给 SQL 注入带来了很大的隐患。
对特殊字符进行转义处理
举例如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
|
skytf=> update test_66 set name=E'bbb'bbb' where id=1; UPDATE 1
skytf=> select * from test_66; id | name ----+--------- 2 | aaa 3 | aaa 4 | aaa 5 | aaa 6 | aaa 7 | aaa 8 | aaa 9 | aaa 10 | aaa 1 | bbb'bbb (10 rows)
skytf=> update test_66 set name=E'bbb'--' where id=2; UPDATE 1
skytf=> select * from test_66; id | name ----+--------- 3 | aaa 4 | aaa 5 | aaa 6 | aaa 7 | aaa 8 | aaa 9 | aaa 10 | aaa 1 | bbb'bbb 2 | bbb'-- (10 rows)
|
解决方法
为了减少此类情况和 SQL 注入的情况,建议程序里对客户端输入的文字进行合法性检查,对特殊字符进行转义处理;同时也要增加应用程序的安全性,例如权限, 不使用动态SQL,以及密码需加密等。
参考文档
原创文章,作者:506227337,如若转载,请注明出处:https://blog.ytso.com/237808.html