-
Notifications
You must be signed in to change notification settings - Fork 979
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Question about taint analysis in Slither #156
Comments
Hi @cty12 , thank you for your interest to Slither! What version are you using? We refactored the data dependency and the taint with slither 0.5.0 (it uses now the SSA representation of slithIR). We did not document the taint API, but we are going to do it prior to 0.6.0. There are two functions for what you are asking for:
If the context is the contract, the dependency/taint is from a fixpoint across all the functions. It means that if In your example, you can use: from slither import Slither
from slither.analyses.data_dependency.data_dependency import is_tainted, is_dependent
slither = Slither('taint.sol')
sampleContract = slither.get_contract_from_name('SampleContract')
svar = sampleContract.get_state_variable_from_name('svar')
taint = is_tainted(svar, sampleContract, slither)
print('{} is tainted: {}'.format(svar, taint))
func_a = sampleContract.get_function_from_signature('func_A(uint256)')
user_input = func_a.parameters[0]
dependent = is_dependent(svar, user_input, func_a, slither)
print('{} is depedent from {}: {}'.format(svar, user_input, taint)) Some notes:
Let me know if that answers your questions |
We have more examples of the dependency here: data_dependency.sol, data_dependency.py. |
Thank you for the kind reply! In the code snippet that you posted, running Please point it out if I missed anything. |
In fact we can use
In this case, I do not think data dependency has been propagated correctly through function calls. By the way I have checked |
Ah yes, you're right, I was printing The dependency is not yet propagated through the arguments of functions, while it should. That's a good catch, thanks! I will see if I can integrate this feature for the 0.6.0 release. |
OK thanks! By the way, the |
Yes indeed! It's what I meant when mentioning that the taint does not consider the visibility of the functions, so the parameters of private/internal will be considered as input-controlled. It creates an over-approximation where many parameters are considered tainted why they are not. Propagating the dependency across parameters should allow refining this limitation! |
Thanks for recognizing this issue. By the way, is there a plan for a simple alias analysis? It can be pretty handy when writing a slightly more complex detector. |
Sure! By alias analysis, do you mean:
function f(uint x){
uint y = x;
} Feel free to open issues in github if you have specific needs from Slither; we will do our best to add these features |
Yes you are right. I think pointer analysis is the broader term. By the way, in addition to simple assignments, as is shown in your example, it is also possible to store a pointer into a vector and retrieve it later (creating an alias, for example). |
For info, Slither does a light alias analysis on storage references. contract MyContract{
struct myStruct{
uint val;
}
myStruct val_a;
myStruct val_b;
myStruct val_c;
function myFunc(bool condition) internal returns(myStruct storage){
myStruct storage st1 = val_a;
myStruct storage st2 = val_b;
if(condition){
st2 = val_c;
}
return st2;
}
} from slither import Slither
from slither.core.variables.local_variable import LocalVariable
slither = Slither('ref.sol')
myContract = slither.get_contract_from_name('MyContract')
myFunc = myContract.get_function_from_signature('myFunc(bool)')
for node in myFunc.nodes:
if node.expression:
print(f'Solidity expression: {node}')
for ssa_var in set(node.ssa_local_variables_read + node.ssa_local_variables_written):
if isinstance(ssa_var, LocalVariable):
if ssa_var.is_storage:
print(f'\tLocal variable {ssa_var.non_ssa_version.name} points to {[v.non_ssa_version.name for v in ssa_var.refers_to]}') Will result in
Some notes:
We are working to improve the IR, the data dependency and the alias analysis. Feel free to contact us on slack (#ethereum) if you need support to integrate more advanced analyses |
I am working on an improvement of the SSA and the taint in the |
Hi, I merged the track of the taint and data dependency through arguments to master. Please let me know if you have any other questions related to Slither's internals, or if something is not working as expected. We know that there is room for improvement for the data dependency computation. |
I've checked out the latest commit on the master branch. Is the non-SSA dependency still broken? Consider the following example:
Printing the dependencies information related to function
In other words, Slither does not consider |
I don't have the same result on your example (tested on 3dbe807): contract SampleContract {
uint svar = 0;
function func_A (uint [] user_input) public {
svar = user_input.length + 1;
}
} from slither import Slither
from slither.analyses.data_dependency.data_dependency import is_tainted, pprint_dependency
slither = Slither('test.sol')
sampleContract = slither.get_contract_from_name('SampleContract')
svar = sampleContract.get_state_variable_from_name('svar')
print('{} is tainted? {}'.format(svar, is_tainted(svar, sampleContract)))
pprint_dependency(sampleContract) Gives
Could you share your python script? Concerning the TMP and REF variables, those are slithIR variables, they exist only in SSA form (they have a lifetime of the node) so they are in SSA even if the other variables are not. We can also add a printer that shows the dependency directly (in a textual form, or a graph-based form). |
I built Slither from source and is on the latest commit on Would you please replace
with something like
and try again? This is because the latter one outputs the dependency information of that specific function (that is, in a function-wise context). I understand the contract-wise one does not have that issue. |
Oh you're right, the dependency is not computed through a fix-point on the function's context (but only on the contract's context). That's another good catch! I am opening a separate issue for it. Thank you @cty12 for finding these issues, that's really valuable. |
Consider the following example:
Now we would like to check if the state variable
svar
can be controlled by user input. It is not directly written byfunc_A
, howeversvar
can be modified infunc_B
, where its value to depends on an argument passed byfunc_A
, which depends on user input.In the current Slither taint analysis implementation, if we set the taint source to be the local variable
user_input
infunc_A
, the local variablea
infunc_A
is tainted, which is expected. However it cannot figure out that the value ofsvar
is controlled by the taint source, which means that runningget_state_variable_tainted
gets an empty list.Is this an intended behavior?
The text was updated successfully, but these errors were encountered: