Capturing User Data: Thick-Client Components

Besides HTML forms, the other main method for capturing, validating, and submitting user data is to use a thick-client component. The technologies you are most likely to encounter here are Java applets, ActiveX controls, and Shockwave Flash objects.

Thick-client components can capture data in various different ways, both via input forms and in some cases by interacting with the client operating system’s file system or registry. They can perform arbitrarily complex validation and manipulation of captured data prior to submission to the server. Further, because their internal workings are less transparently visible than HTML forms and JavaScript, developers are more likely to assume that the validation they perform cannot be circumvented. For this reason, thick-client components are often a fruitful means of discovering vulnerabilities within web applications.

Java Applets

Java applets are a popular choice of technology for implementing thick-client components because they are cross-platform and they run in a sandboxed environment which mitigates against various kinds of security problems that can afflict more heavyweight thick-client technologies. As a result of running in a sandbox, Java applets cannot normally access operating system resources such as the file system. Hence, their main use as a client-side control is to capture user input or other in-browser information. Consider the following extract of HTML source, which loads a Java applet containing a game:

<script>
function play()
{
alert(“you scored “ + TheApplet.getScore());
document.location = “submitScore.jsp?score=” +
TheApplet.getObsScore() + “&name=” +
document.playForm.yourName.value;
}
</script>
<form name=playForm>
<p>Enter name: <input type=”text” name=”yourName” value=”“></p>
<input type=”button” value=”Play” onclick=JavaScript:play()>
</form>
<applet code=”https://wahh-game.com/JavaGame.class”
id=”TheApplet”></applet>

In this code, the applet tag instructs the browser to load a Java applet from the specified URL and instantiate it with the name The Applet . When the user clicks the Play button, a JavaScript routine executes that invokes the get Score method of the applet. This is when the actual game play takes place, after which the score is displayed in an alert dialog. The script then invokes the getObsScore method of the applet, and submits the returned value as a parameter to the submitScore.jsp URL, together with the name entered by the user.

For example, playing the game results in a dialog like the one shown in Figure *1, followed by a request for a URL with this form:
https://wahh-game.com/submitScore.jsp?score=c1cc3139323c3e4544464d51515352585a61606a6b&name=daf

which generates an entry in the high-scores table with a value of 38.

Screenshot from 2020-04-23 22:08:13

Figure -1: A dialog produced when the applet-based game is played

It appears, therefore, that the long string that is returned by the getObsScore method, and submitted in the score parameter, contains an obfuscated representation of your score. If you want to cheat the game and submit an arbitrary high score, you will need to figure out a way of correctly obfuscating your chosen score, so that it is decoded in the normal way by the server.

One approach you may consider is to harvest a large number of scores together with their obfuscated equivalents, and attempt to reverse engineer the obfuscation algorithm. However, suppose that you play the game several times, always scoring 38 and observe the following values being submitted:

bb58303981393b424d4a5059575c616a676d72757b818683
5f48303981393b41474951585861606a656f6f7377817f828b
fd20303981393b4149495651555c66686a6c73797680848489
370c303981393b42494a505359606361696e76787b828584
b5bc303981393b454549545a5a5e6365656971717d818388
1744303981393b43464d515a585f5f646b6f7477767f7e86
f3d4303981393b494a4b5653556162616e6d6f7577827e
de08303981393b474a4d5357595b5d69676a7178757b
da40303981393b43464b54545b6060676e6d70787e7b7e85
1aec303981393b434d4b5054556266646c6b6e717a7f80

Each time you submit a score of 38, a portion of the obfuscated string remains constant, but the majority of it changes in unpredictable ways. You find that if you modify any of the obfuscated score, it is rejected by the server. Attempting to reverse engineer the algorithm based on observed values could be a very difficult task.

Decompiling Java Bytecode

A much more promising approach is to decompile the applet to obtain its source code. Languages like Java are not compiled into native machine instructions, but to an intermediate language called bytecode, which is interpreted at runtime by a virtual machine. Normally, Java bytecode can be decompiled to recover its original source code without too many problems.

To decompile a client-side applet, you first need to save a copy of it to disk. You can do this simply by using your browser to request the URL specified in the code attribute of the applet tag shown previously. There are various tools available that can decompile Java bytecode. The following example shows partial output from one such tool, Jad:

E:\>jad.exe JavaGame.class
Parsing JavaGame.class… Generating JavaGame.jad
E:\>type JavaGame.jad
// Decompiled by Jad v1.5.8f. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name:
JavaGame.java
import java.applet.Applet;
import java.awt.Graphics;
public class JavaGame extends Applet
{
public int getScore()
{
play();
return score;
}
public String getObsScore()
{
return obfuscate(Integer.toString(score) + “|” +
Double.toString(Math.random()));
}
public static String obfuscate(String input)
{

return hexEncode(checksum(input) + scramble(input));
}
private static String scramble(String input)
{
StringBuffer output = new StringBuffer();
for(int i = 0; i < input.length(); i++)
output.append((char)((input.charAt(i) – 3) + i * 4));
return output.toString();
}
private static String checksum(String input)
{
char checksum = ‘\0’;
for(int i = 0; i < input.length(); i++)
{
checksum ^= input.charAt(i);
checksum <<= ‘\002’;
}
return new String(new char[] {
(char)(checksum / 256), (char)(checksum % 256)
});
}

With access to this source code, you can immediately see how your score is converted into a long obfuscated string that has the characteristics observed. The applet first appends some random data to your score (separated by the pipe character). It takes a checksum of the resulting string, and also scrambles it. It then prepends the checksum to the scrambled string and finally hexencodes the result for safe transmission within a URL parameter.

The addition of some random data accounts for the length and unpredictability of the obfuscated string, and the addition of a checksum explains why changing any part of the obfuscated string causes the server-side decoder to reject it.

Having decompiled the applet back to its source code, there are various ways in which you could leverage this to bypass the client-side controls and submit an arbitrary high score to the server:

■ You can modify the decompiled source to change the behavior of the applet, recompile it to bytecode, and modify the source code of the HTML page to load the modified applet in place of the original.

Forexample, you could change the getObsScore method to:

return obfuscate(“99999|0.123456789”);
To recompile your modified code, you should use the Java compiler javac provided with Sun’s Java SDK.

■You can add a main method to the decompiled source to provide the functionality to obfuscate arbitrary inputs:

public stati c void main(String[] args)
{
System.out.println(obfuscate(args[0]));
}

You can then run the recompiled byte code from the command line to obfuscate any score you like:

E:\>java JavaGame “99999|0.123456789 “6ca4363a3e42468d45474e53585d62676c7176

■ You can review the public methods exposed by the applet to determine whether any of them can be leveraged to achieve your objectives without actually modifying the applet. In the present case, you can see that the obfuscate method is marked as public, meaning that you can call it directly from JavaScript with arbitrary input. Hence, you can submit your chosen score simply by modifying the source code of the HTML page as follows:

function p lay()
{
alert(“you scored “ + TheApplet.getScore());
document.location = “submitScore.jsp?score=” +
TheApplet.obfuscate(“99999|0.123456789”) + “&name=” +
document.playForm.yourName.value;
}

Coping with Bytecode Obfuscation

Because of the ease with which Java bytecode can be decompiled to recover its source, various techniques have been developed to obfuscate the bytecode itself. Applying these techniques results in bytecode that is harder to decompile or that decompiles to misleading or invalid source code that may be very difficult to understand and impossible to recompile without substantial effort.

For example:
package   myapp.interface;
import     myapp.class.public;
import     myapp.interface.else.class;
import     myapp.throw.throw;
import     if.if.if.if.else;
import     if.if.if.if.if;
import     java.awt.event.KeyEvent;

public class double extends public implements strict
{
public double(j j1)
{
_mthif();
_fldif = j1;

}
private void _mthif(ActionEvent actionevent)
{
_mthif(((KeyEvent) (null)));
switch(_fldif._mthnew()._fldif)
{
case 0:
_fldfloat.setEnabled(false);
_fldboolean.setEnabled(false);
_fldinstanceof.setEnabled(false);
_fldint.setEnabled(false);
break;
case 3:
_fldfloat.setEnabled(true);
_fldboolean.setEnabled(true);
_fldinstanceof.setEnabled(false);
_fldint.setEnabled(false);
break;

The obfuscation techniques commonly employed are as follows:

■ Meaningful class, method, and member variable names are replaced with meaningless expressions like a, b, c. This forces the reader of decompiled code to identify the purpose of each item by studying how it is used, and can make it very difficult to keep track of different items while tracing them through the source code.

■ Going further, some obfuscators replace item names with Java keywords such as new and int . Although this technically renders the byte code illegal, most JVMs will tolerate the illegal code and it will execute normally. However, even if a decompiler can handle the illegal bytecode, the resulting source code will be even less readable than that described in the previous point. More importantly, the source will not be recompilable without extensive reworking to rename illegally named items in a consistent manner.

■ Many obfuscators strip unnecessary debug and meta-information from the bytecode, including source file names and line numbers (which makes stack traces less informative), local variable names (which frustrates debugging), and inner class information (which stops reflection from working properly).

■ Redundant code may be added that creates and manipulates various kinds of data in significant-looking ways but that is autonomous from the real data actually being used by the application’s functionality.

■ The path of execution through code can be modified in convoluted ways, through the use of jump instructions, so that the logical sequence of execution is hard to discern when reading through the decompiled source.

■ Illegal programming constructs may be introduced, such as unreachable statements, and code paths with missing return statements. Most JVMs will tolerate these phenomena in bytecode, but the decompiled source cannot be recompiled without correcting the illegal code.


..NEXT is…ActiveX Controls…..,.,,.,.>>>>>>