maven
本文将讨论如何使用Maven程序集创建可提供给第三方漏洞评估站点(例如Veracode )进行审查的工件。
错误的静态分析与漏洞评估
在这一点上,每个人都知道findbug并虔诚地使用它,对吗?
对?
Findbugs使用静态分析来查找错误。 更准确地说,它使用静态分析来查找可以通过静态分析发现的错误。 例如,我看到了一种常见的模式
public void foo(Object obj) {
if (obj != null) {
obj.doSomething();
}
// lots of obscuring code
obj.doSomethingElse()
}
我们应该第二次检查null吗? 我们需要第一次检查吗? 我们应该从“ if”子句中返回吗?
为什么我们还需要漏洞评估?
什么是漏洞评估? 它与错误有何不同?
关键概念是,易受攻击的代码表面上没有错误,但是仍然容易受到滥用以攻击该网站或其用户。
易受攻击的代码的一个示例是使用未经消毒的用户提供的值。 从事前端工作的任何人都应该了解净化这些价值的重要性。
但是,当用户提供的数据从前端传递出去时(例如,将其写入数据库时)会发生什么? 每个从数据库中提取数据的人都知道它可能包含未经消毒的用户提供的数据吗? 如何通过SQL注入将恶意数据放入数据库?
用于漏洞评估的静态分析与静态分析很像,可以发现漏洞,而且要经过很多检查。 而findbug可能需要5分钟才能运行Veracode,可能需要几个小时!
(动态分析使这一步骤更进一步,并针对实时系统运行测试。您可以使用集成测试来进行此测试的简化版。)
漏洞评估工件
我们需要提供什么来进行漏洞评估? 简短的答案是三件事:
- 我们的编译代码(例如,java或scala)
- 我们的脚本代码(例如,jsp)
- 递归地依赖于每个jar文件
我们不需要提供我们的源代码或资源。 编译后的代码确实需要包括调试系统,这样它才能给出有意义的错误消息-仅知道包含79个类的库中有19个缺陷不是很有帮助!
一个好的格式是包含以下内容的压缩包:
- 我们的jar和wars在顶层,没有版本号
- 我们在“ / lib”下的依赖,带有版本号
版本号被剥离或保留用于跟踪目的。 我们的代码在多次运行中具有连续性。 我们的依赖关系可以随时更改,并且除了版本号中明确指出的内容之外,没有任何连续性。
我们的war文件应该从嵌入式jar中删除,因为它们将出现在“ lib”目录下。 “厚”战争文件只会增加上传的工件的大小。
我们可以使用两个Maven程序集描述符来构建它。
va-war.xml(漏洞评估皮包骨头的战争)
第一个程序集创建一个精简的.war文件。 我不想称它为一场皮包骨头的战争,因为预期的目的有所不同,但它们有很多共同点。
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/plugins/maven/assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>va-war</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<!-- grab everything except any jars -->
<fileSet>
<directory>target/${project.artifactId}-${project.version}</directory>
<outputDirectory>/</outputDirectory>
<includes />
<excludes>
<exclude>**/*.jar</exclude>
</excludes>
</fileSet>
</fileSets>
</assembly>
如果您具有敏感信息或大量大型工件,则可以排除其他文件:
<excludes>
<exclude>**/*.jar</exclude>
<exclude>**/*.jks</exclude>
<exclude>**/*.p12</exclude>
<exclude>**/*.jpg</exclude>
<exclude>**/db.properties</exclude>
</excludes>
不过,您需要注意–您需要包含脚本编写的所有内容,例如jsp文件或Velocity模板。
va-artifact.xml(漏洞评估工件)
第二个工件收集所有依赖项,并将战争简化为一个压缩包。 我们的jar和wars在tarball的顶层,所有依赖项都在“ lib”目录中。 这使得区分工件和依赖关系变得容易。
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://maven.apache.org/plugins/maven/assembly-plugin/assembly/1.1.2
http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>va-artifact</id>
<formats>
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<!-- ******************************************* -->
<!-- Our code should not include version numbers -->
<!-- ******************************************* -->
<dependencySet>
<includes>
<include>${project.groupId}:*:jar</include>
<include>${project.groupId}:*:va-war</include>
<!-- we could also include subprojects -->
<include>${project.groupId}.**:*:jar</include>
</includes>
<!-- we might have sensitive resources -->
<excludes>
<exclude>${project.groupId}:*-properties</exclude>
<excludes>
<outputFileNameMapping>${artifact.artifactId}${dashClassifier?}.${artifact.extension}</outputFileNameMapping>
</dependencySet>
<!-- *********************************************** -->
<!-- Our dependencies should include version numbers -->
<!-- *********************************************** -->
<dependencySet>
<outputDirectory>lib</outputDirectory>
<includes />
<excludes>
<exclude>${project.groupId}:*</exclude>
<exclude>*.pom</exclude>
<!-- exclude standard APIs -->
<exclude>javax.*:*</exclude>
<exclude>dom4j:*</exclude>
<exclude>jaxen:*</exclude>
<exclude>jdom:*</exclude>
<exclude>xml-apis:*</exclude>
</excludes>
</dependencySet>
</dependencySets>
</assembly>
构建工件
汇编描述符只是故事的一半。 我们仍然需要调用maven程序集,我们不想在每个构建中都这样做。
这是配置文件的理想时间–只有指定了特定配置文件时,我们才会构建工件。
pom.xml用于战争模块
对于war模块,pom.xml文件的必要附加内容很少。 我们需要调用程序集描述符,但不需要显式添加依赖项。
<profiles>
<profile>
<id>vulnerability-assessment</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/va-war.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
pom.xml用于顶级模块
顶级模块的pom.xml文件的必要添加更为复杂,尤其是在分发程序集是在子模块而不是根模块中创建时。 在这种情况下,我们需要显式添加对pom文件和lite war文件的依赖。 如果不指定前者,则将丢失大多数依赖项;如果不指定后者,则将丢失.war文件。
<profiles>
<profile>
<id>vulnerability-assessment</id>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/va-artifact.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- specify parent pom -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>parent</artifactId> <!-- FIXME -->
<version>${project.version}</version>
<type>pom</type>
</dependency>
<!-- specify each war file and corresponding pom file -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>webapp-1</artifactId> <!-- FIXME -->
<version>${project.version}</version>
<type>war</type>
<classifier>va-war</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>webapp-1</artifactId> <!-- FIXME -->
<version>${project.version}</version>
<type>pom</type>
</dependency>
<!-- second... -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>webapp-2</artifactId> <!-- FIXME -->
<version>${project.version}</version>
<type>war</type>
<classifier>va-war</classifier>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>webapp-2</artifactId> <!-- FIXME -->
<version>${project.version}</version>
<type>pom</type>
</dependency>
<!-- and so on... -->
</dependencies>
</profile>
</profiles>
一个小陷阱!
有一个小陷阱! 在这种特定方法中。 各个Web模块可能依赖于公共库的不同版本。 没有人希望这样做,但是一旦项目达到一定规模,您就无法承受使所有模块保持同步所需的时间和精力。
当我们在公共位置进行依赖关系解析时,此信息将丢失。
我不认为这是一个问题,原因有两个。 首先,我们可以以更精细的粒度执行漏洞评估–本质上是在.war级别而不是.ear文件下进行分析。 这保证了库将匹配,但是如果我们有大量的Web模块,则将极大地增加我们的工作量。
其次,我们的主要重点是代码中的漏洞,而不是第三方库的特定版本中的漏洞。 这些库为评估工具提供了重要的提示,但是我们只希望对代码进行完整的分析。 如果有必要,我们总是可以对我们依赖的库进行单独的评估。
Jenkins Veracode插件
最后,我想指出的是,有一个用于Veracode分析的Jenkins插件: Veracode Scanner Plugin 。 它可用于定期计划扫描,因此当您最终记得在发布前几天运行扫描时,不会发现数百个缺陷。
maven