• Web安全防护(二)


    点击劫持

    点击劫持,也称UI覆盖攻击

    1.1 iframe覆盖攻击

    黑客创建一个网页,用iframe包含了目标网站,并且把它隐藏起来。做一个伪装的页面或图片盖上去,且按钮与目标网站一致,诱导用户去点击。伪装的按钮背后可能就会执行了危险操作。

    <!DOCTYPE html>
    <html>
    <meta http-equiv="Content-Type" content="text/html;
    charset=utf-8">
    <head>
        <title>点击劫持 POC</title>
          <style>
            iframe {
                   1440px;
                  height: 900px;
                  position: absolute;
                  top: -0px;
                  left: -0px;
                  z-index: 2;
                  -moz-opacity: 0;
                  opacity: 0;
                  filter: alpha(opacity=0);
               }
            button {
                  position: absolute;
                  top: 270px;
                  left: 1150px;
                  z-index: 1;
                   90px;
                  height:40px;
               }
          </style>
    </head>
    <body>
    <button>美女图片</button>
    <img src="http://pic1.win4000.com/wallpaper/2018-03-
    19/5aaf2bf0122d2.jpg">
    <iframe src="http://i.youku.com/u/UMjA0NTg4Njcy"
            scrolling="no"></iframe>
    </body>
    </html>
    

    防护方案:

    使用一个HTTP头-X-Frame-Options。它可以设置frame的加载权限。它有三个可选的值:

    • DENY:浏览器会拒绝当前页面加载任何frame页面
    • SAMEORIGIN:frame页面的地址只能为同源域名下的页面
    • ALLOW-FROM uri:允许frame加载的页面地址

    nginx配置:

    add_header X-Frame-Options SAMEORIGIN;
    

    1.2 图片覆盖攻击

    图片覆盖攻击,攻击者使用一张或多张图片,利用图片的style或者能够控制的CSS,将图片覆盖在网页上,形成点击劫持。

    <a href="http://tieba.baidu.com/f?kw=%C3%C0%C5%AE">
      <img src="XXXXXX"
    style="position:absolute;top:90px;left:320px;" />
    </a>
    

    你以为你点了图片,其实你点了其他的链接。

    防护方案:

    在防御图片覆盖攻击时,需要检查用户提交的HTML代码中,img标签的style属性是否可能导致浮出。

    URL跳转漏洞

    URL跳转漏洞(URL重定向漏洞),跳转漏洞一般用于钓鱼攻击

    攻击原理:

    URL跳转漏洞本质上是利用Web应用中带有重定向功能的业务,将用户从一个网站重定向到另一个网站。

    示例:http://www.
    aaa.com?returnUrl=http://www.evil.com,www.aaa.com 有一个功能会取到returnUrl后的路径,然后跳转。这种功能就会被黑客利用,跳转到他想跳转的其他页面上去。

    一般容易出现的漏洞的点:

    • 登录跳转、第三方授权
    • 分享
    • 收藏

    URL跳转漏洞校验绕过

    1. 域名字符串校验
    //获取参数
    String url = request.getParameter("returnUrl");
    //判断是否包含域名
    if (url.indexOf("www.abc.com ") !=-1){ 
      response.sendRedirect(url);
    }
    

    黑客可以注册一个包含abc.com的域名来绕过,如:
    http://www.abc.com?returnUrl=http://www.abc.com.evil.com
    2. 利用URL的各种特性符号

    http://www.aaa.com?returnUrl=http://www.evil.com?www.aaa.com
    http://www.aaa.com?returnUrl=http://www.evil.comwww.aaa.com
    http://www.aaa.com?returnUrl=http://www.aaa.com@www.evil.com
    http://www.aaa.com?returnUrl=http://www.evil.com#www.aaa.com
    

    防护方案

    1. 代码固定跳转地址,不让用户随意输
    2. 跳转目标地址采用映射机制,如 1代表aaa.com,2代表bbb.com这样,用户只能输1和2才能过校验
    3. 合理充分的校验机制,校验跳转的目标地址,非己方的地址跳转时可以提示用户,类似知乎做的那种。

    Session攻击

    通过窃取用户SessionId,使用SessionId登录进目标账户的攻击方法。如果SessionId是保存在Cookie中的,则这种攻击可以称为Cookie劫持。

    3.1 Session劫持

    攻击原理:

    1. 目标用户登录网站
    2. 登录成功后,用户的SessionId服务器会认为是已登录的,可以做一些他权限内的操作
    3. 攻击者通过某种攻击手段捕获Session ID
    4. 攻击者通过捕获到的Session ID访问站点即可获得目标用户合法会话。

    获取SessionId的方式有多种:

    1. 暴力破解:不断尝试各种Session ID
    2. 预测:如果Session ID使用非随机的方式产生,那么就有可能计算出来
    3. 窃取:使用网络嗅探、本地木马窃取、XSS攻击等方法

    防御方法:

    1. Cookie HttpOnly
    2. Cookie Secure,是设置Cookie时,可以设置的一个属性,设置了之后只有https访问时,浏览器才会发送该cookie。这样攻击者从网络上窃听到,也是拿到一个加密的cookie
    response.setHeader("SET-
    HEADER","user="+request.getParameter("cookie")+";HttpOnly;Sec
    ure");
    

    3.2 会话固定

    会话固定是让用户使用黑客预先设置的sessionID进行登录,这样同样黑客能拿到用户SessionId。

    攻击步骤:

    1. 攻击者通过某种手段重置用户的SessinoID,然后监听用户会话状态
    2. 目标用户携带攻击者设定的Session ID登录站点
    3. 攻击者通过Session ID获得合法会话

    攻击者如果让目标使用黑客的Session ID呢?如果是保存在Cookie中是比较难做的,但如果是SessionID保存在URL中,则攻击者只要诱导用户打开这个URL即可。

    防御方法:

    1. 用户登录的时候就进行重置SessionID
    // 会话失效
    session.invalidate();
    // 会话重建
    session=request.getSession(true);
    
    1. SessionID闲置过久时,进行重置
    2. 设置HttpOnly

    3.3 Session保持攻击

    一般情况下,Session是有生命周期的,当用户长时间未活动,或者用户点击退出后,服务器将销毁Session。但如果攻击者拿到了一个用户的Session,它可以通过不停的发起访问请求,让Session一直存活。

    <script>
     //要保持session的url
     var url =
    "http://bbs.yuanjing.com/wap/index.php?/sid=LOXSAJH4M";
     //定时任务
     window.setInterval("keeyId()",6000);
     function keepsid(){
     
     document.getElementById("iframe1").src=url+"&time"+Math.rand
    om();
    }
    </script>
    <iframe id="iframe1" src=""/></iframe>
    

    攻击者设置可以为Session Cookie增加一个Expire事件,使得原本浏览器关闭就会失效的Cookie持久化地保存在本地。

    防护方案:

    1. 可以设置一个固定的时间,如3天后就强制过期,但是也影响了正常用户
    2. 比如用户的IP、UserAgent信息发生变化,就可以强制销毁当前的Session,并要求用户重新登录

    注入攻击

    注入攻击是Web安全领域中一种最常见的攻击方式。XSS本质上也是一种针对HTML的注入攻击。注入攻击的本质,是把用户输入的数据当做了代码执行。这里有两个关键条件,第一个是用户能控制输入,第二个是原本程序要执行的代码拼接了用户输入的数据。解决注入攻击的核心思想:数据与代码分离原则

    4.1 SQL注入

    本应该输入正常的数据,而黑客却输入一些sql语句。如果应用程序比较脆弱的话,则可能应用程序会被攻击。

    最简单的示例就是一个:查询某个用户

    String query = "select * from accounts where name ='"+request.getParameter("name")+"';
    

    用户如果输张三李四是没问题的,如果输入 李四 or 1=1 那么它会查到所有用户数据。

    容易导致SQL注入的弱点:

    1. 应用程序中使用字符串连接方式或联合查询方式组合SQL语句
    2. 应用程序连接数据库时使用权限过大的账户(很多开发人员喜欢直接用管理员账户)
    3. 未校验用户输入的字符串

    攻击步骤:

    1. SQL盲注

    所谓盲注,就是在服务器没有返回错误信息的情况下完成的注入攻击。最常见的盲注验证方法是构造简单的条件语句,根据返回的页面是否变化来判断是否存在漏洞。

    示例:下面是一个根据userId查询用户的功能:

    1) 我先输入

    1 ' and 1=1 #


    发现能查询到数据

    2)再输入

    1 ' and 1=2 # 发现查不出数据,证明注入成功。

    1. 猜解数据库

    3)继续输入利用order by猜列数

    1' order by 1 #
    成功,然后输入 1' order by 2 # ,依次递增,直到提示
    Unknown column '3' in 'order clause'

    成功得到该表的列数。

    4)知道列数之后,使用union select 联合查询获取更多的信息,union 查询的使用前提是关联查询的两个查询列数要一致

    1 ' union select database(),user() #

    查询到数据库名和当前查询的用户名

    5)继续查询当前数据库版本、操作系统

    1 ' union select version(),@@version_compile_os#

    6)根据数据库名,查询里面的表

    1 ' union select table_name,table_schema from information_schema.tables where table_schema= 'dvwa' #

    7)猜users表的字段,根据经验试试是不是user和password

    1' union select user,password from users#

    成功爆出了某网站的用户名和密码

    1. ORM注入

    1) Mybatis:
    ${}:单纯替代,纯粹的将参数传进去,没有做任何的转义操作和预编译。
    #{}: Mybatis会通过预编译机制生成PreparedStatement参数,然后再安全的给参数赋值

    ${}是存在注入风险的。

    2) Hibernate

    usernameString//前台输入的用户名
    passwordString//前台输入的密码
    //hql语句
    String queryString = "from User t where t.username= " +
    usernameString + " and t.password="+ passwordString;
    //执行查询
    List result = session.createQuery(queryString).list();
    

    通过hql拼接的方式不安全。建议用参数绑定:

    usernameString//前台输入的用户名
    passwordString//前台输入的密码
    //hql语句
    String queryString = "from User t where t.username:
    usernameString and t.password: passwordString";
    //执行查询
    List result = session.createQuery(queryString)
              .setString("usernameString ",
    usernameString )
              .setString("passwordString",
    passwordString)
              .list(); 
    

    3)JDBC:使用预处理执行SQL语句,对所有传入SQL语句中的变量做绑定,这样用户拼接进来的变量无论内容是什么,都会被当做替代符号"?"所替代的值。

    示例:

    String sql = "select * from users where userid = " + userid;
    

    如果用户输入userid是"1;delete users;"会被编译成2条sql,那么users表会被非法删除。

    但是如果是预编译的方式,那么会编译成一条sql,查询userid为'"1;delete users;"的用户,查询结果会是不存在,不会存在危险。

    4.2 XML注入

    XML注入是将用户录入的信息作为XML节点。
    示例:

    //userData是准备保存的XML数据,接受了name和email两个用户提交的数据
    String userData = "<USER >"+
     "<name>"+
     request.getParameter("name")+
     "</name>"+
     "<email>"+
     request.getParameter("email")+
     "</email>"
      "</USER>"
    //保存XML数据
    userDao.save(userData);
    

    如果用户输入的时候name输入张三,email输入:

    user1@lagou.com</email></USER><USER><name>user2</name>
    <email>user2@lagou.com
    

    这样就恶意构造了一个xml,拼接起来一次保存了两条数据。

    防护方案:

    对xml数据进行转义:

    String userData = "<USER>"+
      "
    <name>"+StringUtil.xmlEncode(request.getParameter("name"))+"
    </name>"+
      "
    <email>"+StringUtil.xmlEncode(request.getParameter("email"))+
    "</email>"+
      "</USER>";
    

    4.3 代码注入

    web应用程序中如果有允许接收用户输入一段代码并执行。那么用户可以根据这个功能写一个远程控制木马,进行恶意攻击。代码注入往往是由一些不安全的函数或者方法引起的,其中的典型代表就是eval()

    public static void main(String[] args) {
        //在Java中也可以实施代码注入,比如利用Java的脚本引擎。
        ScriptEngineManager manager = new
    ScriptEngineManager();
        //获得JS引擎对象
        ScriptEngine engine =
    manager.getEngineByName("JavaScript");
        try {
          //用户录入
          String param = "hello";
          String command = "print('"+param+"')";
          //调用JS中的eval方法
          engine.eval(command);
       } catch (ScriptException e) {
          e.printStackTrace();
       }
     }
    

    攻击示例:

    hello'); var fImport = new JavaImporter(java.io.File);
    with(fImport) { var f = new File('new'); f.createNewFile(); }
    

    防护方案:

    对抗代码注入,需要禁止eval()等可以执行命令的函数,如果一定要用,则需要对用户输入的数据进行处理。如只能由开发人员定义代码内容,用户只能提交对应的id”1、2、3“等参数。

    4.4 OS命令注入

    OS命令注入(操作系统命令注入),仅当Web应用程序代码包括操作系统调用,并且使用了用户的输入内容。

    示例:
    应用程序开发人员希望用户能够在Web应用程序中查看Ping命令的输出。用户正常输入ip,那还好。

    如果输入:

    127.0.0.1 && whoami
    或者
    127.0.0.1 && ps -ef
    就能够执行一些危险的操作。

    防护方案:

    最有效的方法就是不要再应用程序代码中调用OS命令。如果非要这么搞,那么还是一样需要对用户输入进行严格的验证。

    文件操作防护

    5.1 文件上传漏洞

    互联网当中,我们经常用到文件上传功能,传excel、传图片、传视频等等。文件上传后,服务器的处理逻辑如果做的不够安全,就会导致漏洞的产生。

    文件上传后导致的常见安全问题一般有:

    • 上传文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本
    • 上传文件是病毒、木马文件,然后诱使用户或管理员下载执行
    • 上传文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。

    防护方案:

    1. 检查上传文件扩展名
    2. 上传文件的目录必须是http请求无法直接访问到的。如果需要访问,需要上传到其他(和web服务器不同的)域名下,并设置该目录为不可执行目录
    3. 上传文件要保存的文件名和目录名由系统根据时间生成,不允许用户自定义
    4. 图片上传,要通过处理(缩略图、水印等),无异常才能保存到服务器
    5. 上传文件需要做日志记录

    5.2 文件下载和目录浏览漏洞

    文件下载和目录浏览漏洞是属于程序设计和编码上的不严谨导致的。处理用户请求下载文件时,用户提交文件路径,就把服务器上对应的文件发送给用户,这就造成了任意文件下载危险。如果用户提交目录,就把目录下的文件列表发给用户,会造成目录遍历安全威胁。良好的设计应该是:不允许用户提交任意文件路径进行下载,而是用户单机下载按钮默认传递ID到后台程序。

    防护方案:

    1. 要下载的文件地址保存在数据库中
    2. 文件路径保存至数据库,让用户提交文件对应ID下载文件
    3. 下载文件之前做权限判断
    4. 文件放在web无法直接访问的目录下
    5. 记录文件下载日志
    6. 不允许提供目录遍历服务

    访问控制

    6.1 功能权限漏洞

    功能权限漏洞是指Web应用没有做权限控制,或仅仅在菜单上做了权限控制,导致恶意用户只要猜到了其他页面的URL地址,就可以访问到他权限外的页面和数据。

    防护方案:

    针对任何URL,每次用户访问,都要判断用户是否有访问此URL的权限。

    6.2 数据权限漏洞

    这种问题出现在未对用户与数据级别之间建立关系,如用户A和用户B都有查询订单的权限,但是A只能查询A的订单,B只能查B的订单。如果只校验用户是否有某个功能的权限,不校验时候有这个数据的权限,就会出现越权问题。

    防护方案:

    根据用户的ID做好数据级权限控制,比如针对CRUD操作进行身份验证,且对用户访问的数据进行数据权限校验,防止通过修改ID的方式查看别人的数据。

    DDOS攻击

    7.1 DDOS攻击

    DDOS(Distributed Denial of Service)又称为分布式拒绝服务,DDOS是利用合理的请求造成资源过载,导致服务不可用。常见的DDOS攻击有SYN flood、UDP flood、ICMP flood等。其中SYN flood是一种最为经典的DDOS攻击,其发现于1996年,至今仍然保持着非常强大的生命力。SYN flood如此猖獗是因为它利用了TCP协议设计中的缺陷,而TCP/IP是整个互联网的基础,想要修复这样的缺陷机不是不可能的事情。

    SYN flood攻击原理:

    SYN flood攻击是根据TCP协议的三次握手过程进行的攻击。在TCP服务器收到SYN请求包时,在发送ACK包回去之前,TCP服务器需要先分配一个数据区专门服务于这个快形成的TCP连接。

    在常见的SYN flood攻击中,攻击者短时间内发送大量的SYN包给受害者服务器,服务器需要为每个TCP SYN包分配一个数据区,只要这些SYN包具有不同的源地址。这将给受害者服务器造成很大的系统负担,最终导致系统不能正常工作。

    SYN flood防护方案:

    syn cookie:

    syn cookie是通过修改TCP三次握手协议,来专门防御DDOS的一种手段。服务器收到客户端的SYN包,并且返回一个ACK+SYN包时,不专门分配一个数据区,而是根据这个包计算出一个cookie值。然后再收到ACK包时,服务器根据这个cookie值检查这个ACK包是否合法。如果合法,再分配专门的数据区进行处理未来的TCP连接。

    7.2 CC攻击

    CC攻击是DDOS攻击的一种,可以看作是应用层面的DDOS攻击。攻击原理是:针对一些耗费资源较大的应用页面不断发起请求,以达到消耗服务器资源的目的。

    防护方案:

    1. 代码要做好性能优化,合理的使用缓存,减轻数据库负担
    2. 网络架构优化,善用负债均衡,避免用户流量集中在单台服务器,同时可以充分利用CDN和镜像站点的分流作用,缓解主站的压力。
    3. 使用页面静态化技术,利用客户端浏览器的缓存功能或服务器的缓存功能,CDN节点的缓冲服务,均可以降低服务器的检索压力和计算压力。
    4. 也可以使用一些对抗手段。如限制每个ip的请求频率,超出频率的ip加入黑名单

    IP黑白名单的开发

    可以使用OpenResty+Lua脚本实现。也可以使用KONG

  • 相关阅读:
    ZOJ 4097 Rescue the Princess
    最大值最小化 最小值最大化
    SD第九届省赛B题 Bullet
    Euler Circuit UVA
    bzoj 1878
    随笔
    BZOJ
    主席树模板
    AC自动机模板
    BZOJ
  • 原文地址:https://www.cnblogs.com/javammc/p/15841824.html
Copyright © 2020-2023  润新知