如何消除VeraCode检测中的OS Command Injection Issue(CWE ID 78)

Veracode是一个检测应用程序是否存在安全漏洞的工具,更多细节请访问http://www.veracode.com

这里主要总结一下如何消除Veracode检测结果中的OS Command Injection issue(CWE ID 78)。

首先,先看看VeraCode对OS Command Injection的定义:
OS command injection vulnerabilities occur when data enters an application from an untrusted source and is used to
dynamically construct and execute a system command.  This allows an attacker to either alter the command executed by the application or append additional commands.  The command is typically executed with the privileges of the executing process and gives an attacker a privilege or capability that he would not otherwise have.

再看卡VeraCode对如何解决这个问题的建议:
Careful handling of all untrusted data is critical in preventing OS command injection attacks.   Using one or more of the following techniques provides defense-in-depth and minimizes the likelihood of an vulnerability.
* If possible, use library calls rather than external processes to recreate the desired functionality.
* Validate user-supplied input using positive filters (white lists) to ensure that it conforms to the expected format, using centralized data validation routines when possible.
* Select safe API routines.  Some APIs that execute system commands take an array of strings as input rather than a
single string, which protects against some forms of command injection by ensuring that a user-supplied argument
cannot be interpreted as part of the command.
通过对现有系统的实践证明,对于这类OS Command Injection Issue,消除时主要遵循以下几个原则:

1)重构代码,保证只有1个函数最终执行Runtime.exec(xxxx,xxx)
    public static Process execAndReturnProcess(String cmd[]) throws Exception
    {
        
return execAndReturnProcess(cmd, null);
    }
   
    public static Process execAndReturnProcess(String cmds[], String envps[]) throws Exception
    {
        String[] validatedCmdArray 
= ASEUtils.validateCommandArray(cmds);
        String[] validatedEnvArray 
= ASEUtils.validateEnvArray(envps);
        
        
if (null == validatedCmdArray)
        {
            
throw new Exception("No permission to execute the command:" + cmds[0]);
        }
        
        Runtime runtime 
= Runtime.getRuntime();
        Process process 
= runtime.exec(validatedCmdArray, validatedEnvArray);
        
return process;
    }

2)用Runtime.exec调用操作系统命令时,优先使用数组作为参数
Process exec(String[] cmdarray, String[] envp, File dir)
而不是字符串作为参数
Process exec(String cmd, String[] envp, File dir)

3)Veracode会检测传入exec()的变量是否存在隐患(比如文件中读取出来的,或者注册表里读取出来的),这种情况就需要对原有变量做验证,然后重新定义变量,传入Runtime.exec中,如下面代码所示:
public static Process execAndReturnProcess(String cmds[], String envps[]) throws Exception
    {
        String[] validatedCmdArray 
= validateCommandArray(cmds);
        String[] validatedEnvArray 
= validateEnvArray(envps);
        
        
if (null == validatedCmdArray)
        {
            
throw new Exception("No permission to execute the command:" + cmds[0]);
        }
        
        Runtime runtime 
= Runtime.getRuntime();
        Process process 
= runtime.exec(validatedCmdArray, validatedEnvArray);
        
return process;
    }    
    
    
public static String[] validateCommandArray(String[] cmdArray)
    {
        String[] validatedCmdArray = new String[cmdArray.length];
        
        
for (int i=0; i<cmdArray.length; i++)
        {
            
if ( null != cmdArray[i] && cmdArray[i].trim().length()>0)
            {
                validatedCmdArray[i] 
= removeControlCharacter(cmdArray[i]);
            }
        }
        
return validatedCmdArray;
    }

4)另外,还可以定义一个全局的可执行命令的列表(White List),对每次要执行的命令,都验证它是否在允许的可执行命令列表里。

public static final String [] ALLOWED_COMMAND_ROUTINES =
    {
        
"cmd",        
        
"command",    
        
"sh",         
        
"env",
    };
    
    
private static boolean isValidateCommandRoutine(String command)
    {
        Boolean isValidRoutine 
= false;
        
for (int i=0; i<ALLOWED_COMMAND_ROUTINES.length ;i++)
        {
            
if (command.equals(ALLOWED_COMMAND_ROUTINES[i]) != -1)
            {
                isValidRoutine 
= true;
            }
        }
        
return isValidRoutine;
    }
    
    
public static String[] validateCommandArray(String cmds[])
    {
        Boolean isValidRoutine 
= isValidateCommandRoutine(cmds[0]);
        
if (isValidRoutine)
        {
            String[] validatedCmdArray 
= new String[cmds.length];
            
for (int i=0; i<cmds.length; i++)
            {
                
if ( null != cmds[i] && cmds[i].trim().length()>0)
                {
                    validatedCmdArray[i] 
= removeControlCharacter(cmds[i]);
                }
            }
            
return validatedCmdArray;
        }
        
return null;
    }

当然,如果第三方检测程序始终认为最后的调用 Runtime.exec(xxx,xx)存在隐患,则可以采用它们提供的注释或者标记等其他方法消除最终的调用入口。

实际上,我们在做第三方安全检测时,使用上面提到的4点,Veracode 已经可以通过检测了,但是Fortify不行,所以最后只能在Fortify的系统里标记"Not an issue", 忽略这个最终的Runtime.exec调用。

posted on 2011-09-06 10:28 想飞就飞 阅读(3632) 评论(0)  编辑  收藏 所属分类: J2EE开发工具&环境


只有注册用户登录后才能发表评论。


网站导航:
 

公告


导航

<2011年9月>
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

统计

常用链接

留言簿(13)

我参与的团队

随笔分类(69)

随笔档案(68)

最新随笔

搜索

积分与排名

最新评论

阅读排行榜

评论排行榜