【问题标题】:execve("/bin/sh", 0, 0); in a pipeexecve("/bin/sh", 0, 0);在管道中
【发布时间】:2012-01-20 11:55:37
【问题描述】:

我有以下示例程序:

#include <stdio.h>

int
main(int argc, char ** argv){
    char buf[100];

    printf("Please enter your name: ");
    fflush(stdout);
    gets(buf);
    printf("Hello \"%s\"\n", buf);

    execve("/bin/sh", 0, 0);
}

当我在没有任何管道的情况下运行时,它会正常工作并返回sh promt:

bash$ ./a.out
Please enter your name: warning: this program uses gets() which is unsafe.
testName
Hello "testName"
$ exit
bash$

但这在管道中不起作用,我想我知道为什么会这样,但我无法找到解决方案。示例运行如下。

bash$ echo -e "testName\npwd" | ./a.out
Please enter your name: warning: this program uses gets() which is unsafe.
Hello "testName"
bash$

我认为这与gets 清空stdin 的方式有关,/bin/sh 收到 EOF 并立即退出而没有错误消息。

但是我该如何解决这个问题(如果可能,不修改程序,如果没有,不删除gets)以便即使我通过管道提供输入也能得到提示?

附:我在 FreeBSD (4.8) 机器 D.S. 上运行它

【问题讨论】:

  • 从不使用gets。它总是会打开一个缓冲区溢出安全漏洞。
  • 我知道 ;) ...这是我大学安全实验室计算机上缓冲区溢出尝试的一部分。纯学术。 =D

标签: c shell pipe freebsd execve


【解决方案1】:

不是 100% 确定这一点(使用的精确 shell 和操作系统可能会抛出这些答案;我相信 FreeBSD 默认使用 GNU bash 作为/bin/sh?),但是

  • sh 可能检测到其输入不是 tty。

  • 您的sh 版本可能会进入非交互模式,如果调用为sh,则期望login 将在argv[0] 前添加-。设置 execve ("/bin/sh", { "-sh", NULL}, NULL) 可能会让它相信它是作为登录 shell 运行的。

【讨论】:

    【解决方案2】:

    您可以运行您的程序,而无需像这样进行任何修改:

    (echo -e 'testName\n'; cat ) | ./a.out
    

    这样可以确保程序的标准输入不会在echo 输出之后结束。相反,cat 继续为您的程序提供输入。后续输入的来源是您的终端,因为这是读取 cat 的地方。

    这是一个示例会话:

    bash-3.2$ cc stdin_shell.c 
    bash-3.2$ (echo -e 'testName\n'; cat ) | ./a.out 
    Please enter your name: warning: this program uses gets(), which is unsafe.
    Hello "testName"
    pwd
    /home/user/stackoverflow/stdin_shell_question
    ls -l
    total 32
    -rwxr-xr-x  1 user  group  9024 Dec 14 18:53 a.out
    -rw-r--r--  1 user  group   216 Dec 14 18:52 stdin_shell.c
    ps -p $$
      PID TTY           TIME CMD
    93759 ttys000    0:00.01 (sh)
    exit
    
    bash-3.2$
    

    请注意,由于 shell 的标准输入没有连接到终端,sh 认为它不是交互式执行的,因此不显示提示。不过,您可以正常键入命令。

    【讨论】:

    • 啊..是的,你是对的,(实际上我在看到你的帖子之前就找到了这个解决方案,但谢谢你把它放在这里)。
    【解决方案3】:

    使用execve("/bin/sh", 0, 0); 是对shell 的残忍和不寻常的惩罚。它根本没有给它任何参数或环境——甚至没有它自己的程序名称,甚至没有像 PATH 或 HOME 这样的强制性环境变量。

    【讨论】:

    • 嗯...是的,我完全同意,但这只是用作实验。我永远不会在类似于可用程序的任何东西中使用它。
    猜你喜欢
    • 2013-05-16
    • 2015-09-07
    • 2021-10-16
    • 1970-01-01
    • 2022-11-03
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    • 2021-07-29
    相关资源
    最近更新 更多