No it doesn't. It's still the same byte. However, the 0 to 255 range is
for unsigned bytes, a type that does exist in some other language like
C. In Java bytes are signed, so the same value is represented
differently. However, both 200 (unsigned) and -56 (signed) represent the
same binary value: 1100_1000.
On 30/12/2021 13:13, Fabrice Tiercelin wrote:
Hi,
Le mercredi 29 décembre 2021, 11:35:12 UTC+1, Rob Spoor
<open...@icemanx.nl> a écrit :
An example is
reading input streams byte-by-byte: the result is an int between 0 and > 255
(inclusive), or -1 for EOF. If the result is not -1, the result is > almost always
cast to a byte
Does your example mean that a whole virus can bypass an antivirus this way?
Fabrice
On 29/12/2021 07:43, Fabrice Tiercelin wrote:
Greetings,
Any Java application may be concerned by a hacker attack using a type narrowing
leak. If a program does the following things in this order:
- Assert that a numerical id is allowed - Do a type narrowing among other
things, even followed by a type widening - Do an action with the numerical id
...the hacker can do forbidden actions. Let's say that a given user doesn't
have rights to change an amount for the id 63:
public void changeAmount(long userId, double newAmount) throws
IllegalArgumentException { isUserIdAllowedOrThrowException(userId); // userId
= 4294967359
int theUserId = (int) userId; // theUserId = 63 userId = theUserId; //
userId = 63
doChangeAmount(userId, newAmount); // userId = 63
}
It will fail passing 63 but it will success passing 4294967359 because
4_294_967_359 is narrowed into 63. Let's call 4_294_967_359 a rebound of 63.
4294967359 can be retrieved in few seconds by a basic program like this:
public class MyClass {
public static void main(String args[]) {
long targettedNumber = 63;
for (long rebound = Integer.MAX_VALUE + 1; true; rebound++) { int typeNarrowing = (int) rebound;
long typeWidening = typeNarrowing;
if (typeWidening == targettedNumber) {
System.out.println("Rebound for " + targettedNumber + " found:
" + rebound);
return;
}
}
}
}
And it can be optimized. It works for any type narrowing. It not only works for
numerical id but also for flags. If a numerical value should contain or not
several flags, you can search a rebound among billions of rebounds until you
find one with the perfect features. All the Java versions are concerned. The
security layer can even be coded in another programming language.
To fix it, I suggest to add a test just before the type narrowing in the
bytecode. The test verifies if the type narrowing will alter the numerical
value. If true, it throws an unchecked exception or an error. Otherwise, it
continues as currently. Note that it changes the behavior but the current
behavior is dangerous, useless and is a failing case. You can add a compiler
option to restore the original behavior but the new behavior should be the
default.
Best regards,Fabrice TIERCELIN