代码改变世界

[hyddd的Fortify SCA分析Java代码记录][Data Flow]Denial of Servie

2009-02-25 13:44  hyddd  阅读(2792)  评论(0编辑  收藏

看Fortify说明的示例代码:

例1:

int usrSleepTime = Integer.parseInt(usrInput);
Thread.sleep(usrSleepTime);

例2:

   ZipFile zf = new ZipFile("c:\\tttt.zip");
        ZipEntry ze = zf.getEntry("tttt.txt");
        InputStream zipInput = zf.getInputStream(ze);
        Reader zipReader =
new InputStreamReader(zipInput);
        BufferedReader br =
new BufferedReader(zipReader);
        String line = br.readLine();
        System.out.println(line);

例3:

    public static String getHttpRequestMsg(String url) {
        String szRetCode 
= "";
        String szTmp 
= "";
        HttpURLConnection httpUrl;
        
try {
            URL urlDest 
= new URL(url);
            httpUrl 
= (HttpURLConnection) urlDest.openConnection();
            httpUrl.getResponseMessage();

            InputStream input 
= httpUrl.getInputStream();

            
int nRead = 0;
            
byte[] b = new byte[1024];
            szTmp 
= "";
            
while ((nRead = input.read(b, 0, b.length)) > 0) {
                szTmp 
= new String(b, 0, nRead, "utf-8");
                szRetCode 
+= szTmp;
            }
            
            input.close();
        } 
catch (IOException e) {
            e.printStackTrace();
        }

        
return szRetCode;
    }

看例1:

  如果例1是一个后端程序,usrSleepTime是前端用户的输入,那么线程的睡眠时间是不确定的,因为你不可能知道用户输入的时间有多大,当多个用户都输入一个很大的usrSleepTime时,后端程序的线程池的消耗是很大的,这会大大影响了后端程序的性能。所以我们应该限制usrSleepTime的值,下面是修正后的代码:

int usrSleepTime = Integer.parseInt(usrInput);
if (usrSleepTime >= SLEEP_MIN && usrSleepTime <= SLEEP_MAX) {
    Thread.sleep(usrSleepTime);
  } 
 
else {
    
throw new Exception("Invalid sleep duration");
 }
}

看例2:

  这里这段代码的目的是读取tttt.zip压缩包里面tttt.txt文件的第一行,这里有个风险是,你不知道tttt.txt文件有多大,也不可能知道tttt.txt文件第一行有多少个字符。攻击者可以传一个很大的文件让你去读取,从而造成OutOfMemoryException,或者制造大量垃圾,让你垃圾回收需要更多的时间,从而降低服务器的性能,又或者会导致后面会因为内存不足而抛异常等等。

下面是修正后的代码,在这里我们应该限制line的长度:

InputStream zipInput = zipFile.getInputStream(zipEntry);
Reader zipReader 
= new InputStreamReader(zipInput);
BufferedReader br 
= new BufferedReader(zipReader);
StringBuffer sb 
= new StringBuffer();
int intC;
while ((intC = br.read()) != -1) {
  
char c = (char) intC;
  
if (c == '\n') {
    
break;
  }
  
if (sb.length() >= MAX_STR_LEN) {
    
throw new Exception("input too long");
  }
  sb.append(c);
}
String line 
= sb.toString();
看例3:

  例3和例2类似,它没有检查URL的可信性,直接就获取URL内容,如果传进来的参数是"http://....//xxx.exe",这会极大的消耗服务器内存,并且在一段时间内大大地降低服务器的性能,这是一个很严重的问题。除了检查URL可信性外,还应该限制一下szRetCode的长度,以免出现消耗内存过大的情况。