众所周知,产生SQL注入漏洞的根本原因是SQL语句的拼接,如果SQL语句中的任何一部分(参数、字段名、搜索关键词、索引等)直接取自用户而未做校验,就可能存在注入漏洞。
攻击者通过构建特殊的输入作为参数传入服务器,导致原有业务逻辑中原有的SQL语句的语义被改变,或改变查询条件,或追加语句执行恶意操作,或调用存储过程等。
在公司没有实施SDL流程之前,
代码通常是这样写的(以互联网公司常用的PHP语言为例):
很显然,大部分教科书也是类似这样编写的,将SQL指令和用户提交的参数拼接成一个字符串,然后提交查询。
开发完成后,经过简单的功能及性能测试,就直接上线了。
一般过不了多久,就会有漏洞报告过来。
但这绝对不是安全上的最佳实践。
让我们来看看实施SDL流程之后,是如何在每一个关卡拦截漏洞的。
需求阶段有将安全纳入需求的要求,但针对此例暂时略过不提;
方案/设计阶段,还没有开始编码,此漏洞暂不涉及,我们直接从开发阶段开始。
假设开发人员没有安全意识,是按照前面存在风险的拼接SQL的方法编码的,让我们来看看一个SQL注入漏洞将要如何闯过项目的各个关卡,存活到最后。
第一道关卡,开发阶段的代码审计
如果公司实施了代码审计这一工序并采购了代码审计工具,会发现代码开发上的错误,给出提示和告警,根据其提供的参考意见加以改进;
发现可能的SQL注入漏洞,查看详情
如果是人工抽检SQL语句,有可能会发现,也可能会遗漏,但鉴于程序员的开发习惯,发现一个问题点即可带出很多个同样的风险点,执行批量改进,消除部分风险。
代码审计这一道关卡通常是可选的(除非签发规定强制实施)。
如果没有这一道工序,则一个潜在的SQL注入漏洞通过了此环节。
第二道关卡,开发阶段的安全自检和复核
项目进行到开发完成,在即将转给测试人员之前,项目流程上有一个安全任务要做:安全自检。
首先,网络安全团队发布有安全开发规范(名字不一定叫这个),针对SQL注入,应该有类似如下的条款:
SQL语句应使用预编译和绑定变量的机制以实现SQL指令和参数的分离,原则上禁止拼接SQL语句,如有必须拼接的场景,应对每个参数进行合法性验证,包括整型验证、单引号的数据库转义(将单引号转换为两个单引号)以及对列名作参数的场景进行白名单检查等
开发人员在开发的时候,如果不知道这个规范,则相应的安全意识教育和培训工作有待加强(暂时问题不大,稍后会有流程上的关卡等着开发人员);如果知道这个规范,就会相应的采用安全的编码,提前规避这个风险,以PHP为例,首先看mysqli:
对于PHP来说,推荐优先采用PDO,经过适当的配置即可很好的预防SQL注入;
对于C#,优先使用SqlParameter对参数进行处理。
如果采用了成熟的ORM框架,一般而言,框架已经可以很好的防止SQL Injection漏洞,与自己写SQL语句相比,即提高了开发的效率,安全性方面也有较好的保障。
千万不要再自己写过滤了!!!
繁琐不说,写的往往都不好(各种绕过),还影响性能!
如果是按照这种预编译的方式,SQL指令和参数是分离的,不会再引入SQL注入漏洞。
要做安全自检,当然少不了一个Checklist模板文档,它由网络安全团队根据发布的标准、规范、策略等文件拟制而成,项目组需要逐条Check,在后面打勾(表示符合)或打叉(表示不符合)。
是否采用预编译和绑定变量的机制以实现SQL指令和参数的分离(符合 / 不符合)
在做自检的过程中,发现了不符合项(条款),一般比较容易改进的漏洞,很快项目组就自己改进了,消除了风险;暂时改进不了的,先留在那里,待评估后再议,制定改进计划或采取一定的规避措施之后接受风险。
安全自检做完之后,需要由来自网络安全团队的人员(可称之为“安全代表”)复核,网络安全代表会基于自检反馈,进行风险评估和相应的抽检,没有问题之后放行。
安全自检任务也可能跟方案评审或开发评审合在一起。
如果开发过程没有安全审核,则漏洞被带入测试环节。
第三道关卡,基于用例的安全测试
现在,项目处于测试阶段,测试人员要对应用进行安全测试了。
测试人员都不怎么懂安全,该如何进行测试呢?
这个问题好比,古代部队里的士兵基本都不会武术,更不要提什么枪法、剑法、降龙十八掌、六脉神剑等高神的武艺,他们如何击败敌人呢?
原来,打仗靠的是兵法和谋略,并不要求每个士兵都是武侠。
但是,武侠技艺中的一些简单、高效的实用技法,可以传授给士兵,提高军队整体的作战能力。
比如,豹子头林冲,担任八十万禁军教头,传授士兵一些实用的枪法,以提高军队的整体作战能力。
网络安全团队的一个重要任务,就是需要有人担任渗透测试教头的角色,建立测试用例,输出指导手册,对测试人员进行培训,把渗透测试中简单实用的测试技法传授给测试人员,让测试人员学会如何基于给定的测试用例,得出产品的某个变量在指定的用例上是否安全的结论。
就本文讨论的SQL注入漏洞,部分测试用例参考:
上述用例,如果前面的用例可以确认漏洞的话,则忽略后面的用例。
测试人员发现存在漏洞之后,即可告知开发人员修改,通常来说,发现一处,即可举一反三,让开发人员一并把同类问题都给修改了。
如果没有执行安全测试,则漏洞会被带入生产环境。
流程走到这里,如果没有绕过的话,大部分风险基本可以控制住。
更多的漏洞发现,就看后面的了。
第四道关卡,上线前的渗透测试
上线前,如果是公司的明星产品(主打产品),一般需要专职的网络安全渗透测试人员参与进来。
渗透测试人员将发现的漏洞提给开发团队改进,消除这部分风险。
这时,基本可以消除绝大部分的高危漏洞。
如果是普通的产品,很可能渗透测试人员忙不过来或者并不要求执行渗透测试,则这些普通产品中的漏洞会被带入生产环境。
这时,项目流程处于发布阶段(在生产环境实施,但尚未验收)。
运维团队需要基于网络安全团队和运维团队共同制定的安全配置规范和脚本,对生产环境的操作系统、中间件等执行安全配置,如:
执行通用的安全配置脚本 关闭不需要的端口 数据库端口和运维端口禁止互联网访问 对互联网屏蔽后台管理入口 配置静态解析用户上传的资源 纳入安全防御基础设施防御范围(WAF等)
安全部署,可以在产品本身仍存在一些缺陷(漏洞)的情况下,仍能够具备基本的安全防御能力,将大部分恶意入侵者挡在企业门户之外。
拦截User-Agent及其它头部、URL、变量名、变量值中的正则匹配 拦截同一用户的高频访问请求
如果没有实施安全部署,则要看验收环节,验收人员有没有认真检查了。
确认安全部署结果 备份及恢复演练 修改各操作系统、数据库口令
安全验收是对安全部署的确认,必要的运维管理移交,回收在发布过程中可能泄露的口令,保障高可用性。
如果这一关卡被忽视,则无法确保执行了安全部署,如果产品仍带有SQL注入漏洞,且未纳入WAF保护范围,则产品面临被注入的风险。
第七道关卡,上线后的安全应急响应
应该说,这时项目已经结束了。但产品的生命周期却开始不久,运行中的产品面临来自互联网的各种威胁。对于很多中小型企业来说,前面的关卡几乎一个都没有,被入侵几乎是必然的。
如果收到来自外部的漏洞报告,则启动应急响应,执行应急防御措施和产品改进,尽可能的举一反三批量改进,降低风险,防止漏洞被利用。
上述各关卡,其实就是SDL流程中的关键安全任务。这些任务执行下来,能够在很大的程度上降低产品上线后所面临的安全风险。
如果不设安全上的任何管控,对开发的产品放任不管,则只能发现一个漏洞就处理一个漏洞,处于被动挨打的局面,无法从根本上扭转安全攻防形势。
对于很多中小型企业来说,也许没有足够的实力和预算来实施这套流程,这时不妨采取开放的心态,尝试使用互联网上的SDL SaaS服务(比如Janusec SDL SaaS等)。
本文由红日安全成员: Aixic 编写,如有不当,还望斧正。
大家好,我们是红日安全-Web安全攻防小组。此项目是关于Web安全的系列文章分享,还包含一个HTB靶场供大家练习,我们给这个项目起了一个名字叫 ,希望对想要学习Web安全的朋友们有所帮助。每一篇文章都是于基于漏洞简介-漏洞原理-漏洞危害-测试方法(手工测试,工具测试)-靶场测试(分为PHP靶场、JAVA靶场、Python靶场基本上三种靶场全部涵盖)-实战演练(主要选择相应CMS或者是Vulnhub进行实战演练),如果对大家有帮助请Star鼓励我们创作更好文章。如果你愿意加入我们,一起完善这个项目,欢迎通过邮件形式联系我们。
如果出现ip无法访问的情况改一下代码即可
构造语句进行盲注,发现不能使用mid只能使用substr。。
这个漏洞环境用到了 SQLITE3 中的 CASE 窗口函数与 RANDOMBLOB 来实现的基于时间的盲注。
基于联合查询注入: 使用
UNION运算符用于SQL注入,UNION
运算符是关联两个表的查询结果。攻击者故意伪造的恶意的查询并加入到原始查询中, 伪造的查询结果将被合并到原始查询的结果返回,攻击者会获得其他表的信息。
这里我们采用Vulnhub靶场进行演练。
Vulnhub是一个提供各种漏洞环境的靶场平台,供安全爱好者学习渗透使用,大部分环境是做好的虚拟机镜像文件,镜像预先设计了多种漏洞,需要使用VMware或者VirtualBox运行。每个镜像会有破解的目标。
Graceful的VulnVM是在虚拟机上运行的Web应用程序,它旨在模拟一个简单的电子商务风格网站,该网站特意容易受到Web应用程序中常见的许多众所周知的安全问题的影响。这实际上是该项目的预发布预览版,但它确实具有实用性,但我计划在不久的将来对此进行大量工作。
该计划最终使应用程序容易受到大量问题的影响,选择不同的过滤器处于不同的困难,以便测试人员能够更好地检测和利用应用程序可以通过常见的开发方法加强的问题,以便测试人员能够更广泛的经验。
第一批过滤器现已实施!该应用程序现在支持“级别”,其中级别1不包括用户输入的实际过滤,级别2包括针对每个易受攻击的功能的简单过滤器。
在products.php页面存在盲注,通过测试发现是数字型盲注
构造语句爆破数据库名,使用之前的python脚本进行爆破。
爆破出来数据库名为seattle
判断出来数据库存在3个表
开始爆字段,用如下语句
一直爆不出来字段,发现原来是这种爆破脚本存在一个无法分辨大小写的问题。改进一下脚本,变成ASCII的判断。
重新尝试爆破字段,改一下语句,用python来跑
最终代码如下,因为可能会因为字符长度过长导致时间过长的问题,就加了个判断d,这样40位的名字也可进行判断
进行UNION注入构造语句,发现并没有显示位。所以只能进行报错盲注了
跟上面几乎一样,就是利用的地方不一样
可以自定义关键字建立数组即可
把查询语句弄成一个对象,通过函数判断输入进来的值是否为数字,然后再通过正则替换内容
使用参数化查询可有效避免SQL注入
五指互联由原盛大集团PHPCMS负责人王参加创办,汇聚众多国内资深CMS开发者,拥有一支战斗力强、专业的技术团队,有超过10年的CMS专业开发经验。
构造url链接,使用SQLMAP可获取数据库敏感数据。
抓包把数据包放到sqlmap上跑
可以自定义关键字建立数组即可
把查询语句弄成一个对象,通过函数判断输入进来的值是否为数字,然后再通过正则替换内容
使用参数化查询可有效避免SQL注入
单引号(’)双引号(")反斜杠(\)NULL
预定义的字符是:& (和号)成为 &" (双引号)成为 "’ (单引号)成为 ’<>成为 <>就是把成变成一个纯字符(:з」∠)
会在以下关键词前面添加转义字符单引号(’)双引号(")反斜杠(\)NULL