Skip to content

Commit 45d712c

Browse files
committed
hardening SocketServer ongoing work
1 parent f4e3def commit 45d712c

File tree

4 files changed

+283
-0
lines changed

4 files changed

+283
-0
lines changed

examples/socketServer.properties

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one or more
2+
# contributor license agreements. See the NOTICE file distributed with
3+
# this work for additional information regarding copyright ownership.
4+
# The ASF licenses this file to You under the Apache License, Version 2.0
5+
# (the "License"); you may not use this file except in compliance with
6+
# the License. You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
17+
# An example log4j configuration file that outputs to System.out. The
18+
# output information consists of relative time, log level, thread
19+
# name, logger name, nested diagnostic context and the message in that
20+
# order.
21+
22+
# For the general syntax of property based configuration files see the
23+
# documenation of org.apache.log4j.PropertyConfigurator.
24+
25+
log4j.rootLogger=DEBUG, A1
26+
27+
# A1 is set to be a ConsoleAppender which outputs to System.out.
28+
log4j.appender.A1=org.apache.log4j.ConsoleAppender
29+
30+
# A1 uses PatternLayout.
31+
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
32+
33+
# The conversion pattern uses format specifiers. You might want to
34+
# change the pattern an watch the output format change.
35+
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
36+
37+
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.log4j.net;
18+
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
import java.util.ArrayList;
22+
import java.util.List;
23+
24+
import org.apache.log4j.Level;
25+
import org.apache.log4j.Priority;
26+
import org.apache.log4j.spi.LocationInfo;
27+
import org.apache.log4j.spi.LoggingEvent;
28+
import org.apache.log4j.spi.ThrowableInformation;
29+
30+
// === Copied from the logback project with permission ==
31+
public class HardenedLoggingEventInputStream extends HardenedObjectInputStream {
32+
33+
static final String ARRAY_PREFIX = "[L";
34+
35+
static public List<String> getWhilelist() {
36+
37+
List<String> whitelist = new ArrayList<String>();
38+
whitelist.add(LoggingEvent.class.getName());
39+
whitelist.add(Level.class.getName());
40+
whitelist.add(Priority.class.getName());
41+
whitelist.add(ThrowableInformation.class.getName());
42+
whitelist.add(LocationInfo.class.getName());
43+
44+
return whitelist;
45+
}
46+
47+
public HardenedLoggingEventInputStream(InputStream is) throws IOException {
48+
super(is, getWhilelist());
49+
}
50+
51+
public HardenedLoggingEventInputStream(InputStream is, List<String> additionalAuthorizedClasses) throws IOException {
52+
this(is);
53+
super.addToWhitelist(additionalAuthorizedClasses);
54+
}
55+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.log4j.net;
18+
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
import java.io.InvalidClassException;
22+
import java.io.ObjectInputStream;
23+
import java.io.ObjectStreamClass;
24+
import java.util.ArrayList;
25+
import java.util.List;
26+
27+
/**
28+
* HardenedObjectInputStream restricts the set of classes that can be
29+
* deserialized to a set of explicitly whitelisted classes. This prevents
30+
* certain type of attacks from being successful.
31+
*
32+
* <p>
33+
* It is assumed that classes in the "java.lang" and "java.util" packages are
34+
* always authorized.
35+
* </p>
36+
*
37+
* @author Ceki G&uuml;lc&uuml;
38+
* @since 1.2.18
39+
*
40+
* === Copied from the logback project with permission ==
41+
*/
42+
public class HardenedObjectInputStream extends ObjectInputStream {
43+
44+
final List<String> whitelistedClassNames;
45+
final static String[] JAVA_PACKAGES = new String[] { "java.lang", "java.util" };
46+
47+
public HardenedObjectInputStream(InputStream in, String[] whilelist) throws IOException {
48+
super(in);
49+
50+
this.whitelistedClassNames = new ArrayList<String>();
51+
if (whilelist != null) {
52+
for (int i = 0; i < whilelist.length; i++) {
53+
this.whitelistedClassNames.add(whilelist[i]);
54+
}
55+
}
56+
}
57+
58+
public HardenedObjectInputStream(InputStream in, List<String> whitelist) throws IOException {
59+
super(in);
60+
61+
this.whitelistedClassNames = new ArrayList<String>();
62+
this.whitelistedClassNames.addAll(whitelist);
63+
}
64+
65+
@Override
66+
protected Class<?> resolveClass(ObjectStreamClass anObjectStreamClass) throws IOException, ClassNotFoundException {
67+
68+
String incomingClassName = anObjectStreamClass.getName();
69+
70+
if (!isWhitelisted(incomingClassName)) {
71+
throw new InvalidClassException("Unauthorized deserialization attempt", anObjectStreamClass.getName());
72+
}
73+
74+
return super.resolveClass(anObjectStreamClass);
75+
}
76+
77+
private boolean isWhitelisted(String incomingClassName) {
78+
for (int i = 0; i < JAVA_PACKAGES.length; i++) {
79+
if (incomingClassName.startsWith(JAVA_PACKAGES[i]))
80+
return true;
81+
}
82+
for (String whiteListed : whitelistedClassNames) {
83+
if (incomingClassName.equals(whiteListed))
84+
return true;
85+
}
86+
return false;
87+
}
88+
89+
protected void addToWhitelist(List<String> additionalAuthorizedClasses) {
90+
whitelistedClassNames.addAll(additionalAuthorizedClasses);
91+
}
92+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.log4j.net;
18+
19+
import java.io.File;
20+
import java.io.IOException;
21+
import java.io.InterruptedIOException;
22+
import java.io.ObjectOutputStream;
23+
import java.net.InetAddress;
24+
import java.net.Socket;
25+
import java.net.UnknownHostException;
26+
import java.util.Properties;
27+
28+
import org.apache.log4j.PropertyConfigurator;
29+
import org.apache.log4j.helpers.LogLog;
30+
import org.apache.log4j.spi.ErrorCode;
31+
32+
/**
33+
* A silly client used send objects to SocketServer
34+
*
35+
* @author ceki
36+
*
37+
*/
38+
public class SillySocketClient {
39+
40+
static InetAddress LOCAL_HOST_ADDRESS;
41+
static String LOCALHOST_STR;
42+
43+
static int PORT;
44+
45+
ObjectOutputStream oos;
46+
47+
public static void main(String[] args) throws UnknownHostException {
48+
Properties props = System.getProperties();
49+
for (Object key : props.keySet()) {
50+
System.out.println(key + ":" + props.getProperty((String) key));
51+
}
52+
53+
if (args.length == 1)
54+
init(args[0]);
55+
else {
56+
usage("Wrong number of arguments.");
57+
return;
58+
}
59+
LOCAL_HOST_ADDRESS = getAddressByName(LOCALHOST_STR);
60+
61+
SillySocketClient ssc = new SillySocketClient();
62+
ssc.connect(LOCAL_HOST_ADDRESS, PORT);
63+
64+
}
65+
66+
static void init(String portStr) {
67+
try {
68+
PORT = Integer.parseInt(portStr);
69+
} catch (java.lang.NumberFormatException e) {
70+
e.printStackTrace();
71+
usage("Could not interpret port number [" + portStr + "].");
72+
}
73+
}
74+
75+
static void usage(String msg) {
76+
System.err.println(msg);
77+
System.err.println("Usage: java " + SillySocketClient.class.getName() + " port");
78+
System.exit(1);
79+
}
80+
81+
static InetAddress getAddressByName(String host) throws java.net.UnknownHostException {
82+
return InetAddress.getByName(host);
83+
}
84+
85+
void connect(InetAddress address, int port) {
86+
if (address == null)
87+
return;
88+
try {
89+
oos = new ObjectOutputStream(new Socket(address, port).getOutputStream());
90+
} catch (IOException e) {
91+
if (e instanceof InterruptedIOException) {
92+
Thread.currentThread().interrupt();
93+
}
94+
String msg = "Could not connect to remote log4j server at [" + address.getHostName() + "].";
95+
LogLog.error(msg);
96+
}
97+
}
98+
99+
}

0 commit comments

Comments
 (0)