Projects STRLCPY param-miner Commits 9b87764d
🤬
  • albinowaxUtils-all.jar
    Binary file.
  • ■ ■ ■ ■ ■
    src/burp/BurpExtender.java
    skipped 68 lines
    69 69   guessSettings.register("try cache poison", true);
    70 70   guessSettings.register("twitchy cache poison", false);
    71 71   guessSettings.register("try method flip", false);
     72 + guessSettings.register("identify smuggle mutations", true);
    72 73   guessSettings.register("try -_ bypass", false);
    73 74   guessSettings.register("rotation interval", 200);
    74 75   guessSettings.register("rotation increment", 4);
    skipped 7 lines
    82 83   guessSettings.register("poison only", false);
    83 84   guessSettings.register("tunnelling retry count", 20);
    84 85   guessSettings.register("abort on tunnel failure", true);
    85  - 
    86 86   
    87 87   loadWordlists();
    88 88   BlockingQueue<Runnable> tasks;
    skipped 53 lines
    142 142   new NormalisedParamScan("normalised param");
    143 143   new NormalisedPathScan("normalised path");
    144 144   new RailsUtmScan("rails param cloaking scan");
     145 + new HeaderMutationScan("identify header smuggling mutations");
    145 146   
    146 147   
    147 148   new BulkScanLauncher(BulkScan.scans);
    skipped 448 lines
  • ■ ■ ■ ■ ■ ■
    src/burp/HeaderMutationGuesser.java
     1 +package burp;
     2 +
     3 +import org.graalvm.compiler.core.common.util.Util;
     4 +
     5 +import java.nio.charset.StandardCharsets;
     6 +import java.util.ArrayList;
     7 +import java.util.HashMap;
     8 +import java.util.Iterator;
     9 +
     10 +public class HeaderMutationGuesser {
     11 + private ConfigurableSettings config;
     12 + private IHttpRequestResponse req;
     13 + private IHttpService service;
     14 + public HashMap<String, IHttpRequestResponse[]> evidence;
     15 + private String[][] testHeaders;
     16 +
     17 + HeaderMutationGuesser(IHttpRequestResponse req, ConfigurableSettings config) {
     18 + this.req = req;
     19 + this.config = config;
     20 + this.service = req.getHttpService();
     21 + this.evidence = new HashMap<String, IHttpRequestResponse[]>();
     22 +
     23 + this.testHeaders = new String[][]{
     24 + {"Content-Length: 0", "Content-Length: z"}
     25 + };
     26 + }
     27 +
     28 + // Returns the mutation names used by HeaderMutator
     29 + public ArrayList<String> guessMutations() {
     30 + byte[] baseReq = this.removeHeader(this.req.getRequest(), "Content-Length");
     31 + ArrayList<String> ret = new ArrayList<String>();
     32 + HeaderMutator mutator = new HeaderMutator();
     33 +
     34 + // Test all the mutations to find back-end errors
     35 + for (int i = 0; i< this.testHeaders.length; i++) {
     36 + Iterator<String> iterator = mutator.mutations.iterator();
     37 + String testHeaderValid = this.testHeaders[i][0];
     38 + String testHeaderInvalid = this.testHeaders[i][1];
     39 +
     40 + // Get the front-end error
     41 + IHttpRequestResponse frontErrReq = this.requestHeader(baseReq, testHeaderInvalid);
     42 + byte[] frontError = frontErrReq.getResponse();
     43 +
     44 + // Check we've managed to generate an error
     45 + IHttpRequestResponse noErrReq = this.requestHeader(baseReq, testHeaderValid);
     46 + byte[] noErr = noErrReq.getResponse();
     47 + if (this.requestMatch(frontError, noErr)) {
     48 + continue;
     49 + }
     50 +
     51 + if (frontError.length == 0 || noErr.length == 0) {
     52 + String host = frontErrReq.getHttpService().getHost();
     53 + Utilities.out("Failed to fetch request while guessing mutations " + host);
     54 + continue;
     55 + }
     56 +
     57 + while (iterator.hasNext()) {
     58 + String mutation = iterator.next();
     59 + if (ret.contains(mutation)) {
     60 + continue;
     61 + }
     62 + byte[] mutated = mutator.mutate(testHeaderInvalid, mutation);
     63 + IHttpRequestResponse testReqResp = this.requestHeader(baseReq, mutated);
     64 + byte[] testReq = testReqResp.getResponse();
     65 +
     66 + // Check that:
     67 + // 1. We have a different error than the front-end error
     68 + // 2. We have an error at all (i.e. not the same as the base request
     69 + // In this case, confirm that we get no error (i.e. the base response) with mutation(CL: 0)
     70 + if (!this.requestMatch(frontError, testReq) && !this.requestMatch(noErr, testReq)) {
     71 + mutated = mutator.mutate(testHeaderValid, mutation);
     72 + IHttpRequestResponse validReqResp = this.requestHeader(baseReq, mutated);
     73 + byte[] validResp = validReqResp.getResponse();
     74 + if (this.requestMatch(noErr, validResp)) {
     75 + ret.add(mutation);
     76 + IHttpRequestResponse[] reqs = new IHttpRequestResponse[4];
     77 + reqs[0] = frontErrReq;
     78 + reqs[1] = noErrReq;
     79 + reqs[2] = testReqResp;
     80 + reqs[3] = validReqResp;
     81 + this.evidence.put(mutation, reqs);
     82 + }
     83 + }
     84 + }
     85 + }
     86 +
     87 + // TODO: Maybe re-check mutations to deal with inconsistent servers?
     88 + return ret;
     89 + }
     90 +
     91 + public void reportMutations(ArrayList<String> mutations) {
     92 + Iterator<String> iterator = mutations.iterator();
     93 + while (iterator.hasNext()) {
     94 + String mutation = iterator.next();
     95 + String urlStr = Utilities.getURL(this.req).toString();
     96 + Utilities.out("Found mutation against " + urlStr + ": " + mutation);
     97 + IHttpRequestResponse[] evidence = this.evidence.get(mutation);
     98 + IHttpService service = evidence[0].getHttpService();
     99 + Utilities.callbacks.addScanIssue(new CustomScanIssue(
     100 + service,
     101 + Utilities.helpers.analyzeRequest(service, evidence[0].getRequest()).getUrl(),
     102 + evidence,
     103 + "Header mutation found",
     104 + "Headers can be snuck to a back-end server using the '" + mutation + "' mutation.",
     105 + "Information",
     106 + "Firm",
     107 + "This issue is not exploitable on its own, but interesting headers may be able to be snuck through to backend servers."
     108 + ));
     109 + }
     110 + }
     111 +
     112 + private IHttpRequestResponse requestHeader(byte[] baseReq, String header) {
     113 + return this.requestHeader(baseReq, header.getBytes(StandardCharsets.UTF_8));
     114 + }
     115 +
     116 + private IHttpRequestResponse requestHeader(byte[] baseReq, byte[] header) {
     117 + byte[] req = this.addHeader(baseReq, header);
     118 + req = Utilities.addCacheBuster(req, Utilities.generateCanary());
     119 + return Utilities.attemptRequest(this.service, req);
     120 + }
     121 +
     122 + private byte[] removeHeader(byte[] req, String headerName) {
     123 + int[] offsets = Utilities.getHeaderOffsets(req, headerName);
     124 + if (offsets == null) {
     125 + return req;
     126 + }
     127 + int start = offsets[0];
     128 + int end = offsets[2] + 2;
     129 + byte[] ret = new byte[req.length - (end - start)];
     130 + // TODO: sometimes getting null point exceptions from this line
     131 + System.arraycopy(req, 0, ret, 0, start);
     132 + System.arraycopy(req, end, ret, start, req.length - end);
     133 + return ret;
     134 + }
     135 +
     136 + private boolean requestMatch(byte[] resp1, byte[] resp2) {
     137 + IResponseInfo info1 = Utilities.helpers.analyzeResponse(resp1);
     138 + IResponseInfo info2 = Utilities.helpers.analyzeResponse(resp2);
     139 + if (info1.getStatusCode() != info2.getStatusCode()) {
     140 + return false;
     141 + }
     142 +
     143 + // If we have a body length, use that as a comparison. Otherwise, use the total length
     144 + int length1 = resp1.length - info1.getBodyOffset();
     145 + int length2 = resp2.length - info2.getBodyOffset();
     146 + if (length1 == 0 || length2 == 0) {
     147 + length1 = resp1.length;
     148 + length2 = resp2.length;
     149 + }
     150 + int lower = (9 * length1) / 10;
     151 + int upper = (11 * length1) / 10;
     152 +
     153 + if (length2 <= lower || length2 >= upper) {
     154 + return false;
     155 + }
     156 +
     157 + return true;
     158 + }
     159 +
     160 + private byte[] addHeader(byte[] baseReq, byte[] header) {
     161 + IRequestInfo info = Utilities.analyzeRequest(baseReq);
     162 + int offset = info.getBodyOffset() - 2;
     163 + byte[] ret = new byte[baseReq.length + header.length + 2];
     164 + byte[] crlf = "\r\n".getBytes(StandardCharsets.UTF_8);
     165 +
     166 + System.arraycopy(baseReq, 0, ret, 0, offset);
     167 + System.arraycopy(header, 0, ret, offset, header.length);
     168 + int newOffset = offset + header.length;
     169 + System.arraycopy(crlf, 0, ret, newOffset, 2);
     170 + newOffset += 2;
     171 + System.arraycopy(baseReq, offset, ret, newOffset, baseReq.length - offset);
     172 +
     173 + return ret;
     174 + }
     175 +}
  • ■ ■ ■ ■ ■ ■
    src/burp/HeaderMutationScan.java
     1 +package burp;
     2 +
     3 +import java.util.ArrayList;
     4 +import java.util.List;
     5 +
     6 +public class HeaderMutationScan extends Scan {
     7 + HeaderMutationScan(String name) {
     8 + super(name);
     9 + }
     10 +
     11 +
     12 + @Override
     13 + List<IScanIssue> doScan(IHttpRequestResponse req) {
     14 + //new ParamGuesser(req, false, Utilities.PARAM_HEADER, BurpExtender.paramGrabber, null, 2147483647, Utilities.globalSettings).run();
     15 + HeaderMutationGuesser guesser = new HeaderMutationGuesser(req, Utilities.globalSettings);
     16 + ArrayList<String> mutations = guesser.guessMutations();
     17 + guesser.reportMutations(mutations);
     18 + return null;
     19 + }
     20 +}
     21 + 
  • ■ ■ ■ ■ ■
    src/burp/ParamAttack.java
    skipped 30 lines
    31 31   private final ParamInsertionPoint insertionPoint;
    32 32   final byte type;
    33 33   private ConfigurableSettings config;
     34 + private ArrayList<String> headerMutations;
    34 35   
    35 36   int getStop() {
    36 37   return stop;
    skipped 58 lines
    95 96   IHttpRequestResponse getBaseRequestResponse() {
    96 97   return baseRequestResponse;
    97 98   }
     99 + 
     100 + ArrayList<String> getHeaderMutations() { return headerMutations; }
     101 + 
     102 + void setHeaderMutations(ArrayList<String> mutations) { this.headerMutations = mutations; }
    98 103   
    99 104   
    100 105   ParamAttack(IHttpRequestResponse baseRequestResponse, byte type, ParamGrabber paramGrabber, int stop, ConfigurableSettings config) {
    skipped 351 lines
  • ■ ■ ■ ■ ■ ■
    src/burp/ParamGuesser.java
    skipped 1 lines
    2 2  
    3 3  import org.apache.commons.collections4.queue.CircularFifoQueue;
    4 4  
    5  -import java.io.ByteArrayOutputStream;
    6  -import java.io.IOException;
    7  -import java.io.PrintWriter;
    8 5  import java.util.*;
    9 6  import java.util.concurrent.ThreadPoolExecutor;
    10 7  
    skipped 63 lines
    74 71   }
    75 72   this.attack = new ParamAttack(req, type, paramGrabber, stop, config);
    76 73   }
     74 +
     75 + // Check for mutations
     76 + if (this.type == Utilities.PARAM_HEADER && config.getBoolean("identify smuggle mutations")) {
     77 + HeaderMutationGuesser mutationGuesser = new HeaderMutationGuesser(req, this.config);
     78 + ArrayList<String> mutations = mutationGuesser.guessMutations();
     79 + this.attack.setHeaderMutations(mutations);
     80 +
     81 + // Report if required
     82 + if (mutations != null) {
     83 + mutationGuesser.reportMutations(mutations);
     84 + }
     85 + }
     86 +
    77 87   ArrayList<Attack> paramGuesses = guessParams(attack);
    78 88   if (!paramGuesses.isEmpty()) {
    79 89   Utilities.callbacks.addScanIssue(Utilities.reportReflectionIssue(paramGuesses.toArray((new Attack[paramGuesses.size()])), req, "", ""));
    skipped 43 lines
    123 133   final HashMap<String, String> requestParams = state.getRequestParams();
    124 134   final WordProvider bonusParams = state.getBonusParams();
    125 135   final byte type = state.type;
     136 + ArrayList<String> headerMutations = state.getHeaderMutations();
    126 137  
    127 138   ArrayList<Attack> attacks = new ArrayList<>();
    128 139   int completedAttacks = 0;
    skipped 30 lines
    159 170   }
    160 171   newParams.add(next);
    161 172   }
    162  - }
    163  - else {
     173 + } else {
    164 174   if (!config.getBoolean("bruteforce")) {
    165  - Utilities.out("Completed attack on "+ targetURL);
     175 + Utilities.out("Completed attack on " + targetURL);
    166 176   if (taskEngine != null) {
    167 177   Utilities.out("Completed " + (taskEngine.getCompletedTaskCount() + 1) + "/" + (taskEngine.getTaskCount()));
    168 178   }
    skipped 8 lines
    177 187   ArrayList<String> candidates;
    178 188   try {
    179 189   candidates = paramBuckets.pop();
    180  - }
    181  - catch (NoSuchElementException e) {
     190 + Iterator<String> iterator = candidates.iterator();
     191 + } catch (NoSuchElementException e) {
    182 192   continue;
    183 193   }
    184 194  
    skipped 10 lines
    195 205   }
    196 206  
    197 207   String submission = String.join("|", candidates);
    198  - Attack paramGuess = injector.probeAttack(submission);
    199  -
    200  - if (!candidates.contains("~")) {
    201  - if (findPersistent(baseRequestResponse, paramGuess, attackID, state.recentParams, candidates, state.alreadyReported)) {
    202  - state.updateBaseline();
    203  - }
    204  - state.recentParams.addAll(candidates); // fixme this results in params being found multiple times
     208 + if (headerMutations == null) {
     209 + headerMutations = new ArrayList<String>();
    205 210   }
    206 211  
    207  - Attack localBase;
    208  - if (submission.contains("~")) {
    209  - localBase = new Attack();
    210  - localBase.addAttack(base);
     212 + // Ensure that the identity mutation is scanned
     213 + if (headerMutations.size() == 0 || headerMutations.get(0) != null) {
     214 + headerMutations.add(0, null);
    211 215   }
    212  - else {
    213  - localBase = base;
    214  - }
     216 + Iterator<String> iterator = headerMutations.iterator();
     217 + while (iterator.hasNext()) {
     218 + String mutation = iterator.next();
     219 + Attack paramGuess = injector.probeAttack(submission, mutation);
    215 220  
    216  - if (!Utilities.globalSettings.getBoolean("carpet bomb") && !Utilities.similar(localBase, paramGuess)) {
    217  - Attack confirmParamGuess = injector.probeAttack(submission);
     221 + if (!candidates.contains("~")) {
     222 + if (findPersistent(baseRequestResponse, paramGuess, attackID, state.recentParams, candidates, state.alreadyReported)) {
     223 + state.updateBaseline();
     224 + }
     225 + state.recentParams.addAll(candidates); // fixme this results in params being found multiple times
     226 + }
    218 227  
    219  - Attack failAttack = injector.probeAttack(Keysmith.permute(submission));
     228 + Attack localBase;
     229 + if (submission.contains("~")) {
     230 + localBase = new Attack();
     231 + localBase.addAttack(base);
     232 + } else {
     233 + localBase = base;
     234 + }
    220 235  
    221  - // this to prevent error messages obscuring persistent inputs
    222  - findPersistent(baseRequestResponse, failAttack, attackID, state.recentParams, null, state.alreadyReported);
     236 + if (!Utilities.globalSettings.getBoolean("carpet bomb") && !Utilities.similar(localBase, paramGuess)) {
     237 + Attack confirmParamGuess = injector.probeAttack(submission, mutation);
    223 238  
    224  - localBase.addAttack(failAttack);
    225  - if (!Utilities.similar(localBase, confirmParamGuess)) {
     239 + Attack failAttack = injector.probeAttack(Keysmith.permute(submission), mutation);
    226 240  
    227  - if(candidates.size() > 1) {
    228  - Utilities.log("Splitting "+ submission);
    229  - ArrayList<String> left = new ArrayList<>(candidates.subList(0, candidates.size() / 2));
    230  - Utilities.log("Got "+String.join("|",left));
    231  - ArrayList<String> right = new ArrayList<>(candidates.subList(candidates.size() / 2, candidates.size()));
    232  - Utilities.log("Got "+String.join("|",right));
    233  - paramBuckets.push(left);
    234  - paramBuckets.push(right);
    235  - }
    236  - else {
    237  - if (state.alreadyReported.contains(submission)) {
    238  - continue;
    239  - }
     241 + // this to prevent error messages obscuring persistent inputs
     242 + findPersistent(baseRequestResponse, failAttack, attackID, state.recentParams, null, state.alreadyReported);
     243 + localBase.addAttack(failAttack);
    240 244  
    241  - Attack WAFCatcher = new Attack(Utilities.attemptRequest(service, Utilities.addOrReplaceHeader(baseRequestResponse.getRequest(), "junk-header", submission)));
    242  - WAFCatcher.addAttack(new Attack(Utilities.attemptRequest(service, Utilities.addOrReplaceHeader(baseRequestResponse.getRequest(), "junk-head", submission))));
    243  - if (!Utilities.similar(WAFCatcher, confirmParamGuess)){
    244  - Probe validParam = new Probe("Found unlinked param: " + submission, 4, submission);
    245  - validParam.setEscapeStrings(Keysmith.permute(submission), Keysmith.permute(submission, false));
    246  - validParam.setRandomAnchor(false);
    247  - validParam.setPrefix(Probe.REPLACE);
    248  - ArrayList<Attack> confirmed = injector.fuzz(localBase, validParam);
    249  - if (!confirmed.isEmpty()) {
    250  - state.alreadyReported.add(submission);
    251  - Utilities.reportedParams.add(submission);
    252  - Utilities.out("Identified parameter on "+targetURL + ": " + submission);
     245 + if (!Utilities.similar(localBase, confirmParamGuess)) {
     246 + if (candidates.size() > 1) {
     247 + Utilities.log("Splitting " + submission);
     248 + ArrayList<String> left = new ArrayList<>(candidates.subList(0, candidates.size() / 2));
     249 + Utilities.log("Got " + String.join("|", left));
     250 + ArrayList<String> right = new ArrayList<>(candidates.subList(candidates.size() / 2, candidates.size()));
     251 + Utilities.log("Got " + String.join("|", right));
     252 + paramBuckets.push(left);
     253 + paramBuckets.push(right);
     254 + } else {
     255 + if (state.alreadyReported.contains(submission)) {
     256 + Utilities.out("Ignoring reporting of submission " + submission + " using mutation " + mutation + " as already reported.");
     257 + continue;
     258 + }
    253 259  
    254  - boolean cacheSuccess = false;
    255  - if (type == Utilities.PARAM_HEADER || type == IParameter.PARAM_COOKIE) {
    256  - cacheSuccess = cachePoison(injector, submission, failAttack.getFirstRequest());
    257  - }
     260 + Attack WAFCatcher = new Attack(Utilities.attemptRequest(service, Utilities.addOrReplaceHeader(baseRequestResponse.getRequest(), "junk-header", submission)));
     261 + WAFCatcher.addAttack(new Attack(Utilities.attemptRequest(service, Utilities.addOrReplaceHeader(baseRequestResponse.getRequest(), "junk-head", submission))));
     262 + if (!Utilities.similar(WAFCatcher, confirmParamGuess)) {
     263 + Probe validParam = new Probe("Found unlinked param: " + submission, 4, submission);
     264 + validParam.setEscapeStrings(Keysmith.permute(submission), Keysmith.permute(submission, false));
     265 + validParam.setRandomAnchor(false);
     266 + validParam.setPrefix(Probe.REPLACE);
     267 + ArrayList<Attack> confirmed = injector.fuzz(localBase, validParam, mutation);
     268 + if (!confirmed.isEmpty()) {
     269 + state.alreadyReported.add(submission);
     270 + Utilities.reportedParams.add(submission);
     271 + Utilities.out("Identified parameter on " + targetURL + ": " + submission);
    258 272  
    259  - if (!Utilities.globalSettings.getBoolean("poison only")) {
    260  - String title = "Secret input: " + Utilities.getNameFromType(type);
    261  - if (!cacheSuccess && canSeeCache(paramGuess.getFirstRequest().getResponse())) {
    262  - title = "Secret uncached input: " + Utilities.getNameFromType(type);
    263  - }
    264  - if (Utilities.globalSettings.getBoolean("name in issue")) {
    265  - title += ": " + submission.split("~")[0];
     273 + boolean cacheSuccess = false;
     274 + if (type == Utilities.PARAM_HEADER || type == IParameter.PARAM_COOKIE) {
     275 + cacheSuccess = cachePoison(injector, submission, failAttack.getFirstRequest());
    266 276   }
    267  - Utilities.callbacks.addScanIssue(Utilities.reportReflectionIssue(confirmed.toArray(new Attack[2]), baseRequestResponse, title, "Unlinked parameter identified."));
     277 + if (!Utilities.globalSettings.getBoolean("poison only")) {
     278 + String title = "Secret input: " + Utilities.getNameFromType(type);
     279 + if (!cacheSuccess && canSeeCache(paramGuess.getFirstRequest().getResponse())) {
     280 + title = "Secret uncached input: " + Utilities.getNameFromType(type);
     281 + }
     282 + if (Utilities.globalSettings.getBoolean("name in issue")) {
     283 + title += ": " + submission.split("~")[0];
     284 + }
     285 + Utilities.callbacks.addScanIssue(Utilities.reportReflectionIssue(confirmed.toArray(new Attack[2]), baseRequestResponse, title, "Unlinked parameter identified."));
     286 + if (type != Utilities.PARAM_HEADER || Utilities.containsBytes(paramGuess.getFirstRequest().getResponse(), staticCanary)) {
     287 + scanParam(insertionPoint, injector, submission.split("~", 2)[0]);
     288 + }
    268 289  
    269  - if (type != Utilities.PARAM_HEADER || Utilities.containsBytes(paramGuess.getFirstRequest().getResponse(), staticCanary)) {
    270  - scanParam(insertionPoint, injector, submission.split("~", 2)[0]);
     290 + base = state.updateBaseline();
    271 291   }
    272 292  
    273  - base = state.updateBaseline();
    274  - }
     293 + //Utilities.callbacks.doPassiveScan(service.getHost(), service.getPort(), service.getProtocol().equals("https"), paramGuess.getFirstRequest().getRequest(), paramGuess.getFirstRequest().getResponse());
    275 294  
    276  - //Utilities.callbacks.doPassiveScan(service.getHost(), service.getPort(), service.getProtocol().equals("https"), paramGuess.getFirstRequest().getRequest(), paramGuess.getFirstRequest().getResponse());
    277  -
    278  - if (config.getBoolean("dynamic keyload")) {
    279  - ArrayList<String> newWords = new ArrayList<>(Keysmith.getWords(Utilities.helpers.bytesToString(paramGuess.getFirstRequest().getResponse())));
    280  - addNewKeys(newWords, state, bucketSize, paramBuckets, candidates, paramGuess);
     295 + if (config.getBoolean("dynamic keyload")) {
     296 + ArrayList<String> newWords = new ArrayList<>(Keysmith.getWords(Utilities.helpers.bytesToString(paramGuess.getFirstRequest().getResponse())));
     297 + addNewKeys(newWords, state, bucketSize, paramBuckets, candidates, paramGuess);
     298 + }
     299 + } else {
     300 + Utilities.out(targetURL + " questionable parameter: " + candidates);
    281 301   }
    282  - } else {
    283  - Utilities.out(targetURL + " questionable parameter: " + candidates);
    284 302   }
    285 303   }
     304 + } else{
     305 + Utilities.log(targetURL + " couldn't replicate: " + candidates);
     306 + base.addAttack(paramGuess);
    286 307   }
    287  - } else {
    288  - Utilities.log(targetURL + " couldn't replicate: " + candidates);
    289  - base.addAttack(paramGuess);
    290  - }
    291 308  
    292  - if(config.getBoolean("dynamic keyload")) {
    293  - addNewKeys(Keysmith.getAllKeys(paramGuess.getFirstRequest().getResponse(), requestParams), state, bucketSize, paramBuckets, candidates, paramGuess);
    294  - }
     309 + if (config.getBoolean("dynamic keyload")) {
     310 + addNewKeys(Keysmith.getAllKeys(paramGuess.getFirstRequest().getResponse(), requestParams), state, bucketSize, paramBuckets, candidates, paramGuess);
     311 + }
    295 312  
    296  - } else if (tryMethodFlip) {
    297  - Attack paramGrab = new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase));
    298  - findPersistent(baseRequestResponse, paramGrab, attackID, state.recentParams, null, state.alreadyReported);
    299  -
    300  - if (!Utilities.similar(altBase, paramGrab)) {
    301  - Utilities.log("Potential GETbase param: " + candidates);
    302  - injector.probeAttack(Keysmith.permute(submission));
    303  - altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
    304  - injector.probeAttack(submission);
     313 + } else if (tryMethodFlip) {
     314 + Attack paramGrab = new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase));
     315 + findPersistent(baseRequestResponse, paramGrab, attackID, state.recentParams, null, state.alreadyReported);
    305 316  
    306  - paramGrab = new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase));
    307 317   if (!Utilities.similar(altBase, paramGrab)) {
     318 + Utilities.log("Potential GETbase param: " + candidates);
     319 + injector.probeAttack(Keysmith.permute(submission), mutation);
     320 + altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
     321 + injector.probeAttack(submission, mutation);
    308 322  
    309  - if(candidates.size() > 1) {
    310  - Utilities.log("Splitting "+ submission);
    311  - ArrayList<String> left = new ArrayList<>(candidates.subList(0, candidates.size() / 2));
    312  - ArrayList<String> right = new ArrayList<>(candidates.subList(candidates.size() / 2 + 1, candidates.size()));
    313  - paramBuckets.push(left);
    314  - paramBuckets.push(right);
    315  - }
    316  - else {
    317  - Utilities.out("Confirmed GETbase param: " + candidates);
    318  - IHttpRequestResponse[] evidence = new IHttpRequestResponse[3];
    319  - evidence[0] = altBase.getFirstRequest();
    320  - evidence[1] = paramGuess.getFirstRequest();
    321  - evidence[2] = paramGrab.getFirstRequest();
    322  - Utilities.callbacks.addScanIssue(new CustomScanIssue(service, Utilities.getURL(baseRequestResponse), evidence, "Secret parameter", "Parameter name: '" + candidates + "'. Review the three requests attached in chronological order.", "Medium", "Tentative", "Investigate"));
     323 + paramGrab = new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase));
     324 + if (!Utilities.similar(altBase, paramGrab)) {
    323 325  
    324  - altBase = new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase));
    325  - altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
    326  - altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
    327  - altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
     326 + if (candidates.size() > 1) {
     327 + Utilities.log("Splitting " + submission);
     328 + ArrayList<String> left = new ArrayList<>(candidates.subList(0, candidates.size() / 2));
     329 + ArrayList<String> right = new ArrayList<>(candidates.subList(candidates.size() / 2 + 1, candidates.size()));
     330 + paramBuckets.push(left);
     331 + paramBuckets.push(right);
     332 + } else {
     333 + Utilities.out("Confirmed GETbase param: " + candidates);
     334 + IHttpRequestResponse[] evidence = new IHttpRequestResponse[3];
     335 + evidence[0] = altBase.getFirstRequest();
     336 + evidence[1] = paramGuess.getFirstRequest();
     337 + evidence[2] = paramGrab.getFirstRequest();
     338 + Utilities.callbacks.addScanIssue(new CustomScanIssue(service, Utilities.getURL(baseRequestResponse), evidence, "Secret parameter", "Parameter name: '" + candidates + "'. Review the three requests attached in chronological order.", "Medium", "Tentative", "Investigate"));
     339 +
     340 + altBase = new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase));
     341 + altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
     342 + altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
     343 + altBase.addAttack(new Attack(Utilities.callbacks.makeHttpRequest(service, invertedBase)));
     344 + }
    328 345   }
    329 346   }
    330 347   }
    skipped 427 lines
  • ■ ■ ■ ■ ■
    src/burp/TriggerParamGuesser.java
    1 1  package burp;
    2 2   
    3 3  import org.apache.commons.collections4.queue.CircularFifoQueue;
     4 +import org.graalvm.compiler.core.common.util.Util;
    4 5   
    5 6  import java.awt.event.ActionEvent;
    6 7  import java.awt.event.ActionListener;
    skipped 122 lines
Please wait...
Page is in error, reload to recover