git-svn-id: http://webgoat.googlecode.com/svn/branches/webgoat-6.0@485 4033779f-a91e-0410-96ef-6bf7bf53c507
528 lines
14 KiB
Java
528 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.Arrays;
|
|
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(Arrays.asList(command).toString(), 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);
|
|
}
|
|
}
|