直接在c中使用 *argv []中的炭指针安全吗?

发布于 2025-02-07 00:05:24 字数 637 浏览 0 评论 0原文

我有以下代码可以从C:c:getopt()中从用户那里获取字符串:

#include <stdio.h>
#include <getopt.h>
#include "util.h"

int main(int argc, char *argv[]) {
    if (argc == 1) {
        usage(); // from util.h
        return 0;
    }

    char *argument = NULL;
    char ch;
    while ((ch = getopt(argc, argv, ":f:"))) {
        switch (ch) {
        case 'f':
            argument = optarg;
            break;
        }
    }
    // ... use `argument` with other stuff ...
}

这是安全的,还是我应该使用strcpy()复制字符串进入参数?如果我不小心更改参数的内容,攻击者可以更改环境变量之类的内容吗?

I have the following code to get a string from a user with getopt() in C:

#include <stdio.h>
#include <getopt.h>
#include "util.h"

int main(int argc, char *argv[]) {
    if (argc == 1) {
        usage(); // from util.h
        return 0;
    }

    char *argument = NULL;
    char ch;
    while ((ch = getopt(argc, argv, ":f:"))) {
        switch (ch) {
        case 'f':
            argument = optarg;
            break;
        }
    }
    // ... use `argument` with other stuff ...
}

Is this safe to do, or should I use strcpy() to copy the string into argument? If I accidentally change the contents of argument, could an attacker change stuff like environment variables?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

苍景流年 2025-02-14 00:05:24

这是安全的,还是我应该使用strcpy()将字符串复制到参数?

这是安全的,并且getopt()设计为使用这种方式。更一般而言,提供给MAIN的程序参数指定为属于该程序的可写字符串。

但是,请注意,某些getopt()实现,尤其是GNU,可能会重新排序argv的元素。

如果我不小心更改了参数的内容,攻击者可以更改诸如环境变量之类的内容吗?

就像程序中的任何其他对象一样,参数字符串易受界限错误的影响。如果通过编程错误或其他方式,您的程序试图通过任何对象的界限编写,那么行为是不确定的。环境变量的修改是UB可能表现的无限空间中最合理的成员之一。

但是,请注意,在这方面制作论点的副本无济于事。您也必须避免使用任何此类副本的界限,以免触发UB,并具有相同的无界表现空间。

如果要确保无法通过变量参数来修改程序参数,那么将其声明为指向const chard Char的指针而不是指针是惯用的(修改)char。这不会干扰为其分配optarg的值。

Is this safe to do, or should I use strcpy() to copy the string into argument?

It is safe to do, and getopt() is designed to be used that way. More generally, the program arguments provided to main are specified to be writable strings belonging to the program.

Do note, however, that some getopt() implementations, notably GNU's, may reorder the elements of argv.

If I accidentally change the contents of argument, could an attacker change stuff like environment variables?

The argument strings are susceptible to bounds overflow errors just like any other objects in the program. If, through programming error or other means, your program attempts to write past the bounds of any object then the behavior is undefined. Modification of environment variables is one of the more plausible members of the unbounded space of possible manifestations of UB.

Note, however, that making a copy of the arguments doesn't help in that regard. You must avoid overrunning the bounds of any such copies, too, lest UB be triggered, with the same unbounded space of possible manifestations.

If you want to make sure that the program arguments cannot be modified via variable argument, then it would be idiomatic to declare it as a pointer to const char instead of a pointer to (modifiable) char. That will not interfere with assigning the value of optarg to it.

偏闹i 2025-02-14 00:05:24

是的,这是“安全的”。

argv的内容由主机环境提供,并属于您的整个过程。

on argv

字符串是可修改的,尽管这些修改不会传播回主机环境,但进行了任何修改,直到程序终止为止:例如,可以使用 strtok

话虽如此,特权流程(例如ps实用程序)通常能够访问argv的当前值。建议使用argv以获取敏感信息。

请参阅: in unix onix 可以在运行时更改argv(不是由应用程序本身)出于安全问题。


一边: getopt getopt 返回int。区别很重要,因为如果char未签名,它不能表示终止值:

如果所有命令行选项都已解析,则getopt()返回-1。

您应该使用int可靠地针对此值进行测试,否则循环将无限继续。

int ch;

while (-1 != (ch = getopt(argc, argv, ":f:")))

Yes, this is "safe".

The contents of argv are supplied by the host environment, and belong to your process for its entire duration.

On argv:

The strings are modifiable, and any modifications made persist until program termination, although these modifications do not propagate back to the host environment: they can be used, for example, with strtok.

With that said, privileged processes, like the ps utility, are generally capable of accessing the current values of argv. Using argv for sensitive information is ill advised.

See: Hiding secret from command line parameter on Unix and Can argv be changed at runtime (not by the app itself) for security concerns.


Aside: getopt returns an int. The distinction is important, because if char is unsigned, it cannot represent the terminating value:

If all command-line options have been parsed, then getopt() returns -1.

You should use int to reliably test against this value, otherwise the loop will continue infinitely.

int ch;

while (-1 != (ch = getopt(argc, argv, ":f:")))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文