Skip to main content
5 of 23
deleted 17 characters in body
Stéphane Chazelas
  • 586.3k
  • 96
  • 1.1k
  • 1.7k

The problem is in cases where the content of $x has not been sanitized and contains data that could potentially be under the control of an attacker in cases that shell code may end up being used in a privilege escalation context (for instance a script invoked by a setuid application, a sudoers script or used to process off-the-network data (CGI, DHCP hook...) directly or indirectly).

If:

x='PATH=2' 

Then:

x=$((1-$x)) 

has the side effect of setting PATH to 2 (a relative path that could very well be under control of the attacker). You can replace PATH with LD_LIBRARY_PATH or IFS... The same happens with x=$((1-x)) in bash, zsh or ksh (not dash nor yash which only accept numerical constants in variables there).

In bash, zsh and ksh (not dash or yash), if x is:

x='a[0$(id>&2)]' 

Then the expansion of $((1-$x)) causes that id command to be executed.

Note that:

x=$((1-$x)) 

won't work properly for negative values of $x in some shells that implement the (optional as per POSIX) -- (decrement) operator (as with x=-1, that means asking the shell to evaluate the 1--1 arithmetic expression). "$((1-x))" doesn't have the problem as x is expanded as part of (not before) the arithmetic evaluation.

In summary, one shouldn't use uninitialised or non-sanitized external data in arithmetic expressions in shells (note that arithmetic evaluation can be done by $((...)) but depending on the shell in the let, [/test, declare/typeset, return, break, continue, printf, print builtin and ((..)) and [[...]] constructs to name a few).

More reading at:

Stéphane Chazelas
  • 586.3k
  • 96
  • 1.1k
  • 1.7k