我正在研究代码安全性,我正在尝试对以下2个片段进行安全性分析,取自“编写安全代码”,第2版:
http://www.di.uniba.it/~ndm/corsi/sa/materiale/lab/StackOverrun.c
http://www.di.uniba.it/~ndm/corsi/sa/materiale/lab/FormatString.c
在第一个中我认为唯一不安全的陈述是
strcpy(buf, input);
应该是
strncpy(buf, input, sizeof(buf-1));
所有其他printf都是安全的:即使他们使用的参数少于他们的意思,他们也是故意这样做的。
在第二个printf
中,fprintf(stdout, buf);
是安全的,但fprintf(stdout, "%s", buf);
不是,应该替换为此代码:pFile = fopen(argv[1], "r");
我的问题是由于可能的竞争条件,{{1}}也被分析程序认为是不安全的,但我认为在此代码中无法利用它。如果文件以只读方式打开,攻击者可以用它做一些讨厌的事吗?我想不。
所以问题是:你认为这种分析是否正确?你能找到其他瑕疵还是我的推理?
谢谢!
答案 0 :(得分:0)
我的第一个想法是将非清理程序输入传递给libc调用是不好的。有太多的情况会导致libc溢出,开发人员不应该传递超出libc期望的参数(在这种情况下,字符串应该是< PATH_MAX)。
但是既然你提到了竞争条件,我认为虽然在这个特定的例子中没有特别的问题,但是fopen()的使用总体上是不受欢迎的,因为它很容易出现竞争条件。如果要使用文件名而不是文件句柄的函数来寻址文件,任何文件。如果通过路径名称引用文件,使用一个操作或另一个操作,则文件的状态可能会发生变化,程序对该状态的假设可能不再正确。在下面的文章中有更好的解释。
http://www.sans.edu/research/security-laboratory/article/race-cndtns
答案 1 :(得分:0)
来自Apple Development site这个明确的描述:
如果您打开一个文件然后从中读取,即使您的应用程序在这两个操作之间没有执行任何其他操作,其他一些进程也可能会在文件打开之后和读取之前更改该文件。如果两个不同的进程(在相同或不同的应用程序中)写入同一个文件,则无法知道哪个进程将先写入,哪个将覆盖另一个进程写入的数据。这种情况会导致安全漏洞。
可以利用两种基本类型的竞争条件:使用检查时间(TOCTOU)和信号处理。
此外,如所示的fopen()调用没有对文件名进行任何清理。当然你不会那样做,对吧?这个名字绝对应该被分析,检查并且根本不被信任,因为它是该程序的一个参数。理想情况下,您应该use more than a single attribute to identify a file