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 {
              width: 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;
              width: 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

posted @ 2022-01-25 10:01  女友在高考  阅读(304)  评论(0编辑  收藏  举报