Java input classes such as Scanner
and BufferedInputStream
facilitate fast, non-blocking nonblocking I/O by buffering an underlying input stream. Programs can create multiple wrappers on an InputStream
. Programs that use multiple wrappers around a single input stream, however, can behave unpredictably depending on whether the wrappers allow look-ahead. An attacker can exploit this difference in behavior by, for example, redirecting System.in
(from a file) or by using the System.setIn()
method to redirect System.in
. In general, any input stream that supports non-blocking nonblocking buffered I/O is susceptible to this form of misuse.
...
Code Block | ||
---|---|---|
| ||
public final class InputLibrary {
private static BufferedInputStream in =
new BufferedInputStream(System.in);
public static char getChar() throws EOFException, IOException {
int input = in.read();
if (input == -1) {
throw new EOFException();
}
in.skip(1); // This statement is to advance to the next line
// The noncompliant code example deceptively
// appeared to work without it (in some cases)
return (char)input;
}
public static void main(String[] args) {
try {
System.out.print("Enter first initial: ");
char first = getChar();
System.out.println("Your first initial is " + first);
System.out.print("Enter last initial: ");
char last = getChar();
System.out.println("Your last initial is " + last);
} catch (EOFException e) {
System.err.println("ERROR");
// Forward to handler
} catch (IOException e) {
System.err.println("ERROR");
// Forward to handler
}
}
}
|
...
This program was compiled under Java 1.6.0. When run from the command line, the program successfully takes two characters as input and prints them out. Unlike the NCCEnoncompliant code example, this program also produces correct output when run with a file redirected to standard input.
Compliant Solution (Accessible Class Variable)
If another class needs a program intends to use System.in
as well as the InputLibrary
class, the class program must use the same buffered wrapper used by InputLibrary
, as does this class rather than creating and using its own additional buffered wrapper. Consequently, the InputLibrary
class must provide make available a reference to its the buffered wrapper for such classesto support this functionality.
Code Block | ||
---|---|---|
| ||
public final class InputLibrary {
private static BufferedInputStream in =
new BufferedInputStream(System.in);
static BufferedInputStream getBufferedWrapper() {
return in;
}
// ...other methods
}
// Some code that requires user input from System.in
class AppCode {
private static BufferedInputStream in;
AppCode() {
in = InputLibrary.getBufferedWrapper();
}
// ...other methods
}
|
...
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="5e1c4859dd204c8f-f49d3662-410049ed-be81bb71-9ec4cba74298657808d56d95"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] | [method Method | http://java.sun.com/javase/6/docs/api/java/io/InputStream.html#read()] | ]]></ac:plain-text-body></ac:structured-macro> |
<ac:structured-macro ac:name="unmigrated-wiki-markup" ac:schema-version="1" ac:macro-id="5fe310aed54e6ede-78e4ed5a-418145fa-8725a26b-88fc7706cc24978afe0b277c"><ac:plain-text-body><![CDATA[ | [[API 2006 | AA. Bibliography#API 06]] | [class Class | http://java.sun.com/javase/6/docs/api/java/io/BufferedInputStream.html] | ]]></ac:plain-text-body></ac:structured-macro> |
...