5 文件操作
5.1 【必须】避免路径穿越问题
在进行文件操作时,需要判断外部传入的文件名是否合法,如果文件名中包含 ../
等特殊字符,则会造成路径穿越,导致任意文件的读写。
错误:
void Foo() {
char file_path[PATH_MAX] = "/home/user/code/";
// 如果传入的文件名包含../可导致路径穿越
// 例如"../file.txt",则可以读取到上层目录的file.txt文件
char name[20] = "../file.txt";
memcpy(file_path + strlen(file_path), name, sizeof(name));
int fd = open(file_path, O_RDONLY);
if (fd != -1) {
char data[100] = {0};
int num = 0;
memset(data, 0, sizeof(data));
num = read(fd, data, sizeof(data));
if (num > 0) {
write(STDOUT_FILENO, data, num);
}
close(fd);
}
}
正确:
void Foo() {
char file_path[PATH_MAX] = "/home/user/code/";
char name[20] = "../file.txt";
// 判断传入的文件名是否非法,例如"../file.txt"中包含非法字符../,直接返回
if (strstr(name, "..") != NULL){
// 包含非法字符
return;
}
memcpy(file_path + strlen(file_path), name, sizeof(name));
int fd = open(file_path, O_RDONLY);
if (fd != -1) {
char data[100] = {0};
int num = 0;
memset(data, 0, sizeof(data));
num = read(fd, data, sizeof(data));
if (num > 0) {
write(STDOUT_FILENO, data, num);
}
close(fd);
}
}
关联漏洞:
高风险-逻辑漏洞
5.2 【必须】避免相对路径导致的安全问题(DLL、EXE劫持等问题)
在程序中,使用相对路径可能导致一些安全风险,例如DLL、EXE劫持等问题。
例如以下代码,可能存在劫持问题:
int Foo() {
// 传入的是dll文件名,如果当前目录下被写入了恶意的同名dll,则可能导致dll劫持
HINSTANCE hinst = ::LoadLibrary("dll_nolib.dll");
if (hinst != NULL) {
cout<<"dll loaded!" << endl;
}
return 0;
}
针对DLL劫持的安全编码的规范:
1)调用LoadLibrary,LoadLibraryEx,CreateProcess,ShellExecute等进行模块加载的函数时,指明模块的完整(全)路径,禁止使用相对路径,这样就可避免从其它目录加载DLL。 2)在应用程序的开头调用SetDllDirectory(TEXT(“”)); 从而将当前目录从DLL的搜索列表中删除。结合SetDefaultDllDirectories,AddDllDirectory,RemoveDllDirectory这几个API配合使用,可以有效的规避DLL劫持问题。这些API只能在打了KB2533623补丁的Windows7,2008上使用。
关联漏洞:
中风险-逻辑漏洞
5.3 【必须】文件权限控制
在创建文件时,需要根据文件的敏感级别设置不同的访问权限,以防止敏感数据被其他恶意程序读取或写入。
错误:
int Foo() {
// 不要设置为777权限,以防止被其他恶意程序操作
if (creat("file.txt", 0777) < 0) {
printf("文件创建失败!\n");
} else {
printf("文件创建成功!\n");
}
return 0;
}
关联漏洞:
中风险-逻辑漏洞