SQL注入竟然把我们的系统搞挂了sql预编译代码schema

select*fromuserorderbyid;select1--limit1,20

--会把后面的limit语句注释掉,导致分页条件失效,返回了所有数据。攻击者可以通过这个漏洞一次性获取所有数据。

动态排序这个功能原本的想法是好的,但是却有sql注入的风险。值得庆幸的是,这次我们及时发现了问题,并且及时解决了,没有造成什么损失。

但是,几年前在老东家的时候,就没那么幸运了。

一次sql注入直接把我们支付服务搞挂了。

还原事故现场

有一天运营小姐姐跑过来跟我说,有很多用户支付不了。这个支付服务是一个老系统,转手了3个人了,一直很稳定没有出过啥问题。

我二话不说开始定位问题了,先看服务器日志,发现了很多报数据库连接过多的异常。因为支付功能太重要了,当时为了保证支付功能快速恢复,先找运维把支付服务2个节点重启了。

5分钟后暂时恢复了正常。

我再继续定位原因,据我当时的经验判断一般出现数据库连接过多,可能是因为连接忘了关闭导致。但是仔细排查代码没有发现问题,我们当时用的数据库连接池,它会自动回收空闲连接的,排除了这种可能。

过了会儿,又有一个节点出现了数据库连接过多的问题。

但此时,还没查到原因,逼于无奈,只能让运维再重启服务,不过这次把数据库最大连接数调大了,默认是100,我们当时设置的500,后面调成了1000。(其实现在大部分公司会将这个参数设置成1000)

使用命令:

setGLOBALmax_connections=500;

能及时生效,不需要重启mysql服务。

使用showprocesslist;命令查看当前线程执行情况:

还可以查看当前的连接状态帮助识别出有问题的查询语句。(需要特别说明的是上图只是我给的一个例子,线上真实的结果不是这样的)

果然,发现了一条不寻常的查询sql,执行了差不多1个小时还没有执行完。

dba把那条sql复制出来,发给我了。然后kill-9杀掉了那条执行耗时非常长的sql线程。

后面,数据库连接过多的问题就没再出现了。

我拿到那条sql仔细分析了一下,发现一条订单查询语句被攻击者注入了很长的一段sql,肯定是高手写的,有些语法我都没见过。

但可以确认无误,被人sql注入了。

知道原因就好处理了,将查询数据的地方改成preparestatement预编译机制后问题得以最终解决。

为什么会导致数据库连接过多?

我相信很多同学看到这里,都会有一个疑问:sql注入为何会导致数据库连接过多?

我下面用一张图,给大家解释一下:

预编译为什么能防sql注入?

preparestatement预编译机制会在sql语句执行前,对其进行语法分析、编译和优化,其中参数位置使用占位符?代替了。

当真正运行时,传过来的参数会被看作是一个纯文本,不会重新编译,不会被当做sql指令。

这样,即使入参传入sql注入指令如:

select*fromuserorderby'id;select1--'limit1,20

这样就不会出现sql注入问题了。

预编译就一定安全?

不知道你在查询数据时有没有用过like语句,比如:查询名字中带有“苏”字的用户,就可能会用类似这样的语句查询:

select*fromuserwherenamelike'%苏%';

正常情况下是没有问题的。

但有些场景下要求传入的条件是必填的,比如:name是必填的,如果注入了:%,最后执行的sql会变成这样的:

select*fromuserwherenamelike'%%%';

这种情况预编译机制是正常通过的,但sql的执行结果不会返回包含%的用户,而是返回了所有用户。

name字段必填变得没啥用了,攻击者同样可以获取用户表所有数据。

为什么会出现这个问题呢?

%在mysql中是关键字,如果使用like'%%%',该like条件会失效。

如何解决呢?

需要对%进行转义:/%。

转义后的sql变成:

select*fromuserwherenamelike'%/%%';

只会返回包含%的用户。

有些特殊的场景怎么办?

在java中如果使用mybatis作为持久化框架,在mapper.xml文件中,如果入参使用#传值,会使用预编译机制。

一般我们是这样用的:

select*fromusername=#{name}

绝大多数情况下,鼓励大家使用#这种方式传参,更安全,效率更高。

但是有时有些特殊情况,比如:

orderby${sortString}

sortString字段的内容是一个方法中动态计算出来的,这种情况是没法用#,代替$的,这样程序会报错。

使用$的情况就有sql注入的风险。

那么这种情况该怎办呢?

表信息是如何泄露的?

有些细心的同学,可能会提出一个问题:在上面锁表的例子中,攻击者是如何拿到表信息的?

方法1:盲猜

就是攻击者根据常识猜测可能存在的表名称。

假设我们有这样的查询条件:

select*fromt_orderwhereid=${id};

传入参数:-1;select*fromuser

最终执行sql变成:

select*fromt_orderwhereid=-1;select*fromuser;

如果该sql有数据返回,说明user表存在,被猜中了。

建议表名不要起得过于简单,可以带上适当的前缀,比如:t_user。这样可以增加盲猜的难度。

方法2:通过系统表

其实mysql有些系统表,可以查到我们自定义的数据库和表的信息。

假设我们还是以这条sql为例:

selectcode,namefromt_orderwhereid=${id};

第一步,获取数据库和账号名。

传参为:-1unionselectdatabase(),user()#

第二步,获取表名。

传参改成:-1unionselecttable_name,table_schemafrominformation_schema.tableswheretable_schema='sue'#最终执行sql变成:

建议在生成环境程序访问的数据库账号,要跟管理员账号分开,一定要控制权限,不能访问系统表。

sql注入到底有哪些危害?

7.1核心数据泄露

大部分攻击者的目的是为了赚钱,说白了就是获取到有价值的信息拿出去卖钱,比如:用户账号、密码、手机号、身份证信息、银行卡号、地址等敏感信息。

他们可以注入类似这样的语句:

-1;select*fromuser;--

就能轻松把用户表中所有信息都获取到。

所以,建议大家对这些敏感信息加密存储,可以使用AES对称加密。

7.2删库跑路

也不乏有些攻击者不按常理出牌,sql注入后直接把系统的表或者数据库都删了。

-1;deletefromuser;--

以上语句会删掉user表中所有数据。

-1;dropdatabasetest;--

以上语句会把整个test数据库所有内容都删掉。

正常情况下,我们需要控制线上账号的权限,只允许DML(datamanipulationlanguage)数据操纵语言语句,包括:select、update、insert、delete等。

不允许DDL(datadefinitionlanguage)数据库定义语言语句,包含:create、alter、drop等。

也不允许DCL(DataControlLanguage)数据库控制语言语句,包含:grant,deny,revoke等。

DDL和DCL语句只有dba的管理员账号才能操作。

顺便提一句:如果被删表或删库了,其实还有补救措施,就是从备份文件中恢复,可能只会丢失少量实时的数据,所以一定有备份机制。

7.3把系统搞挂

有些攻击者甚至可以直接把我们的服务搞挂了,在老东家的时候就是这种情况。

-1;锁表语句;--

从上面三个方面,能看出sql注入问题的危害真的挺大的,我们一定要避免该类问题的发生,不要存着侥幸的心理。如果遇到一些不按常理出票的攻击者,一旦被攻击了,你可能会损失惨重。

如何防止sql注入?

8.1使用预编译机制

尽量用预编译机制,少用字符串拼接的方式传参,它是sql注入问题的根源。

8.2要对特殊字符转义

有些特殊字符,比如:%作为like语句中的参数时,要对其进行转义处理。

8.3要捕获异常

需要对所有的异常情况进行捕获,切记接口直接返回异常信息,因为有些异常信息中包含了sql信息,包括:库名,表名,字段名等。攻击者拿着这些信息,就能通过sql注入随心所欲的攻击你的数据库了。目前比较主流的做法是,有个专门的网关服务,它统一暴露对外接口。用户请求接口时先经过它,再由它将请求转发给业务服务。这样做的好处是:能统一封装返回数据的返回体,并且如果出现异常,能返回统一的异常信息,隐藏敏感信息。此外还能做限流和权限控制。

8.4使用代码检测工具

使用sqlMap等代码检测工具,它能检测sql注入漏洞。

8.5要有监控

需要对数据库sql的执行情况进行监控,有异常情况,及时邮件或短信提醒。

8.6数据库账号需控制权限

8.7代码review

建立代码review机制,能找出部分隐藏的问题,提升代码质量。

8.8使用其他手段处理

对于不能使用预编译传参时,要么开启druid的filter防火墙,要么自己写代码逻辑过滤掉所有可能的注入关键字。

THE END
1.SQL注入漏洞批量检查工具SQLMC(SQL注入大规模检查器)是一款用于扫描域中是否存在SQL注入漏洞的工具。它会抓取给定的URL直至指定深度,检查每个链接是否存在SQL注入漏洞,并报告其发现的结果。 工具特征 扫描域名中是否存在SQL注入漏洞爬取给定的URL直到指定深度检查每个链接的所有GET参数是否存在SQL注入漏洞报告漏洞以及服务器信息和深度 http://www.360doc.com/content/24/1218/19/77981587_1142310547.shtml
2.SQL注入MicrosoftLearn威胁和漏洞缓解(数据库引擎) 使用英语阅读 保存 添加到集合 添加到计划 通过 Facebookx.com 共享LinkedIn电子邮件 打印 项目 2012/04/01 本文内容 验证所有输入 在代码中检查 SQL 注入 请参阅 SQL 注入是一种攻击方式,在这种攻击方式中,恶意代码被插入到字符串中,然后将该字符串传递到 SQL Server 的实例以进行https://msdn.microsoft.com/zh-cn/library/ms161953.aspx
3.判断注入点的方法5.观察HTTP头信息:HTTP头信息中可能包含参数信息,可以通过修改参数来检测是否存在注入漏洞。 以上是几种常用的判断注入点的方法,通过综合运用可以更加快速准确地找到注入点,提高攻击的成功率。同时,为了避免注入攻击,我们也需要在系统开发时加强防御措施,规范输入参数,使用参数化查询等方式防止注入攻击的发生。?https://wenku.baidu.com/view/4180dd2f28160b4e767f5acfa1c7aa00b42a9d13.html
4.检测SQL注入的方法有哪些问答检测SQL 注入的方法主要包括以下几种: 输入验证:对用户提供的数据进行验证,确保其符合预期的格式和类型。例如,只允许数字输入到需要数字的字段中,或者使用正则表达式来匹配合法的输入模式。 参数化查询:使用参数化查询可以将用户提供的数据与 SQL 语句的结构分开,从而防止攻击者通过注入恶意代码来改变 SQL 语句的结构。https://www.yisu.com/ask/99066343.html
5.SQL注入检测工具及方法,黑客零基础入门SQL注入检测是通过各种手段来识别和验证应用程序是否容易受到SQL注入攻击的方法。 SQL注入原理 SQL注入(SQL Injection)是一种利用应用程序对用户输入的不当处理而导致的安全漏洞。攻击者通过在输入中注入恶意的SQL代码,成功执行数据库查询,甚至执行未经授权的数据库操作。SQL注入的原理可以通过以下几个步骤来理解: https://blog.csdn.net/kailiaq_1/article/details/135066418
6.检查sql注入工具类javasql注入检测爆数据库 爆表 爆字段 爆数据 提示 以下均使用如下靶场: SQL手工注入漏洞测试(Sql Server数据库) 判断注入点 与mysql注入一致 ?id=2 and 1=2 1. 判断数据库类型 and exists (select * from sysobjects)--返回正常为mssql and exists (select count(*) from sysobjects)--有时上面那个语句不行就试试这个https://blog.51cto.com/u_16213580/8711201
7.防范注入式攻击11篇(全文)1. SQL注入攻击检测方法。 SQL注入攻击检测分为入侵前的检测和入侵后的检测, 入侵前检测可以手工测试也可以通过软件检测, 入侵后检测主要是针对日志的检测。 (1) 数据库检查。使用HDSI、NBSI和Domain等SQL注入攻击软件工具进行SQL注入攻击后, 都会在数据库中生成一些临时表。通过查看数据库中最近新建表的结构和内容,https://www.99xueshu.com/w/ikeyeyy47maw.html
8.SQL注入的检测方式有几种?常用方法介绍!常用方法介绍! SQL注入攻击是黑客对数据库进行攻击的常用手段之一,范围广、实现容易、破坏性大,能够对Web应用造成一定的数据泄露,那么你知道如何检查网站是否存在SQL注入漏洞吗?请看下文: SQL注入的检测方式有几种? SQL注入的检测方式目前主要分为两大类:动态检测和静态检测,以下是详细的内容介绍:https://blog.itpub.net/69952527/viewspace-2839345/
9.SQLMAP注入检查方法11种常见SQLMAP使用方法详解工具使用一共有11种常见SQLmap使用方法: 一、SQLMAP用于Access数据库注入 (1) 猜解是否能注入 win: python sqlmap.py -u "http://www.xxx.com/en/CompHonorBig.asp?id=7" Linux : .lmap.py -u "http://www.xxx.com/en/CompHonorBig.asp?id=7" https://www.jb51.net/hack/631963.html
10.初学者必备的Web渗透资料详解SQL注入:通过在Web表单中输入恶意SQL语句,攻击者可以绕过身份验证和访问控制,从而读取或修改数据库中的数据。 跨站脚本攻击(XSS):攻击者通过向Web页面插入恶意脚本,当其他用户访问这些页面时,脚本会在用户浏览器中执行,从而窃取用户信息或控制用户浏览器。 跨站请求伪造(CSRF):攻击者利用用户的身份验证信息,伪造请求,使https://www.imooc.com/article/358369
11.SQL注入攻击检测的方法以及装置与流程1.本技术涉及web安全领域,更具体地,涉及一种结构化查询语句sql注入攻击检测的方法、装置以及计算设备。 背景技术: 2.结构化查询语言(structured query language,sql)注入攻击是黑客对数据库进行攻击的常用手段之一。sql注入漏洞可能会影响使用sql数据库的任何网站或web应用程序。犯罪分子可能会利用它来未经授权访问用户的https://www.xjishu.com/zhuanli/55/202010651207.html
12.网站常见漏洞检测方法(6)严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。 (7)避免网站显示SQL错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。 (8)在网站发布之前建议使用一些专业的SQL注入检测工具进行检测,及时修补这些SQL注入漏洞。https://wxzx.gsupl.edu.cn/info/1204/1420.htm
13.渗透测试之sql注入总之一句话:注入产生的原因是接受相关参数未经处理直接带入数据库查询操作。 注入前的准备及注入漏洞检测: 1、显示友好HTTP错误信息(现在浏览器不用管) 2、手工检测SQL注入点 最常用的SQL注入点判断方法,是在网站中寻找如下形式的网页链接。 http://www.***.com/***.asp?id=xx (ASP注入)(其他语言等https://www.jianshu.com/p/9fd42647bf22
14.基于机器学习的电网虚假数据注入攻击检测方法研究虚假数据注入攻击(FDIAs)作为一种新型电力系统网络攻击,可以成功绕过不良数据检测机制,使电力量测数据发生偏移,在极其隐蔽的条件下误导控制中心操作,严重威胁电力系统稳定运行。传统的检测方法难以检测这种攻击,为保证智能电网的运行安全,本文通过分析虚假数据注入攻击机理,利用机器学习在处理二分类问题上的优势,以监督学习https://cdmd.cnki.com.cn/Article/CDMD-10188-1019121108.htm
15.sql注入如何挖掘(一)1、使用请求头提交数据,比如检测HTTP中的源地址、主机IP等。 是否回显 显注 1、前端页面可以回显用户信息,比如 联合注入、报错注入。 盲注 1、前端页面不能回显用户信息,比如 布尔盲注、时间盲注。 危害 1、数据库信息泄露。 2、网页篡改:登陆后台后发布恶意内容。 3、网站挂马 : 当拿到webshell时或者获取到服务https://xz.aliyun.com/t/12149
16.快速学习利用sqlmap扫描检测sql注入漏洞,挖掘及攻击测试-- 快速学习利用sqlmap扫描检测sql注入漏洞,挖掘及攻击测试 【官网】:https://sqlmap.org/ 应用场景 sqlmap是一个开源的渗透测试工具,可以用来进行自动化数据库指纹识别,数据库枚举,数据提取,访问目标文件系统,并在获取完全的操作权限执行任意命令。目前支持数据库有mysql、oracle、access、postagesql、sql server、sqlitehttps://config.net.cn/producttest/3f96a311-9b37-43bc-83a6-4ca6565c3ffb-p1.html
17.防止SQL注入攻击的10种有效方法(防止SQL注入)SQL注入是一种常见的网络安全威胁,攻击者通过在用户输入中插入恶意的SQL代码,从而可以执行未经授权的数据库操作。这些方法包括使用参数化查询、输入验证和过滤、存储过程、最小权限原则、ORM框架、准备语句、安全的数据库连接、避免动态拼接SQL语句、使用防火墙和入侵检测系统以及定期更新和维护数据库软件。通过采取这些预防https://www.yundun.com/document/news/1012