网站10大常见安全漏洞及解决方案

[](https://cl

一般来说牛逼点的地方都会通过安全设备来确保网络环境的安全,所以之前我们也都认为程序员不需要过多的考虑网站安全问题。实际上随着做了几个事业单位的网站之后,也逐渐发现有些方面还是需要程序员注意的。

1. SQL注入 安全等级★★★★★

几乎每一个网站后台开发人员都听到的一个词,并且都很敏感,但是不知道是什么原因造成的很多程序员却在实际开发过程中经常忽视这个问题。前段时间部门一位新同事,据说是5年工作经验,在对他的代码做评审时,我们发现所有的DAO层实现都是直接拼接SQL和参数,总监多次提醒他这个问题,但他也没有发现,直到总监说出SQL注入这个词。

实际上这个漏洞很严重,一旦被注入成功,后果不堪设想,但这类问题处理起来还是蛮简单的,下面以JAVA为例举例说明

方案一: 编写拦截器过滤请求(不推荐),此方案建议只在对维护中项目或者代码结构比较乱的情况下使用,底层不容易修改或者不方便修改。此方案效率低,效果也不佳。

/**
 * 校验参数,判断是否包含sql关键字表达式
 * 此方法会有误伤
 */ 
  
    private static boolean sqlValidate(String str) {  
        str = str.toLowerCase();//统一转为小写  
        String badSqlStr = "'|exec|execute|insert|select|delete|update|count|drop|chr|mid|master|truncate|char|declare|sitename|net user|xp_cmdshell|create|drop|"
                             +"table|from|grant|use|group_concat|column_name|1=1|=|"   
                             +"information_schema.columns|table_schema|union|where|*|"  
                          +"chr|mid|master|truncate|char|declare|or|;|,|like|//|/|%|#|-|--|+|";
        String badXssStr = "frame|iframe|script|javascript|=|<|>";
        
        //sql 关键词 有空格分隔
        String[] badSqlStrs = badSqlStr.split("\\|");  
        for (int i = 0; i < badSqlStrs.length; i++) {  
            if (str.indexOf(" "+badSqlStrs[i]) >= 0 || str.indexOf(badSqlStrs[i]+" ") >= 0) {  
                return true;  
            }  
        }
 
        } 
        
        return false;  
}

方案二:推荐方案,使用预编译的prepareStatement代替statement;使用框架中的setParameter设置参数,此方案可有效处理SQL注入问题。

@Override
      public List<NewsColumn> getColumnListByType(String columnType) {
            String jql = " FROM "+NewsColumn.class.getName(,)+" WHERE type=:type ";
            List<NewsColumn> list = entityManager.createQuery(jql).setParameter("type", columnType).getResultList();
            return list;
      }

2. 验证码必须后台校验 安全等级★★★★

前段时间一客户说后台管理看到了一堆这样用户,/etc/init.d /1=1 ./././ …. Windows/ ,本该截图的,后来处理了就给忘了~~~~,反正从注册内容来看,可以确定两点,通过注册机注册,想通过注册注入攻击。

通过机器注册:直接跳过了前端的表单校验,而恰巧这个项目在开发的时候,验证码只在前端做了校验,提交到后台没有做再一次的校验,也就是这个漏洞导致了这堆垃圾注册。

解决方案:前台提交数据到后台后做进一步校验,如验证码校验、数据格式校验、验重校验。

回想我也曾经用过这个漏洞…老东家海航集团2014年的时候,OA系统添加了登录需要手机短信验证,当时系统更新后第一个版本就是仅做了前台校验,这个漏洞无意中被我发现了,因为每天都要登录OA,每次都要短信实在太麻烦了,我就尝试模拟了个表单请求,重写原登录系统表单提交的脚本,在所有的验证我都直接返回true。很激动的是,一次就成功了,后来也分享给我们同事了,大家都很开心。但随后不久,系统就升级了,后台验证,你们懂得。当然对当时的信息部同事来说,我就是一个坏人……

3. 防止表单重复提交 安全等级★★★

防止表单重复提交其实网上有很多解决方案,并且现在主流的前端框架都可以在页面上做按钮控制,不过做为一个程序员,你们懂得,这并没有什么卵用。个人还是建议采用实际的后台验证法处理。从网上爬文,看到的靠谱的解决方案如下。

解决方案:token验证,请求页面时生成token并放在session中,提交表单到后台验证token,业务逻辑处理完之后,清除token。如果表单提交了一次,token就没了,再次提交就无法通过了。

方案分析:此方法和验证码基本上一致,如果验证码在每次表单提交后都清除一次,也能达到这样的效果。

其他建议:重要的表单页面提交后重定向,取消表单的autocomplete。

4. 文件上传格式校验 安全等级★★★★

黑客攻击网站还有一个常见的方式就是通过文件上传漏洞,比如网站上传图片的功能没有严格校验后缀名。黑客可以通过此功能上传一些脚本文件,上传成功后,通过请求这些脚本文件运行脚本中的功能达到攻击的目的。

那么如果验证了上传文件的后缀名就可以吗?实际上并不是,举例说我们知道页面引入script标签时src写啥都行,比如http://www.baidu.com/123.jpg,也是可以的,攻击者只需要把一个script文件后缀名改为jpg即可通过后缀验证,后面一路畅通。所以这就提到了验证文件的真实格式。如何验证,网上一大堆…

解决方案:设置php文件、jsp文件不可直接被访问(不知道php可以不,jsp放在WEB-INF即可),这样攻击者上传此类文件也无法执行;通过文件头信息严格验证文件格式,从上传功能开始防范。

5. 熟悉使用框架或数据库版本情况 安全等级★★

实际开发中,我们都使用一些开源框架,但这些框架也不是百分百完善的,比如webwork,struts2就经常爆出一些漏洞,这个需要开发者自行关注。

解决方案:根据官方发布的方案进行版本升级;根据公开的漏洞执行方式编写拦截器。

Struts2 s2-016 漏洞处理实例(项目结构不允许版本升级),拦截器,实际上官方的版本也是升级后过滤了一些参数。

@Override
       public void doFilter(ServletRequest request, ServletResponse response,
                     FilterChain filterChain) throws IOException, ServletException {
              HttpServletRequest req = (HttpServletRequest) request;
           HttpServletResponse res = (HttpServletResponse)response;
           //禁止页面被frame
           res.addHeader("x-frame-options","SAMEORIGIN"); 
              Map parameterMap = req.getParameterMap();
        for (Iterator iterator = parameterMap.keySet().iterator(); iterator.hasNext();) {
            String key = (String) iterator.next();
            if ((key.contains("redirect:")) || (key.contains("redirectAction:")) || (key.contains("action:"))) {
             res.sendError(HttpServletResponse.SC_FORBIDDEN, "forbidden");
             System.out.println("----------非法操作-----------");
                return;
            }
        }
        filterChain.doFilter(request, response);
       }

6. 严禁在生产环境下使用缺省密码 安全等级★★

很多时候一些小网站,新人练手的网站(往往价格很便宜),在开发的过程中都要求很快,往往这些网站问题还是蛮多的。后台验证码处于关闭状态、账号密码常用admin/admin组合,看似方便了操作,实际是危险重重。甚至有时候,数据库链接密码都是root/空,这个危害大家都知道。由于没有验证码,用户密码又使用的缺省的,黑客爆破的概率异常的高,一旦获取了后台管理权限,剩下的就交给你了。

解决方案:通过配置测试模式和生产模式控制验证码验证,管理员账户必须使用非缺省加密处理,必要时使用物理验证。

7. 服务器端口尽可能少开 安全等级★★★

六月份一个客户的服务器被挂马了,服务器一直是他们自行维护,只在项目更新时给我们开放远程。无意中发现服务器防火墙竟然是关闭状态我的天呐,是不是所有端口都处于开放状态呐你们以为这就是惊喜,惊喜还在后面呢,客户提供的MySQL数据库用户名明码是root root,个人认为这个才是惊喜。root/root和root/空是一样的效果。分析了一下,防火墙关闭了,3306也就开了,黑客发现3306开着,root/root能连接,通过windows漏洞提升root用户为系统用户,bingo,竟然可以登录这台服务器欸,简直棒棒哒。

解决方案:防护墙打开,仅开放必要的端口如80,13389,设置远程登录IP白名单。再次强调不要用缺省账户。

8. Options方法过滤 安全等级★

这个问题网上提到的都是很严重,但现在并没有发现多少案例,或许处理方案比较简单吧。

解决方案:在web.xml添加配置

<!-- 过滤不安全的请求方法 -->  
    <security-constraint>     
    <web-resource-collection>     
       <url-pattern>/*</url-pattern>     
       <http-method>PUT</http-method>     
    <http-method>DELETE</http-method>     
    <http-method>HEAD</http-method>     
    <http-method>OPTIONS</http-method>     
    <http-method>TRACE</http-method>
    </web-resource-collection>     
       <auth-constraint>     
       </auth-constraint>     
    </security-constraint>     
    <login-config>     
        <auth-method>BASIC</auth-method>     
    </login-config>

9. XSS攻击、CSRF攻击 安全等级★

XSSS攻击处理方案一般来说也是通过拦截器过滤请求参数,都是常规的处理方案。

package com.interceptor;
 
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
 
/**
 * <p>
 *  类说明
 * </p>
 * @author shy
 * @date 2016-4-21 下午03:34:26
 * @vesion $Revision$ $Date$ 
 */
 
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {
       HttpServletRequest orgRequest = null;  
         
    public XssHttpServletRequestWrapper(HttpServletRequest request) {  
        super(request);  
        orgRequest = request;  
    }  
  
    /** 
    * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/> 
    * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/> 
    * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖 
    */  
    @Override  
    public String getParameter(String name) {  
        String value = super.getParameter(xssEncode(name));  
        if (value != null) {  
            value = xssEncode(value);  
        }  
        return value;  
    }  
  
    /** 
    * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/> 
    * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/> 
    * getHeaderNames 也可能需要覆盖 
    */  
    @Override  
    public String getHeader(String name) {  
  
        String value = super.getHeader(xssEncode(name));  
        if (value != null) {  
            value = xssEncode(value);  
        }  
        return value;  
    }  
  
    /** 
    * 将容易引起xss漏洞的半角字符直接替换成全角字符 
    * 
    * @param s 
    * @return 
    */  
    private static String xssEncode(String s) {  
        if (s == null || "".equals(s)) {  
            return s;  
        }  
        StringBuilder sb = new StringBuilder(s.length() + 16);  
        for (int i = 0; i < s.length(); i++) {  
            char c = s.charAt(i);  
            switch (c) {  
            case '>':  
                sb.append('>');//全角大于号  
                break;  
            case '<':  
                sb.append('<');//全角小于号  
                break;  
            case '\'':  
                sb.append('‘');//全角单引号  
                break;  
            case '\"':  
                sb.append('“');//全角双引号  
                break;  
            case '&':  
                sb.append('&');//全角  
                break;  
            case '\\':  
                sb.append('\');//全角斜线  
                break;  
            case '#':  
                sb.append('#');//全角井号  
                break;  
            default:  
                sb.append(c);  
                break;  
            }  
        }  
        return sb.toString();  
    }  
  
    
    /** 
    * 获取最原始的request 
    * 
    * @return 
    */  
    public HttpServletRequest getOrgRequest() {  
        return orgRequest;  
    }  
  
    /** 
    * 获取最原始的request的静态方法 
    * 
    * @return 
    */  
    public static HttpServletRequest getOrgRequest(HttpServletRequest req) {  
        if (req instanceof XssHttpServletRequestWrapper) {  
            return ((XssHttpServletRequestWrapper) req).getOrgRequest();  
        }  
  
        return req;  
    }  
}

CSRF攻击(这个还在学习中)

解决方案:从网上爬文看到的基本上是一致的,校验Referer,添加请求token验证,个人觉得此漏洞在大型系统中比较重视,小网站就呵呵了。

10. frame引入控制 安全等级★

这个不知道为什么会被列入网站安全问题中,一个客户网站找了第三方安全检测公司检测网站有这个漏洞,所以就不得不处理。网上抄来的。

Java代码(拦截器中使用):

response.addHeader(“x-frame-options”,”SAMEORIGIN”);

Nginx配置:

add_header X-Frame-Options SAMEORIGIN

Apache配置:

Header always append X-Frame-Options SAMEORIGIN

接下来我将给各位同学划分一张学习计划表!

学习计划

那么问题又来了,作为萌新小白,我应该先学什么,再学什么?
既然你都问的这么直白了,我就告诉你,零基础应该从什么开始学起:

阶段一:初级网络安全工程师

接下来我将给大家安排一个为期1个月的网络安全初级计划,当你学完后,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web渗透、安全服务、安全分析等岗位;其中,如果你等保模块学的好,还可以从事等保工程师。

综合薪资区间6k~15k

1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(1周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(1周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(1周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

那么,到此为止,已经耗时1个月左右。你已经成功成为了一名“脚本小子”。那么你还想接着往下探索吗?

阶段二:中级or高级网络安全工程师(看自己能力)

综合薪资区间15k~30k

7、脚本编程学习(4周)
在网络安全领域。是否具备编程能力是“脚本小子”和真正网络安全工程师的本质区别。在实际的渗透测试过程中,面对复杂多变的网络环境,当常用工具不能满足实际需求的时候,往往需要对现有工具进行扩展,或者编写符合我们要求的工具、自动化脚本,这个时候就需要具备一定的编程能力。在分秒必争的CTF竞赛中,想要高效地使用自制的脚本工具来实现各种目的,更是需要拥有编程能力。

零基础入门的同学,我建议选择脚本语言Python/PHP/Go/Java中的一种,对常用库进行编程学习
搭建开发环境和选择IDE,PHP环境推荐Wamp和XAMPP,IDE强烈推荐Sublime;

Python编程学习,学习内容包含:语法、正则、文件、 网络、多线程等常用库,推荐《Python核心编程》,没必要看完

用Python编写漏洞的exp,然后写一个简单的网络爬虫

PHP基本语法学习并书写一个简单的博客系统

熟悉MVC架构,并试着学习一个PHP框架或者Python框架 (可选)

了解Bootstrap的布局或者CSS。

阶段三:顶级网络安全工程师

如果你对网络安全入门感兴趣,那么你需要的话可以点击这里👉网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!

学习资料分享

当然,只给予计划不给予学习资料的行为无异于耍流氓,这里给大家整理了一份【282G】的网络安全工程师从入门到精通的学习资料包,可点击下方二维码链接领取哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值