@@ -1,13 +0,0 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
@@ -1,6 +0,0 @@
|
||||
# Log4j Patch
|
||||
|
||||
Copy from [Glavo/log4j-patch](https://github.com/Glavo/log4j-patch/).
|
||||
|
||||
`org.apache.logging.log4j.core.lookup.JndiLookup` is licensed under the WTFPL 2.0 license,
|
||||
and `org.apache.logging.log4j.core.lookup.Interpolator` is licensed under the Apache 2.0 license.
|
||||
@@ -1,53 +0,0 @@
|
||||
import java.io.RandomAccessFile
|
||||
|
||||
version = "1.0"
|
||||
|
||||
sourceSets.create("agent") {
|
||||
java {
|
||||
srcDir("src/main/agent")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly("org.apache.logging.log4j:log4j-core:2.0-beta9")
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
sourceCompatibility = "1.8"
|
||||
targetCompatibility = "1.8"
|
||||
|
||||
doLast {
|
||||
val tree = fileTree(destinationDirectory)
|
||||
tree.include("**/*.class")
|
||||
tree.exclude("module-info.class")
|
||||
tree.forEach {
|
||||
RandomAccessFile(it, "rw").use { rf ->
|
||||
rf.seek(7) // major version
|
||||
rf.write(50) // java 6
|
||||
rf.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val agentJar = tasks.create<Jar>("agentJar") {
|
||||
dependsOn(tasks.compileJava)
|
||||
|
||||
archiveBaseName.set("log4j-patch-agent")
|
||||
|
||||
manifest {
|
||||
attributes("Premain-Class" to "org.glavo.log4j.patch.agent.Log4jAgent")
|
||||
}
|
||||
|
||||
from(sourceSets["agent"].output)
|
||||
from(sourceSets["main"].output) {
|
||||
includeEmptyDirs = false
|
||||
eachFile { path = "org/glavo/log4j/patch/agent/$name.bin" }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tasks.jar {
|
||||
enabled = false
|
||||
dependsOn(agentJar)
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.glavo.log4j.patch.agent;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.lang.instrument.ClassFileTransformer;
|
||||
import java.lang.instrument.IllegalClassFormatException;
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class Log4jAgent {
|
||||
static final String JNDI_LOOKUP_CLASS_NAME = "org/apache/logging/log4j/core/lookup/JndiLookup";
|
||||
static final String INTERPOLATOR_CLASS_NAME = "org/apache/logging/log4j/core/lookup/Interpolator";
|
||||
|
||||
static final byte[] INTERPOLATOR_CLASS_SHA = {53, 103, 16, 123, 51, 29, 65, -70, -32, 71, -11, 7, 114, -15, 72, 127, 40, -38, 35, 18};
|
||||
|
||||
static boolean isBeta = false;
|
||||
|
||||
private static byte[] loadResource(String name) {
|
||||
try {
|
||||
try (InputStream input = Log4jAgent.class.getResourceAsStream(name)) {
|
||||
if (input == null) {
|
||||
throw new AssertionError(name + " not found");
|
||||
}
|
||||
int available = input.available();
|
||||
if (available <= 0) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
byte[] res = new byte[available];
|
||||
if (input.read(res) != available) {
|
||||
throw new AssertionError();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new InternalError(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public static void premain(String agentArgs, Instrumentation inst) throws Exception {
|
||||
if ("true".equals(agentArgs)) {
|
||||
isBeta = true;
|
||||
}
|
||||
inst.addTransformer(new Transformer());
|
||||
}
|
||||
|
||||
private static final class Transformer implements ClassFileTransformer {
|
||||
|
||||
@Override
|
||||
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
|
||||
if (!isBeta && JNDI_LOOKUP_CLASS_NAME.equals(className)) {
|
||||
return loadResource("JndiLookup.class.bin");
|
||||
}
|
||||
if (isBeta && INTERPOLATOR_CLASS_NAME.equals(className)) {
|
||||
try {
|
||||
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
|
||||
sha1.update(classfileBuffer);
|
||||
if (Arrays.equals(INTERPOLATOR_CLASS_SHA, sha1.digest())) {
|
||||
return loadResource("Interpolator.class.bin");
|
||||
}
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new InternalError(e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache license, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the license for the specific language governing permissions and
|
||||
* limitations under the license.
|
||||
*/
|
||||
package org.apache.logging.log4j.core.lookup;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.core.LogEvent;
|
||||
import org.apache.logging.log4j.core.config.plugins.PluginManager;
|
||||
import org.apache.logging.log4j.core.config.plugins.PluginType;
|
||||
import org.apache.logging.log4j.status.StatusLogger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The Interpolator is a StrLookup that acts as a proxy for all the other StrLookups.
|
||||
*/
|
||||
public class Interpolator implements StrLookup {
|
||||
|
||||
private static final Logger LOGGER = StatusLogger.getLogger();
|
||||
|
||||
/** Constant for the prefix separator. */
|
||||
private static final char PREFIX_SEPARATOR = ':';
|
||||
|
||||
private final Map<String, StrLookup> lookups = new HashMap<String, StrLookup>();
|
||||
|
||||
private final StrLookup defaultLookup;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public Interpolator(final StrLookup defaultLookup) {
|
||||
this.defaultLookup = defaultLookup == null ? new MapLookup(new HashMap<String, String>()) : defaultLookup;
|
||||
final PluginManager manager = new PluginManager("Lookup");
|
||||
manager.collectPlugins();
|
||||
final Map<String, PluginType<?>> plugins = manager.getPlugins();
|
||||
|
||||
for (final Map.Entry<String, PluginType<?>> entry : plugins.entrySet()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
final Class<? extends StrLookup> clazz = (Class<? extends StrLookup>) entry.getValue().getPluginClass();
|
||||
try {
|
||||
lookups.put(entry.getKey(), clazz.newInstance());
|
||||
} catch (final Exception ex) {
|
||||
LOGGER.error("Unable to create Lookup for " + entry.getKey(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the default Interpolator using only Lookups that work without an event.
|
||||
*/
|
||||
public Interpolator() {
|
||||
this.defaultLookup = new MapLookup(new HashMap<String, String>());
|
||||
lookups.put("sys", new SystemPropertiesLookup());
|
||||
lookups.put("env", new EnvironmentLookup());
|
||||
// lookups.put("jndi", new JndiLookup());
|
||||
LOGGER.warn("Log4j patch works, JNDI lookup is disabled. This message is not a warning, it represents the successful elimination of some security risks. You should be able to play safely.");
|
||||
|
||||
try {
|
||||
if (Class.forName("javax.servlet.ServletContext") != null) {
|
||||
lookups.put("web", new WebLookup());
|
||||
}
|
||||
} catch (ClassNotFoundException ex) {
|
||||
LOGGER.debug("ServletContext not present - WebLookup not added");
|
||||
} catch (Exception ex) {
|
||||
LOGGER.error("Unable to locate ServletContext", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the specified variable. This implementation will try to extract
|
||||
* a variable prefix from the given variable name (the first colon (':') is
|
||||
* used as prefix separator). It then passes the name of the variable with
|
||||
* the prefix stripped to the lookup object registered for this prefix. If
|
||||
* no prefix can be found or if the associated lookup object cannot resolve
|
||||
* this variable, the default lookup object will be used.
|
||||
*
|
||||
* @param var the name of the variable whose value is to be looked up
|
||||
* @return the value of this variable or <b>null</b> if it cannot be
|
||||
* resolved
|
||||
*/
|
||||
@Override
|
||||
public String lookup(final String var) {
|
||||
return lookup(null, var);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the specified variable. This implementation will try to extract
|
||||
* a variable prefix from the given variable name (the first colon (':') is
|
||||
* used as prefix separator). It then passes the name of the variable with
|
||||
* the prefix stripped to the lookup object registered for this prefix. If
|
||||
* no prefix can be found or if the associated lookup object cannot resolve
|
||||
* this variable, the default lookup object will be used.
|
||||
*
|
||||
* @param event The current LogEvent or null.
|
||||
* @param var the name of the variable whose value is to be looked up
|
||||
* @return the value of this variable or <b>null</b> if it cannot be
|
||||
* resolved
|
||||
*/
|
||||
@Override
|
||||
public String lookup(final LogEvent event, String var) {
|
||||
if (var == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final int prefixPos = var.indexOf(PREFIX_SEPARATOR);
|
||||
if (prefixPos >= 0) {
|
||||
final String prefix = var.substring(0, prefixPos);
|
||||
final String name = var.substring(prefixPos + 1);
|
||||
final StrLookup lookup = lookups.get(prefix);
|
||||
String value = null;
|
||||
if (lookup != null) {
|
||||
value = event == null ? lookup.lookup(name) : lookup.lookup(event, name);
|
||||
}
|
||||
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
var = var.substring(prefixPos + 1);
|
||||
}
|
||||
if (defaultLookup != null) {
|
||||
return event == null ? defaultLookup.lookup(var) : defaultLookup.lookup(event, var);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
for (final String name : lookups.keySet()) {
|
||||
if (sb.length() == 0) {
|
||||
sb.append("{");
|
||||
} else {
|
||||
sb.append(", ");
|
||||
}
|
||||
|
||||
sb.append(name);
|
||||
}
|
||||
if (sb.length() > 0) {
|
||||
sb.append("}");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2021 Glavo <zjx001202@gmail.com>
|
||||
* This work is free. You can redistribute it and/or modify it under the
|
||||
* terms of the Do What The Fuck You Want To Public License, Version 2,
|
||||
* as published by Sam Hocevar. See http://www.wtfpl.net/ for more details.
|
||||
*/
|
||||
package org.apache.logging.log4j.core.lookup;
|
||||
|
||||
public class JndiLookup {
|
||||
public JndiLookup() {
|
||||
throw new NoClassDefFoundError("JNDI lookup is disabled. This is not an error. We are blocking some vulnerabilities through it. You should be able to play safely.");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user