我在 /etc/ 的子目录中有一个文件,我想复制该文件,我可以以普通用户身份运行该文件,但是当我运行时
cp /etc/subdir/desired_file .
我被拒绝许可。但是我可以在没有超级用户权限的情况下执行该文件。有没有办法让我将该文件复制到另一个目录中?
编辑:不更改文件权限
答案1
cp src dst
读取文件的内容src
并将其写入dst
其创建的新文件。
所以它需要对该文件的读取权限。
至少在 Linux 上以及某些文件系统(例如 )上btrfs
,它可以用 a 替换read()
s + write()
s 来ioctl (dest_fd, FICLONE, src_fd)
执行所谓的转发链接副本其中数据最初并未在磁盘上复制,但即使如此,它仍然需要打开源文件以读取到src_fd
.
如果复制文件足以绕过读取限制,那么权限系统将被严重破坏。
现在,您可以使用不同的名称创建指向该文件的新链接,而不是复制文件:
后:
ln from/src to/dst
为此,您只需要对from
目录进行搜索访问和对目录进行搜索+写入访问to
,并且dst
与src
.您最终会得到src
和dst
,但请注意,它们是链接到两个不同目录(或具有不同名称的同一目录)的同一文件。
现在,如果src
是可执行文件,并且是一种本机可执行格式(例如,与脚本相反,尽管您无法在没有读取权限的情况下运行脚本,因为解释器确实需要能够读取它),这意味着允许系统映射内容将可执行文件放入其中之一的内存中你的过程,这相当于代表您阅读它。
系统会注意不允许绕过读取限制。例如,至少在 Linux 上,当接收到 SIGQUIT 等信号(在Ctrl+上发送\ )时,进程不会生成核心转储。它不会让您阅读/proc/<pid>/maps
或/proc/<pid>/mem
执行该过程:
$ cp /usr/bin/sleep .
$ chmod 111 sleep
$ ./sleep inf &
[1] 86474
$ cat /proc/$!/maps
cat: /proc/86474/maps: Permission denied
$ cat /proc/$!/mem
cat: /proc/86474/mem: Permission denied
它也不会让您附加调试器,即使使用kernel.yama.ptrace_scope = 0
.
但进程本身显然可以读取自己的内存,所以如果你能说服它把它转储到某个地方,你就可以恢复一些文件中的数据。
如果文件是动态链接的 ELF 可执行文件,并且不是 setuid/setgid...(未启用安全执行模式),至少在 GNU/Linux 系统上,您可以说服动态链接器将任意代码注入可执行文件中机制$LD_PRELOAD
,或者告诉它使用它所使用的共享库的修改版本,这些库已被劫持以通过更改$LD_LIBRARY_PATH
.
例如:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
static void init(void) __attribute__((constructor));
static void init(void)
{
FILE *maps, *dst;
char exe[4096], path[4096];
char *start, *end;
off_t offset;
int n;
n = readlink("/proc/self/exe", exe, sizeof(exe));
exe[n] = '\0';
dst = fopen(getenv("DST"), "w");
maps = fopen("/proc/self/maps", "r");
while((n = fscanf(maps, "%p-%p%*s%lx%*s%*s%*[ ]%[^\n ]\n", &start, &end, &offset, path)) != EOF) {
if (n == 4 && !strcmp(path, exe)) {
printf("Dumping [%p - %p] from %s at offset %#lx\n", start, end, path, offset);
fseek(dst, offset, SEEK_SET);
fwrite(start, end - start, 1, dst);
}
}
exit(0);
}
(错误处理留给读者作为练习)
编译为:
gcc -fPIC -shared -o hack.so that-file.c
运行src
为:
DST=./dst LD_PRELOAD=./hack.so ./src
truncate -r src dst
会将文件中映射到内存的部分转储到./dst
文件中。
如果您有以下内容的可读副本src
并使用:
cmp -l src-copy dst | perl -pe 's/\d+/sprintf"%#x",$&-1/e'
并将输出与objdump -h src-copy
偏移量上的输出进行匹配,您会发现它并不相同,因为某些部分丢失或已被动态链接器修改。在我的测试中,它们是:
20 .init_array 00000008 0000000000009bb0 0000000000009bb0 00008bb0 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .fini_array 00000008 0000000000009bb8 0000000000009bb8 00008bb8 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .data.rel.ro 000000b8 0000000000009bc0 0000000000009bc0 00008bc0 2**5
CONTENTS, ALLOC, LOAD, DATA
23 .dynamic 000001f0 0000000000009c78 0000000000009c78 00008c78 2**3
CONTENTS, ALLOC, LOAD, DATA
24 .got 00000190 0000000000009e68 0000000000009e68 00008e68 2**3
CONTENTS, ALLOC, LOAD, DATA
26 .bss 000001b8 000000000000a080 000000000000a080 00009080 2**5
ALLOC
但.text
和.rodata
部分至少是完整的,这表明尝试在不可读的动态链接 ELF 可执行文件中隐藏秘密是徒劳的。
答案2
这里可能有两种情况:
要么你缺乏读取权限所需文件。您可能拥有该文件的执行权限,但要查看或复制该文件,需要读取权限。
或者您缺乏目标目录的写权限。
请通过https://www.tutorialspoint.com/unix/unix-file-permission.htm。它将帮助您了解 unix 权限。
所有者可以使用以下方式授予权限chmod命令。