The full chain of the attack:
Request sent to the url, containing headers with '() { :;}; codehere'
Per CGI standard: environment variables are set with the attack code.
PHP is executed directly, with the environment containing the attack.
PHP calls system - the same environment is there, meaning the code is executed if /bin/sh points to bash.
N.B. - If /bin/sh is not bash, but the program executed by system() itself executes a call to system() which points to something explicitly calling a bash ( apply this if recursively), the exploit is triggered.
It's not about passing "arguments" on the command line, its about what the environment variables are. It's not always immediately obvious how the env vars are constructed - everyone points to CGI because it's a well known scenario, but there are plenty of other cases where environment variables are set from user data.
tl; dr - in any situation user input is used in environment variables, simply calling /bin/bash is enough.
https://news.ycombinator.com/item?id=8369443
right?
Under the hood, system("echo foo") does a fork, and in the child process does execv(["/bin/sh", "-c", "echo", "foo"], env...)