Version 4 of Injection Attack

Updated 2010-06-14 21:53:23 by AMG

AMG: An injection attack is the substitution of executable code into an expression. A system is vulnerable to injection attacks when it reparses substitution results. Tcl normally does not reparse substitution results, but several Tcl commands internally perform parsing and substitution on their arguments, after Tcl has already parsed and substituted them.

Injection attacks often allow users to execute arbitrary code in a privileged context.

Here's an example value of $exploit that can be used in the following code snippets. Don't use it; typing this in is playing with fire! Executing it is suicidal, so let's be safe by not even typing it.

set exploit {[exec rm -rf /]}

Here's a safer version for testing:

set exploit {[error PWNED!]}

after

after 0 puts $exploit   ;# vulnerable
after 0 {puts $exploit} ;# safe

apply

apply "{exploit} {puts $exploit}" $exploit ;# vulnerable
apply {{exploit} {puts $exploit}} $exploit ;# safe

catch

catch "puts $exploit" ;# vulnerable
catch {puts $exploit} ;# safe

dict filter

dict filter {a 1} script {k v} "puts $exploit; lindex 1" ;# vulnerable
dict filter {a 1} script {k v} {puts $exploit; lindex 1} ;# safe

dict for

dict for {k v} {a 1} "puts $exploit" ;# vulnerable
dict for {k v} {a 1} {puts $exploit} ;# safe

eval

eval puts $exploit   ;# vulnerable
eval "puts $exploit" ;# vulnerable
eval {puts $exploit} ;# safe

expr

expr 2 + 2 == $exploit    ;# vulnerable
expr "2 + 2 == $exploit"  ;# vulnerable
expr {2 + 2 == $exploit}  ;# safe

Always brace your expr-essions!!

subst

subst "this is vulnerable to the $exploit"
subst {this is immune to the $exploit}

The -novariables and -nobackslashes options can't be used to completely deny access to variables and backslash substitutions if -nocommands is not given. (Passing all three options means that [subst] will simply return its argument, same as single-argument [lindex].) This is because command substitution (script substitution) is allowed to internally use variables and backslashes.

switch

Here's a different kind of attack, where a user-supplied value gets interpreted as an option, resulting in an error. Depending on how the program is written, the error may in turn create other problems, such as denial of service .

set exploit -crash
switch    $exploit  A {puts "got A"} default {puts "didn't get A"}  ;# vulnerable
switch    $exploit {A {puts "got A"} default {puts "didn't get A"}} ;# safe
switch -- $exploit  A {puts "got A"} default {puts "didn't get A"}  ;# safe
switch -- $exploit {A {puts "got A"} default {puts "didn't get A"}} ;# safe

Always using -- is the recommended solution. RS calls it "the option to end all options". :^) However, it's not required when using switch's single body form, wherein all the cases are grouped into a single word [L1 ]. This is because this form of switch always treats the second-to-last argument as the match word. Hmm, I think I might stop using -- since it's not really necessary...

more to come...

Others

Here's a very famous injection attack:

http://imgs.xkcd.com/comics/exploits_of_a_mom.png [L2 ]

Sanitizing database inputs is more of a band-aid than anything; it doesn't address the root of the problem, which is reparsing substitution results. Instead use prepared statements. This page has many non-SQL examples of what are essentially prepared statements, for example "expr {2 + 2 == $exploit}". Here, the "statement" (math expression) is a single word which gets bytecode-compiled (prepared), and expr always gets the same argument into which it performs variable substitution.