Have default capsule for the node specify node-specific mods file

This commit is contained in:
rick.parker 2023-04-04 15:08:51 +01:00
parent 68e107be68
commit 622319031c
4 changed files with 94 additions and 22 deletions

View File

@ -9,6 +9,7 @@ apply plugin: 'com.jfrog.artifactory'
description 'Corda standalone node'
evaluationDependsOn(':node')
evaluationDependsOn(':tools:aegis4j')
configurations {
runtimeArtifacts.extendsFrom runtimeClasspath
@ -37,23 +38,27 @@ capsule {
}
def nodeProject = project(':node')
def aegisProject = project(':tools:aegis4j')
task buildCordaJAR(type: FatCapsule, dependsOn: [
nodeProject.tasks.named('jar'),
aegisProject.tasks.named('shadowJar'),
project(':core-deterministic').tasks.named('assemble'),
project(':serialization-deterministic').tasks.named('assemble')
]) {
]) {
applicationClass 'net.corda.node.Corda'
archiveBaseName = 'corda'
archiveVersion = corda_release_version
archiveClassifier = jdkClassifier
archiveName = archiveFileName.get()
applicationSource = files(
nodeProject.configurations.runtimeClasspath,
nodeProject.tasks.jar,
nodeProject.buildDir.toString() + '/resources/main/corda-reference.conf',
"$rootDir/config/dev/log4j2.xml",
'NOTICE' // Copy CDDL notice
nodeProject.configurations.runtimeClasspath,
nodeProject.tasks.jar,
aegisProject.tasks.named('shadowJar'),
nodeProject.buildDir.toString() + '/resources/main/corda-reference.conf',
nodeProject.buildDir.toString() + '/resources/main/mods.properties',
"$rootDir/config/dev/log4j2.xml",
'NOTICE' // Copy CDDL notice
)
from configurations.capsuleRuntime.files.collect { zipTree(it) }
with jar
@ -99,6 +104,7 @@ task buildCordaJAR(type: FatCapsule, dependsOn: [
def quasarExcludeExpression = "x(antlr**;bftsmart**;co.paralleluniverse**;com.codahale**;com.esotericsoftware**;com.fasterxml**;com.google**;com.ibm**;com.intellij**;com.jcabi**;com.nhaarman**;com.opengamma**;com.typesafe**;com.zaxxer**;de.javakaffee**;groovy**;groovyjarjarantlr**;groovyjarjarasm**;io.atomix**;io.github**;io.netty**;jdk**;kotlin**;net.corda.djvm**;djvm**;net.bytebuddy**;net.i2p**;org.apache**;org.bouncycastle**;org.codehaus**;org.crsh**;org.dom4j**;org.fusesource**;org.h2**;org.hibernate**;org.jboss**;org.jcp**;org.joda**;org.objectweb**;org.objenesis**;org.slf4j**;org.w3c**;org.xml**;org.yaml**;reflectasm**;rx**;org.jolokia**;com.lmax**;picocli**;liquibase**;com.github.benmanes**;org.json**;org.postgresql**;nonapi.io.github.classgraph**)"
def quasarClassLoaderExclusion = "l(net.corda.djvm.**;net.corda.core.serialization.internal.**)"
javaAgents = quasar_classifier ? ["quasar-core-${quasar_version}-${quasar_classifier}.jar=${quasarExcludeExpression}${quasarClassLoaderExclusion}"] : ["quasar-core-${quasar_version}.jar=${quasarExcludeExpression}${quasarClassLoaderExclusion}"]
javaAgents += "aegis4j-1.2.jar=path=mods.properties"
systemProperties['visualvm.display.name'] = 'Corda'
if (JavaVersion.current() == JavaVersion.VERSION_1_8) {
minJavaVersion = '1.8.0'

View File

@ -0,0 +1,56 @@
# format: <feature>.<class-name>.<method-name>=<replacement-code>
# JNDI
# ----
# Patches the 3 protected methods which InitialContext uses internally to get all Context instances,
# so that these methods always throw a NoInitialContextException (NICE). As a result, no JNDI lookups
# are possible.
JNDI.javax.naming.InitialContext.getURLOrDefaultInitCtx=throw new javax.naming.NoInitialContextException("JNDI context creation blocked by aegis4j");
JNDI.javax.naming.InitialContext.getDefaultInitCtx=throw new javax.naming.NoInitialContextException("JNDI context creation blocked by aegis4j");
# RMI
# ---
# Outside of traditional JEE application servers, few people use the RMI libraries anymore.
RMI.java.rmi.registry.LocateRegistry.getRegistry=throw new java.rmi.StubNotFoundException("RMI registry creation blocked by aegis4j");
RMI.java.rmi.registry.LocateRegistry.createRegistry=throw new java.rmi.StubNotFoundException("RMI registry creation blocked by aegis4j");
RMI.java.rmi.server.RemoteObject.RemoteObject=throw new java.lang.RuntimeException("RMI remote object creation blocked by aegis4j");
# Process Execution
# -----------------
# Many remote code execution exploits culminate in local process execution, but it's relatively rare to
# need to use these methods for legitimate purposes.
#PROCESS.java.lang.Runtime.exec=throw new java.io.IOException("Process execution blocked by aegis4j");
#PROCESS.java.lang.ProcessBuilder.start=throw new java.io.IOException("Process execution blocked by aegis4j");
#PROCESS.java.lang.ProcessBuilder.startPipeline=throw new java.io.IOException("Process execution blocked by aegis4j");
# JDK HTTP Server
# ---------------
# The JDK HTTP server is intended for quick testing, especially for platform beginners. It is rarely (if
# ever) used in production, so we can eliminate this little bit of attack surface.
HTTPSERVER.com.sun.net.httpserver.HttpServer.HttpServer=throw new java.lang.RuntimeException("HTTP server creation blocked by aegis4j");
HTTPSERVER.com.sun.net.httpserver.HttpsServer.HttpsServer=throw new java.lang.RuntimeException("HTTPS server creation blocked by aegis4j");
HTTPSERVER.com.sun.net.httpserver.spi.HttpServerProvider.HttpServerProvider=throw new java.lang.RuntimeException("HTTP server provider creation blocked by aegis4j");
HTTPSERVER.com.sun.net.httpserver.spi.HttpServerProvider.provider=throw new java.lang.RuntimeException("HTTP server provider lookup blocked by aegis4j");
# Java Serialization
# ------------------
# Probably a bit more commonly used than most of the other features on this list, but a huge security
# liability for applications that don't use it. Best to live without it, if at all possible.
#SERIALIZATION.java.io.ObjectInputStream.ObjectInputStream=throw new java.lang.RuntimeException("Java deserialization blocked by aegis4j");
#SERIALIZATION.java.io.ObjectOutputStream.ObjectOutputStream=throw new java.lang.RuntimeException("Java serialization blocked by aegis4j");
# Unsafe
# ------
# Quite commonly used in the olden days, but many applications should be able to run without it these days.
#UNSAFE.sun.misc.Unsafe.*=throw new java.lang.RuntimeException("Unsafe blocked by aegis4j");
# Scripting
# ---------
# Nashorn was removed from the platform in JDK 15. There are other JSR 223 script engines out there,
# but they're probably not common enough to leave this capability enabled by default.
#SCRIPTING.javax.script.ScriptEngineManager.ScriptEngineManager=throw new java.lang.RuntimeException("Scripting blocked by aegis4j");
#SCRIPTING.javax.script.AbstractScriptEngine.AbstractScriptEngine=throw new java.lang.RuntimeException("Scripting blocked by aegis4j");
#SCRIPTING.javax.script.SimpleScriptContext.SimpleScriptContext=throw new java.lang.RuntimeException("Scripting blocked by aegis4j");
#SCRIPTING.javax.script.CompiledScript.CompiledScript=throw new java.lang.RuntimeException("Scripting blocked by aegis4j");
# JShell
# ------
# Introduced in JDK 9, the Java Shell is intended for rapid prototyping and testing. It is not usually used in production.
#JSHELL.jdk.jshell.JShell.JShell=throw new java.lang.RuntimeException("JShell blocked by aegis4j");
#JSHELL.jdk.jshell.JShell.create=throw new java.lang.RuntimeException("JShell blocked by aegis4j");
#JSHELL.jdk.jshell.JShell.builder=throw new java.lang.RuntimeException("JShell blocked by aegis4j");
#JSHELL.jdk.jshell.tool.JavaShellToolBuilder.builder=throw new java.lang.RuntimeException("JShell blocked by aegis4j");
#JSHELL.jdk.jshell.Snippet.Snippet=throw new java.lang.RuntimeException("JShell blocked by aegis4j");
#JSHELL.jdk.jshell.TaskFactory.parse=throw new java.lang.RuntimeException("JShell blocked by aegis4j");

View File

@ -9,7 +9,7 @@ plugins {
group = 'net.gredler'
archivesBaseName = 'aegis4j'
version = '1.1'
version = '1.2'
repositories {
mavenCentral()

View File

@ -2,6 +2,7 @@
package net.gredler.aegis4j;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.instrument.Instrumentation;
@ -35,24 +36,33 @@ public final class AegisAgent {
*/
public static void premain(String args, Instrumentation instr) {
instrumentation = instr;
if(args.trim().equalsIgnoreCase("dynamic")) return;
Path path = null;
boolean started = false;
for(String arg: args.split(";")) {
if (started) throw new IllegalArgumentException("Aegis4j ERROR: parameter ordering means patching already started");
String normalisedaArg = arg.trim().toLowerCase();
if(normalisedaArg.isEmpty() || normalisedaArg.startsWith("block=") || normalisedaArg.startsWith("unblock=")) {
try {
Patcher.start(instr, toBlockList(normalisedaArg, path), getModificationsInputStream(path));
started = true;
} catch (IOException e) {
throw new IllegalArgumentException("Aegis4j ERROR: Unable to process mods file", e);
if (args != null) {
if (args.trim().equalsIgnoreCase("dynamic")) return;
for (String arg : args.split(";")) {
if (started) throw new IllegalArgumentException("Aegis4j ERROR: parameter ordering means patching already started");
String normalisedaArg = arg.trim().toLowerCase();
if (normalisedaArg.isEmpty() || normalisedaArg.startsWith("block=") || normalisedaArg.startsWith("unblock=")) {
try {
Patcher.start(instr, toBlockList(normalisedaArg, path), getModificationsInputStream(path));
started = true;
} catch (IOException e) {
throw new IllegalArgumentException("Aegis4j ERROR: Unable to process mods file", e);
}
} else if (normalisedaArg.startsWith("path=")) {
String pathString = arg.trim().substring(5);
if (pathString.startsWith(File.pathSeparator)) {
path = Paths.get(pathString);
} else {
Path agentJar = Paths.get(AegisAgent.class.getProtectionDomain().getCodeSource().getLocation().getPath());
path = agentJar.resolveSibling(pathString);
}
System.out.println("Aegis4j patching from " + path + " mods file");
} else {
throw new IllegalArgumentException("Aegis4j ERROR: unrecognised parameters " + arg);
}
} else if (normalisedaArg.startsWith("path=")) {
path = Paths.get(arg.trim().substring(5));
System.out.println("Aegis4j patching from " + path + " mods file");
} else {
throw new IllegalArgumentException("Aegis4j ERROR: unrecognised parameters " + arg);
}
}
if (!started) {