divide by zero, inaccurate discount and totals, reflection of user input git-svn-id: http://webgoat.googlecode.com/svn/trunk/webgoat@273 4033779f-a91e-0410-96ef-6bf7bf53c507
543 lines
14 KiB
Java
543 lines
14 KiB
Java
package org.owasp.webgoat.util;
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.OutputStream;
|
|
import java.util.BitSet;
|
|
|
|
/*******************************************************************************
|
|
*
|
|
*
|
|
* This file is part of WebGoat, an Open Web Application Security Project
|
|
* utility. For details, please see http://www.owasp.org/
|
|
*
|
|
* Copyright (c) 2002 - 2007 Bruce Mayhew
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it under
|
|
* the terms of the GNU General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option) any later
|
|
* version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
* Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* Getting Source ==============
|
|
*
|
|
* Source for this application is maintained at code.google.com, a repository
|
|
* for free software projects.
|
|
*
|
|
* For details, please see http://code.google.com/p/webgoat/
|
|
*
|
|
* @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
|
|
* @created October 28, 2003
|
|
*/
|
|
public class Exec
|
|
{
|
|
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @param input Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execInput(String command, String input)
|
|
{
|
|
return (execOptions(command, input, 0, 0, false));
|
|
}
|
|
|
|
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execLazy(String command)
|
|
{
|
|
return (execOptions(command, "", 0, 0, true));
|
|
}
|
|
|
|
|
|
/*
|
|
* Execute an OS command and capture the output in an ExecResults.
|
|
* All exceptions are caught and stored in the ExecResults.
|
|
* @param String command is the OS command to execute
|
|
* @param String input is piped into the OS command
|
|
* @param int successCode is the expected return code if the command completes successfully
|
|
* @param int timeout is the number of milliseconds to wait before interrupting the command
|
|
* @param boolean quit tells the method to exit when there is no more output waiting
|
|
*/
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @param input Description of the Parameter
|
|
* @param successCode Description of the Parameter
|
|
* @param timeout Description of the Parameter
|
|
* @param lazy Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execOptions(String[] command, String input,
|
|
int successCode, int timeout, boolean lazy)
|
|
{
|
|
Process child = null;
|
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
ByteArrayOutputStream errors = new ByteArrayOutputStream();
|
|
ExecResults results = new ExecResults(command[0], input, successCode,
|
|
timeout);
|
|
BitSet interrupted = new BitSet(1);
|
|
boolean lazyQuit = false;
|
|
ThreadWatcher watcher;
|
|
|
|
try
|
|
{
|
|
// start the command
|
|
child = Runtime.getRuntime().exec(command);
|
|
|
|
// get the streams in and out of the command
|
|
InputStream processIn = child.getInputStream();
|
|
InputStream processError = child.getErrorStream();
|
|
OutputStream processOut = child.getOutputStream();
|
|
|
|
// start the clock running
|
|
if (timeout > 0)
|
|
{
|
|
watcher = new ThreadWatcher(child, interrupted, timeout);
|
|
new Thread(watcher).start();
|
|
}
|
|
|
|
// Write to the child process' input stream
|
|
if ((input != null) && !input.equals(""))
|
|
{
|
|
try
|
|
{
|
|
processOut.write(input.getBytes());
|
|
processOut.flush();
|
|
processOut.close();
|
|
}
|
|
catch (IOException e1)
|
|
{
|
|
results.setThrowable(e1);
|
|
}
|
|
}
|
|
|
|
// Read from the child process' output stream
|
|
// The process may get killed by the watcher at any time
|
|
int c = 0;
|
|
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
if (interrupted.get(0) || lazyQuit)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// interrupted
|
|
c = processIn.read();
|
|
|
|
if (c == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// end of stream
|
|
output.write(c);
|
|
|
|
if (lazy && (processIn.available() < 1))
|
|
{
|
|
lazyQuit = true;
|
|
}
|
|
|
|
// if lazy and nothing then quit (after at least one read)
|
|
}
|
|
|
|
processIn.close();
|
|
}
|
|
catch (IOException e2)
|
|
{
|
|
results.setThrowable(e2);
|
|
}
|
|
finally
|
|
{
|
|
if (interrupted.get(0))
|
|
{
|
|
results.setInterrupted();
|
|
}
|
|
|
|
results.setOutput(output.toString());
|
|
}
|
|
|
|
// Read from the child process' error stream
|
|
// The process may get killed by the watcher at any time
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
if (interrupted.get(0) || lazyQuit)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// interrupted
|
|
c = processError.read();
|
|
|
|
if (c == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// end of stream
|
|
output.write(c);
|
|
|
|
if (lazy && (processError.available() < 1))
|
|
{
|
|
lazyQuit = true;
|
|
}
|
|
|
|
// if lazy and nothing then quit (after at least one read)
|
|
}
|
|
|
|
processError.close();
|
|
}
|
|
catch (IOException e3)
|
|
{
|
|
results.setThrowable(e3);
|
|
}
|
|
finally
|
|
{
|
|
if (interrupted.get(0))
|
|
{
|
|
results.setInterrupted();
|
|
}
|
|
|
|
results.setErrors(errors.toString());
|
|
}
|
|
|
|
// wait for the return value of the child process.
|
|
if (!interrupted.get(0) && !lazyQuit)
|
|
{
|
|
int returnCode = child.waitFor();
|
|
results.setReturnCode(returnCode);
|
|
|
|
if (returnCode != successCode)
|
|
{
|
|
results.setError(ExecResults.BADRETURNCODE);
|
|
}
|
|
}
|
|
}
|
|
catch (InterruptedException i)
|
|
{
|
|
results.setInterrupted();
|
|
}
|
|
catch (Throwable t)
|
|
{
|
|
results.setThrowable(t);
|
|
}
|
|
finally
|
|
{
|
|
if (child != null)
|
|
{
|
|
child.destroy();
|
|
}
|
|
}
|
|
|
|
return (results);
|
|
}
|
|
|
|
|
|
/*
|
|
* Execute an OS command and capture the output in an ExecResults.
|
|
* All exceptions are caught and stored in the ExecResults.
|
|
* @param String command is the OS command to execute
|
|
* @param String input is piped into the OS command
|
|
* @param int successCode is the expected return code if the command completes successfully
|
|
* @param int timeout is the number of milliseconds to wait before interrupting the command
|
|
* @param boolean quit tells the method to exit when there is no more output waiting
|
|
*/
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @param input Description of the Parameter
|
|
* @param successCode Description of the Parameter
|
|
* @param timeout Description of the Parameter
|
|
* @param lazy Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execOptions(String command, String input,
|
|
int successCode, int timeout, boolean lazy)
|
|
{
|
|
Process child = null;
|
|
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
|
ByteArrayOutputStream errors = new ByteArrayOutputStream();
|
|
ExecResults results = new ExecResults(command, input, successCode,
|
|
timeout);
|
|
BitSet interrupted = new BitSet(1);
|
|
boolean lazyQuit = false;
|
|
ThreadWatcher watcher;
|
|
|
|
try
|
|
{
|
|
// start the command
|
|
child = Runtime.getRuntime().exec(command);
|
|
|
|
// get the streams in and out of the command
|
|
InputStream processIn = child.getInputStream();
|
|
InputStream processError = child.getErrorStream();
|
|
OutputStream processOut = child.getOutputStream();
|
|
|
|
// start the clock running
|
|
if (timeout > 0)
|
|
{
|
|
watcher = new ThreadWatcher(child, interrupted, timeout);
|
|
new Thread(watcher).start();
|
|
}
|
|
|
|
// Write to the child process' input stream
|
|
if ((input != null) && !input.equals(""))
|
|
{
|
|
try
|
|
{
|
|
processOut.write(input.getBytes());
|
|
processOut.flush();
|
|
processOut.close();
|
|
}
|
|
catch (IOException e1)
|
|
{
|
|
results.setThrowable(e1);
|
|
}
|
|
}
|
|
|
|
// Read from the child process' output stream
|
|
// The process may get killed by the watcher at any time
|
|
int c = 0;
|
|
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
if (interrupted.get(0) || lazyQuit)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// interrupted
|
|
c = processIn.read();
|
|
|
|
if (c == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// end of stream
|
|
output.write(c);
|
|
|
|
if (lazy && (processIn.available() < 1))
|
|
{
|
|
lazyQuit = true;
|
|
}
|
|
|
|
// if lazy and nothing then quit (after at least one read)
|
|
}
|
|
|
|
processIn.close();
|
|
}
|
|
catch (IOException e2)
|
|
{
|
|
results.setThrowable(e2);
|
|
}
|
|
finally
|
|
{
|
|
if (interrupted.get(0))
|
|
{
|
|
results.setInterrupted();
|
|
}
|
|
|
|
results.setOutput(output.toString());
|
|
}
|
|
|
|
// Read from the child process' error stream
|
|
// The process may get killed by the watcher at any time
|
|
try
|
|
{
|
|
while (true)
|
|
{
|
|
if (interrupted.get(0) || lazyQuit)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// interrupted
|
|
c = processError.read();
|
|
|
|
if (c == -1)
|
|
{
|
|
break;
|
|
}
|
|
|
|
// end of stream
|
|
output.write(c);
|
|
|
|
if (lazy && (processError.available() < 1))
|
|
{
|
|
lazyQuit = true;
|
|
}
|
|
|
|
// if lazy and nothing then quit (after at least one read)
|
|
}
|
|
|
|
processError.close();
|
|
}
|
|
catch (IOException e3)
|
|
{
|
|
results.setThrowable(e3);
|
|
}
|
|
finally
|
|
{
|
|
if (interrupted.get(0))
|
|
{
|
|
results.setInterrupted();
|
|
}
|
|
|
|
results.setErrors(errors.toString());
|
|
}
|
|
|
|
// wait for the return value of the child process.
|
|
if (!interrupted.get(0) && !lazyQuit)
|
|
{
|
|
int returnCode = child.waitFor();
|
|
results.setReturnCode(returnCode);
|
|
|
|
if (returnCode != successCode)
|
|
{
|
|
results.setError(ExecResults.BADRETURNCODE);
|
|
}
|
|
}
|
|
}
|
|
catch (InterruptedException i)
|
|
{
|
|
results.setInterrupted();
|
|
}
|
|
catch (Throwable t)
|
|
{
|
|
results.setThrowable(t);
|
|
}
|
|
finally
|
|
{
|
|
if (child != null)
|
|
{
|
|
child.destroy();
|
|
}
|
|
}
|
|
|
|
return (results);
|
|
}
|
|
|
|
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execSimple(String[] command)
|
|
{
|
|
return (execOptions(command, "", 0, 0, false));
|
|
}
|
|
|
|
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execSimple(String command)
|
|
{
|
|
return (execOptions(command, "", 0, 0, false));
|
|
}
|
|
|
|
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @param args Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execSimple(String command, String args)
|
|
{
|
|
return (execOptions(command, args, 0, 0, false));
|
|
}
|
|
|
|
|
|
/**
|
|
* Description of the Method
|
|
*
|
|
* @param command Description of the Parameter
|
|
* @param timeout Description of the Parameter
|
|
* @return Description of the Return Value
|
|
*/
|
|
public static ExecResults execTimeout(String command, int timeout)
|
|
{
|
|
return (execOptions(command, "", 0, timeout, false));
|
|
}
|
|
|
|
|
|
/**
|
|
* The main program for the Exec class
|
|
*
|
|
* @param args The command line arguments
|
|
*/
|
|
public static void main(String[] args)
|
|
{
|
|
ExecResults results;
|
|
String sep = System.getProperty("line.separator");
|
|
System.out.println("-------------------------------------------" + sep
|
|
+ "TEST 1: execSimple");
|
|
results = Exec.execSimple("c:/swarm-2.1.1/bin/whoami.exe");
|
|
System.out.println(results);
|
|
System.out.println("-------------------------------------------" + sep
|
|
+ "TEST 2: execSimple (with search)");
|
|
results = Exec.execSimple("netstat -r");
|
|
System.out.println(results);
|
|
|
|
if (results.outputContains("localhost:1031"))
|
|
{
|
|
System.out.println("ERROR: listening on 1031");
|
|
}
|
|
|
|
System.out.println("-------------------------------------------" + sep
|
|
+ "TEST 3: execInput");
|
|
results = Exec.execInput("find \"cde\"",
|
|
"abcdefg1\nhijklmnop\nqrstuv\nabcdefg2");
|
|
System.out.println(results);
|
|
System.out.println("-------------------------------------------" + sep
|
|
+ "TEST 4:execTimeout");
|
|
results = Exec.execTimeout("ping -t 127.0.0.1", 5 * 1000);
|
|
System.out.println(results);
|
|
System.out.println("-------------------------------------------" + sep
|
|
+ "TEST 5:execLazy");
|
|
results = Exec.execLazy("ping -t 127.0.0.1");
|
|
System.out.println(results);
|
|
System.out.println("-------------------------------------------" + sep
|
|
+ "TEST 6:ExecTimeout process never outputs");
|
|
results = Exec.execTimeout("c:/swarm-2.1.1/bin/sleep.exe 20", 5 * 1000);
|
|
System.out.println(results);
|
|
System.out.println("-------------------------------------------" + sep
|
|
+ "TEST 7:ExecTimeout process waits for input");
|
|
results = Exec.execTimeout("c:/swarm-2.1.1/bin/cat", 5 * 1000);
|
|
System.out.println(results);
|
|
}
|
|
}
|