Jalangi2 Shadow Value
Recently I am working on JavaScript Taint Analysis by using Jalangi2. However, I found that mechanism of shadow value of Jalangi2, which is used to store taint state here, works differently from the one mentioned in this paper. The reason might be that the version is different: the paper covers Jalangi1 while I am using Jalangi2.
In the paper, it is suggested to use a AnnotatedValue
to replace some variables, and as long as the variable is used for some operation, actual(value)
is used to convert it to actual value for operation. Then when our analysis callback function analysis.binary
is called, value
is passed as the arguments instead of actual(value)
, shown as below, according to the seudo-codes in the paper.
//definition of AnotatedValue
function AnotatedValue(val, shadow)
{
this.val = val;
this.shadow = shadow;
}
function actual(val)
{
return val instanceof AnotatedValue ? val.val : val;
}
//when executing instrumented code of binary operator
var result = actual(left) op actual(right) //call `actual` to operands
if (analysis && analysis.binary)
analysis.binary(op, left, right, result)
However, in Jalangi2, things works differently, here is the part of the source code of Jalangi2.
function B(iid, op, left, right, flags) {
var bFlags = decodeBitPattern(flags, 3); // [isComputed, isOpAssign, isSwitchCaseComparison]
var result, aret, skip = false;
if (sandbox.analysis && sandbox.analysis.binaryPre) {
aret = sandbox.analysis.binaryPre(iid, op, left, right, bFlags[1], bFlags[2], bFlags[0]);
if (aret) {
op = aret.op;
left = aret.left;
right = aret.right;
skip = aret.skip;
}//a `binaryPre` is added
}
if (!skip) {
switch (op) {
case "+": // not actual(left) + actual(right)
result = left + right;
break;
//... other operators
default:
throw new Error(op + " at " + iid + " not found");
break;
}
}
if (sandbox.analysis && sandbox.analysis.binary) {
//left and right being passed to `analysis.binary`
//are same as ones used as operands
//which is different from the approach mentioned in paper
aret = sandbox.analysis.binary(iid, op, left, right, result, bFlags[1], bFlags[2], bFlags[0]);
if (aret) {
result = aret.result;
}
}
return (lastComputedValue = result);
}
Therefore, it seems that AnnotatedValue
class is not supported in Jalangi2, but instead, shadow value is associated with a object reference. SMemory
is a mechanism that support shadow value feature in Jalangi2. However, the drawback of this approach is that we cannot have a shadow value assoicated with primitive value, including string
. Therefore, since the approach of Jalangi1 mentioned in the paper is better for me to use, I will define AnotatedValue
by myself, and then define analysis.binaryPre
to let skip === true
, and perform calculation inside analysis.binary
instead. Also, I will do this for all operations, not only binary operator.
Here is the codes that describe what I am thinking about.
this.binaryPre = function(iid, op, left, right)
{
return {op:op,left:left,right:right,skip:true}//skip
}
this.binary = function(iid, op, left, right, result)
{
var result;
var aleft = actual(left);
var aright = actual(right);
switch (op)
{//switch copied from source code of Jalangi2
case "+":
result = aleft + aright;
break;
//... many other operands
default:
throw new Error(op + " at " + iid + " not found");
break;
}
//use left and right to perform analysis
return {result : result}
//eval("left"+op+"right")} eval might be insecure
}
In this way we can use the shadow value in the same way as Jalangi1.