The buffer Buffer classes defined in the java.nio package (e.g. , such as IntBuffer, CharBuffer, and ByteBuffer) , define a variety of methods that wrap an array () methodsor a portion of the array) of the corresponding primitive data type into a buffer and return the buffer as a Buffer object. Although these wrap() methods create a new Buffer object, the new Buffer is backed by the given input array for which it is created. According to the JavaDoc Java API for these methods :[API 2014],
The new buffer will be backed by the given character array; that is, modifications to the buffer will cause the array to be modified and vice versa.
Consequently, exposing the buffer Exposing these buffers to untrusted code exposes the backing array of the original buffer to malicious modification. Likewise, the duplicate(), array(), slice() methods , and subsequence() methods create additional buffers that are backed by the original buffer's backing array; exposing such additional buffers to untrusted code affords the same opportunity for malicious modification of the contents of the original buffer's backing store.
This rule is an instance of OBJ06-J. Defensively copy mutable inputs and mutable internal components.
Noncompliant Code Example (wrap())
This noncompliant code example declares a char array, wraps it with within a Buffer CharBuffer, and exposes that Buffer CharBuffer to untrusted code via the getBufferCopy() method. The return value of this method is of type CharBuffer.:
| Code Block | ||
|---|---|---|
| ||
final class Wrap { private char[] dataArray; public Wrap () { dataArray = new char[10]; // Initialize } public CharBuffer getBufferCopy() { return CharBuffer.wrap(dataArray); } } |
Compliant Solution (asReadOnlyBuffer())
This compliant solution returns a read-only view of the char array , in the form of a read-only CharBuffer. The standard library implementation of CharBuffer guarantees that attempts to modify the elements of a read-only CharBuffer will result in a java.nio.ReadOnlyBufferException.
| Code Block | ||
|---|---|---|
| ||
final class Wrap { private char[] dataArray; public Wrap () { dataArray = new char[10]; // Initialize } public CharBuffer getBufferCopy() { CharBuffer cbreturn = CharBuffer.allocatewrap(10); return cbdataArray).asReadOnlyBuffer(); } } |
Compliant Solution (Copy)
This compliant solution allocates a new CharBuffer and explicitly copies the contents of the char array into it , before returning the copy. Consequently, malicious callers can modify the copy of the array , but cannot modify the original.
| Code Block | ||
|---|---|---|
| ||
final class Wrap { private char[] dataArray; public Wrap () { dataArray = new char[10]; // Initialize } public CharBuffer getBufferCopy() { CharBuffer cb = CharBuffer.allocate(10dataArray.length); cb.put(dataArray); return cb; } } |
Noncompliant Code Example (duplicate())
This noncompliant code example uses invokes the duplicate() method to create and return a copy of the CharBuffer. As stated in the contract for the duplicate() method, the returned buffer is backed by the same array as is the original buffer. Consequently, if a caller can were to modify the elements of the backing array; , these modifications would also affect the original buffer.
| Code Block | ||
|---|---|---|
| ||
final class Dup { CharBuffer cb; public Dup() { cb = CharBuffer.allocate(10); // Initialize } public CharBuffer getBufferCopy() { return cb.duplicate(); } } |
When the CharBuffer created by the duplicate() method is based on a CharBuffer originally obtained by using the wrap() method, modifying the CharBuffer returned by the duplicate() method also modifies the contents of the backing char array; this property can be useful to a malicious attacker.
Noncompliant Code Example
This noncompliant code example attempts to repair the above vulnerability by allocating a new CharBuffer, and duplicating the CharBuffer into the newly allocated CharBuffer. This approach fails to protect the contents of the duplicated buffer, because the duplicate() method only duplicates the wrapping buffer fields and produces a buffer with the same backing store as the original buffer.l Consequently, malicious modifications to the duplicated buffer also affect the backing store of the original buffer.
| Code Block | ||
|---|---|---|
| ||
final class Dup {
CharBuffer cb;
public Dup() {
cb = CharBuffer.allocate(10);
// Initialize
}
public CharBuffer getBufferCopy() {
CharBuffer copy = CharBuffer.allocate(10);
copy = cb.duplicate();
return copy;
}
}
|
Compliant Solution
Compliant Solution (asReadOnlyBuffer())
This compliant solution exposes a read-only view of the CharBuffer to untrusted code.:
| Code Block | ||
|---|---|---|
| ||
final class Dup { CharBuffer cb; public Dup() { cb = CharBuffer.allocate(10); // Initialize } public CharBuffer getBufferCopy() { return cb.asReadOnlyBuffer(); } } |
Risk Assessment
Returning Exposing buffers created using the wrap() or duplicate, duplicate(), array(), slice(), or subsequence() methods methods may allow an untrusted caller to alter the contents of the original data.
Rule | Severity | Likelihood | Detectable |
|---|
Repairable | Priority | Level |
|---|
FIO05-J | Medium |
Likely |
No |
No |
P6 |
L2 |
Automated Detection
Sound automated detection of this vulnerability is not feasible. Heuristic approaches may be useful.
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this guideline on the CERT website.
Bibliography
| Wiki Markup |
|---|
\[[API 2006|AA. Bibliography#API 06]\] class {{CharBuffer}}
\[[Hitchens 2002|AA. Bibliography#Hitchens 02]\] 2.3 Duplicating Buffers |
| Tool | Version | Checker | Description | ||||||
|---|---|---|---|---|---|---|---|---|---|
| Parasoft Jtest |
| CERT.FIO05.BUFEXP | Do not expose data wrapped by a buffer to untrusted code | ||||||
| SpotBugs |
| MS_EXPOSE_BUF | Implemented (since 4.3.0) |
Bibliography
[API 2014] | |
Section 2.3 "Duplicating Buffers" |
...
FIO00-J. Defensively copy mutable inputs and mutable internal components 09. Input Output (FIO) FIO02-J. Keep track of bytes read and account for character encoding while reading data