I think that if you’d add forName(“Blah”), the static initializer would have been executed…?
forName is a method in Class, not ClassLoader.
And as Class is declared final, I cannot access the method as a sub-class (to avoid usage of the dot operator)
Nope, looks like you were safe afterall, I can’t find a way of executing the class initialiser of a class constructed through Reflection without using the dot operator.
The only security hole exposed through ClassLoader is that you can get an InputStream to any file on the classpath.
So in theory we could of grabbed the class files of the application, piped them to the OutputStream you provide us in the method parameter, resulting in the class file contents being piped back to us as the contents of the web page.
I suppose decompiling the resultant files might have allowed us to find an exploit in your app…
I still think there is a loophole to be found with overriding toString() (as that doesn’t require the explicit method-invocation) with a body containing System.exit(0); in bytecode.
If you can grab an instance of the produced class, or can run the static initializer, it’s pretty much overtaken.
You should leave it up!
Consider it the the ‘out of the (sand)box’ coding exercise ;D
If it was my own server… yes, but I’m renting this one, and I just paid 250 euro, and I don’t want to get my account suspended.
Further, a company is dependant (critically) on a MySQL database on it.
And… I don’t have much time to fix it, with my examns this week.
I fixed the security holes… until somebody finds some class that has a static method named read or write, that has some funny sideeffect.
And another one…
http://213.247.55.3:8484/compileandrun/?assignment=encoder
This one could get extremely small.
(48 bytes)
(46 bytes)
(45 bytes)
48,47,46 :’(
I watched you in SSH, and you’re so damn near the answer…
you need to remember the behaviour of modulo with negative values
45!, Got there in the end ;D
Great, you (??) caused a few (harmless) ArithmeticExceptions and NullPointerExceptions on the way to it
I passed the getMessage() to the client now.
I only saw those that threw errors, and if your last is like that, you got a completely different solution than I came up with…
for(int b=48;(b^=in.read()%2)>0;out.write(b));
yup, that’s what I got to in the end.
While I wouldn’t stake my life on it, it looks pretty much like the optimal solution…
p.s.
I don’t think I was the cause of the exceptions - I do all my testing in Eclipse, only use the submission page to check the size.
I see somebody doing extremely clever stuff at the server now, and he keeps getting stuck at 46 bytes… it’s a bit unfair, really
Are you using the same class for defining the assignments?
I have an idea for one
Yup, I posted the code, and nothing changed yet.
Gimme gimme!
To be honest, I exp[ected more people to join in… this competition is being played by roughly 5 people
But well, once the assignments get thougher, and the website has user-accounts, things might become better.
aargh, I give up! I got two similar 46 byte solutions:
for (
int i = 0;
(i ^= in.read()) >= 0;
out.write(48|i)
);
for (
int i = 48;
(i ^= in.read() & 3) < 50;
out.write(i)
);
Martin
I witnessed your suffering.
You got two great solutions!
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ReverseStream extends TinyCodeAssignment {
public byte[] createQuestion() {
return str2arr("stun slap swang god . burg slipup stool ergo trams");
}
public String getDefaultSource() {
StringBuilder sb = new StringBuilder();
sb.append("byte [] buffer = new byte[4];\n");
sb.append("int len = 0;\n");
sb.append("int b;\n");
sb.append("while((b=in.read())>=0) {\n");
sb.append(" buffer[len++] = (byte)b;\n");
sb.append(" if(len==buffer.length) {\n");
sb.append(" byte [] newBuffer = new byte[len*2];\n");
sb.append(" for(int i = 0;i < len;i++) {\n");
sb.append(" newBuffer[i] = buffer[i];\n");
sb.append(" }\n");
sb.append(" buffer = newBuffer;\n");
sb.append(" }\n");
sb.append("}\n\n");
sb.append("for(int i = len-1;i>=0; i--) {\n");
sb.append(" out.write(buffer[i]);\n");
sb.append("}");
return sb.toString();
}
public String getDescription() {
return "Reverse the order of the stream";
}
public String getExample() {
return "ABCD -> DCBA";
}
public String getName() {
return "reverse";
}
public String getTitle() {
return "Reverse";
}
public void processCorrectly(InputStream in, OutputStream out)
throws IOException {
byte [] buffer = new byte[4];
int len = 0;
int b;
while((b=in.read())>=0) {
buffer[len++] = (byte)b;
if(len==buffer.length) {
byte [] newBuffer = new byte[len*2];
for(int i = 0;i < len;i++) {
newBuffer[i] = buffer[i];
}
buffer = newBuffer;
}
}
for(int i = len-1;i>=0; i--) {
out.write(buffer[i]);
}
}
}