Skip to content

Commit

Permalink
hardening SocketServer ongoing work
Browse files Browse the repository at this point in the history
  • Loading branch information
ceki committed Jan 12, 2022
1 parent f4e3def commit 45d712c
Show file tree
Hide file tree
Showing 4 changed files with 283 additions and 0 deletions.
37 changes: 37 additions & 0 deletions examples/socketServer.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# 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.


# An example log4j configuration file that outputs to System.out. The
# output information consists of relative time, log level, thread
# name, logger name, nested diagnostic context and the message in that
# order.

# For the general syntax of property based configuration files see the
# documenation of org.apache.log4j.PropertyConfigurator.

log4j.rootLogger=DEBUG, A1

# A1 is set to be a ConsoleAppender which outputs to System.out.
log4j.appender.A1=org.apache.log4j.ConsoleAppender

# A1 uses PatternLayout.
log4j.appender.A1.layout=org.apache.log4j.PatternLayout

# The conversion pattern uses format specifiers. You might want to
# change the pattern an watch the output format change.
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n


Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* 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.log4j.net;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Level;
import org.apache.log4j.Priority;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.apache.log4j.spi.ThrowableInformation;

// === Copied from the logback project with permission ==
public class HardenedLoggingEventInputStream extends HardenedObjectInputStream {

static final String ARRAY_PREFIX = "[L";

static public List<String> getWhilelist() {

List<String> whitelist = new ArrayList<String>();
whitelist.add(LoggingEvent.class.getName());
whitelist.add(Level.class.getName());
whitelist.add(Priority.class.getName());
whitelist.add(ThrowableInformation.class.getName());
whitelist.add(LocationInfo.class.getName());

return whitelist;
}

public HardenedLoggingEventInputStream(InputStream is) throws IOException {
super(is, getWhilelist());
}

public HardenedLoggingEventInputStream(InputStream is, List<String> additionalAuthorizedClasses) throws IOException {
this(is);
super.addToWhitelist(additionalAuthorizedClasses);
}
}
92 changes: 92 additions & 0 deletions src/main/java/org/apache/log4j/net/HardenedObjectInputStream.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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.log4j.net;

import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamClass;
import java.util.ArrayList;
import java.util.List;

/**
* HardenedObjectInputStream restricts the set of classes that can be
* deserialized to a set of explicitly whitelisted classes. This prevents
* certain type of attacks from being successful.
*
* <p>
* It is assumed that classes in the "java.lang" and "java.util" packages are
* always authorized.
* </p>
*
* @author Ceki G&uuml;lc&uuml;
* @since 1.2.18
*
* === Copied from the logback project with permission ==
*/
public class HardenedObjectInputStream extends ObjectInputStream {

final List<String> whitelistedClassNames;

This comment has been minimized.

Copy link
@vlsi

vlsi Jan 12, 2022

Contributor

@ceki , it is sad you skipped commits from apache/logging-log4j1#18

For instance, apache/logging-log4j1@746716f would configure indent_style = space

The code you add happens no mix tabs with spaces :-/

This comment has been minimized.

Copy link
@ceki

ceki Jan 12, 2022

Author Member

These can be integrated as we go along. Such improvements are most welcome.

final static String[] JAVA_PACKAGES = new String[] { "java.lang", "java.util" };

public HardenedObjectInputStream(InputStream in, String[] whilelist) throws IOException {
super(in);

this.whitelistedClassNames = new ArrayList<String>();
if (whilelist != null) {
for (int i = 0; i < whilelist.length; i++) {
this.whitelistedClassNames.add(whilelist[i]);
}
}
}

public HardenedObjectInputStream(InputStream in, List<String> whitelist) throws IOException {
super(in);

this.whitelistedClassNames = new ArrayList<String>();
this.whitelistedClassNames.addAll(whitelist);
}

@Override
protected Class<?> resolveClass(ObjectStreamClass anObjectStreamClass) throws IOException, ClassNotFoundException {

String incomingClassName = anObjectStreamClass.getName();

if (!isWhitelisted(incomingClassName)) {
throw new InvalidClassException("Unauthorized deserialization attempt", anObjectStreamClass.getName());
}

return super.resolveClass(anObjectStreamClass);
}

private boolean isWhitelisted(String incomingClassName) {
for (int i = 0; i < JAVA_PACKAGES.length; i++) {
if (incomingClassName.startsWith(JAVA_PACKAGES[i]))
return true;
}
for (String whiteListed : whitelistedClassNames) {
if (incomingClassName.equals(whiteListed))
return true;
}
return false;
}

protected void addToWhitelist(List<String> additionalAuthorizedClasses) {
whitelistedClassNames.addAll(additionalAuthorizedClasses);
}
}
99 changes: 99 additions & 0 deletions src/test/java/org/apache/log4j/net/SillySocketClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*
* 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.log4j.net;

import java.io.File;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.log4j.PropertyConfigurator;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.spi.ErrorCode;

/**
* A silly client used send objects to SocketServer
*
* @author ceki
*
*/
public class SillySocketClient {

static InetAddress LOCAL_HOST_ADDRESS;
static String LOCALHOST_STR;

static int PORT;

ObjectOutputStream oos;

public static void main(String[] args) throws UnknownHostException {
Properties props = System.getProperties();
for (Object key : props.keySet()) {
System.out.println(key + ":" + props.getProperty((String) key));
}

if (args.length == 1)
init(args[0]);
else {
usage("Wrong number of arguments.");
return;
}
LOCAL_HOST_ADDRESS = getAddressByName(LOCALHOST_STR);

SillySocketClient ssc = new SillySocketClient();
ssc.connect(LOCAL_HOST_ADDRESS, PORT);

}

static void init(String portStr) {
try {
PORT = Integer.parseInt(portStr);
} catch (java.lang.NumberFormatException e) {
e.printStackTrace();
usage("Could not interpret port number [" + portStr + "].");
}
}

static void usage(String msg) {
System.err.println(msg);
System.err.println("Usage: java " + SillySocketClient.class.getName() + " port");
System.exit(1);
}

static InetAddress getAddressByName(String host) throws java.net.UnknownHostException {
return InetAddress.getByName(host);
}

void connect(InetAddress address, int port) {
if (address == null)
return;
try {
oos = new ObjectOutputStream(new Socket(address, port).getOutputStream());
} catch (IOException e) {
if (e instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
String msg = "Could not connect to remote log4j server at [" + address.getHostName() + "].";
LogLog.error(msg);
}
}

}

0 comments on commit 45d712c

Please sign in to comment.