When I wrote The Confused Deputy in 1988, I was unaware of the Unix system call setuid(). Hal Finney pointed out that setuid() solved the problem that I had described. This is true but setuid() fails to solve slightly more general problems. Hal’s note leads to other interesting observations as well. Kragen Sitaker has written about capability security and included some interesting variations on the confused deputy.
A particular problem is that a process whose saved and real UIDs differ, cannot invoke other files that perform setuid. Such a process has two authority sources and will in general need to convey each (or parts of each) to its sub sub contractor. Execing another program in set_uid mode fails to convey the invoker’s authority that stems from the invoker’s saved uid process value. Here is some code to summarize how the Unix kernel treats the various user IDs.
This page has an excellent brief definition of the problem.
This excellent paper covers this and related issues clearly. Fred Spiessens has written this explanation of the confused deputy.
Endowing a file with the “set user ID” property as in “chmod 4755 file” is analogous to arranging for machine code to run in privileged mode. The program in the endowed file is thereby allowed to take actions beyond those that its invoker could, just as a system call invokes code running in privileged mode so as to obey privileged machine instructions that it may contain. The setuid() system call even helps such programs avoid the analog to a frequent security bug in operating systems.
But the two state mode is suitable only when there is a program, such as the privileged Unix kernel, to mediate between multiple interests. The Unix kernel does this but its rules for interactions do not support patterns such as described above. Capability systems may be built on the same two state foundation and support such interactions.
A closely related problem is that the imported code will use the cookies of the user of the browser to make its accesses. Cookies supply a sort of authority that the guest program should not wield without the user’s explicit permission.
int m1(int * a, int * b){ static aa=0; aa += *a; return *a + *b + aa;} int m2(int * a){ int q = 20; static int aa=0; aa += *a; return m1(a, &q);} int m3(){int r = 22; return m2(&r);}Routine m1 requires authority from both m2 and m3 to fetch its input. In the capability analog the authority would come along with the “name”. In Java parameters really do convey authority just like capabilities.
See another hardware deputy problem.
The deputy must always know whose authority it acts with!
There are many good confused deputy descriptions on the web now, 2008. There are subtle modifications in the retelling but they seldom miss the important point. Some of the modifications are actually better in some aspect. The story is evolving and improving.