Search in sources :

Example 21 with Request

use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.

the class ManagerFile method readFile.

/**
 * Attempt to read files in parallel by their path from the website using injection.
 * Reading file needs a FILE right on the server.
 * The user can interrupt the process at any time.
 * @param pathsFiles List of file paths to read
 * @throws JSqlException when an error occurs during injection
 * @throws InterruptedException if the current thread was interrupted while waiting
 * @throws ExecutionException if the computation threw an exception
 */
public void readFile(List<ItemList> pathsFiles) throws JSqlException, InterruptedException, ExecutionException {
    if (!MediatorHelper.model().getResourceAccess().isReadingAllowed()) {
        return;
    }
    var countFileFound = 0;
    ExecutorService taskExecutor = Executors.newFixedThreadPool(10, new ThreadFactoryCallable("CallableReadFile"));
    CompletionService<CallableFile> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
    for (ItemList pathFile : pathsFiles) {
        var callableFile = new CallableFile(pathFile.toString(), MediatorHelper.model());
        taskCompletionService.submit(callableFile);
        MediatorHelper.model().getResourceAccess().getCallablesReadFile().add(callableFile);
    }
    List<String> duplicate = new ArrayList<>();
    int submittedTasks = pathsFiles.size();
    int tasksHandled;
    for (tasksHandled = 0; tasksHandled < submittedTasks && !MediatorHelper.model().getResourceAccess().isSearchFileStopped(); tasksHandled++) {
        var currentCallable = taskCompletionService.take().get();
        if (StringUtils.isNotEmpty(currentCallable.getSourceFile())) {
            var name = currentCallable.getPathFile().substring(currentCallable.getPathFile().lastIndexOf('/') + 1, currentCallable.getPathFile().length());
            String content = currentCallable.getSourceFile();
            String path = currentCallable.getPathFile();
            var request = new Request();
            request.setMessage(Interaction.CREATE_FILE_TAB);
            request.setParameters(name, content, path);
            MediatorHelper.model().sendToViews(request);
            if (!duplicate.contains(path.replace(name, StringUtils.EMPTY))) {
                LOGGER.log(LogLevel.CONSOLE_INFORM, "Shell might be possible in folder {}", () -> path.replace(name, StringUtils.EMPTY));
            }
            duplicate.add(path.replace(name, StringUtils.EMPTY));
            countFileFound++;
        }
    }
    // Force ongoing suspendables to stop immediately
    for (CallableFile callableReadFile : MediatorHelper.model().getResourceAccess().getCallablesReadFile()) {
        callableReadFile.getSuspendableReadFile().stop();
    }
    MediatorHelper.model().getResourceAccess().getCallablesReadFile().clear();
    taskExecutor.shutdown();
    taskExecutor.awaitTermination(5, TimeUnit.SECONDS);
    MediatorHelper.model().getResourceAccess().setSearchFileStopped(false);
    var result = String.format("Found %s file%s%s on %s files checked", countFileFound, countFileFound > 1 ? 's' : StringUtils.EMPTY, tasksHandled != submittedTasks ? " of " + tasksHandled + " processed " : StringUtils.EMPTY, submittedTasks);
    if (countFileFound > 0) {
        LOGGER.log(LogLevel.CONSOLE_SUCCESS, result);
    } else {
        LOGGER.log(LogLevel.CONSOLE_ERROR, result);
    }
    var request = new Request();
    request.setMessage(Interaction.END_FILE_SEARCH);
    MediatorHelper.model().sendToViews(request);
}
Also used : CallableFile(com.jsql.model.accessible.CallableFile) ItemList(com.jsql.view.swing.list.ItemList) ExecutorService(java.util.concurrent.ExecutorService) ArrayList(java.util.ArrayList) Request(com.jsql.model.bean.util.Request) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) ThreadFactoryCallable(com.jsql.model.suspendable.callable.ThreadFactoryCallable)

Example 22 with Request

use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.

the class InjectionModel method testStrategies.

/**
 * Find the insertion character, test each strategy, inject metadata and list databases.
 * @param isParamByUser true if mode standard/JSON/full, false if injection point
 * @param isJson true if param contains JSON
 * @param parameter to be tested, null when injection point
 * @return true when successful injection
 * @throws JSqlException when no params' integrity, process stopped by user, or injection failure
 */
// TODO Merge isParamByUser and parameter: isParamByUser = parameter != null
private boolean testStrategies(boolean isParamByUser, boolean isJson, SimpleEntry<String, String> parameter) throws JSqlException {
    // Define insertionCharacter, i.e, -1 in "[..].php?id=-1 union select[..]",
    LOGGER.trace(I18n.valueByKey("LOG_GET_INSERTION_CHARACTER"));
    // Test for params integrity
    String characterInsertionByUser = ParameterUtil.checkParametersFormat(false, isParamByUser, parameter);
    // Force to insertion char otherwise.
    if (parameter != null) {
        String charInsertion = new SuspendableGetCharInsertion().run(characterInsertionByUser, parameter, isJson);
        LOGGER.info(I18n.valueByKey("LOG_USING_INSERTION_CHARACTER") + " [" + charInsertion.replace(InjectionModel.STAR, "") + "]");
    }
    // Fingerprint database
    this.vendor = new SuspendableGetVendor().run();
    // Test each injection strategies: time, blind, error, normal
    StrategyInjection.TIME.instance().checkApplicability();
    StrategyInjection.BLIND.instance().checkApplicability();
    StrategyInjection.ERROR.instance().checkApplicability();
    StrategyInjection.NORMAL.instance().checkApplicability();
    // Choose the most efficient strategy: normal > error > blind > time
    if (StrategyInjection.NORMAL.instance().isApplicable()) {
        StrategyInjection.NORMAL.instance().activateStrategy();
    } else if (StrategyInjection.ERROR.instance().isApplicable()) {
        StrategyInjection.ERROR.instance().activateStrategy();
    } else if (StrategyInjection.BLIND.instance().isApplicable()) {
        StrategyInjection.BLIND.instance().activateStrategy();
    } else if (StrategyInjection.TIME.instance().isApplicable()) {
        StrategyInjection.TIME.instance().activateStrategy();
    } else if (PreferencesUtil.isEvasionEnabled() && this.stepSecurity < 3) {
        // No injection possible, increase evasion level and restart whole process
        this.stepSecurity++;
        LOGGER.warn("Injection failed, testing evasion level " + this.stepSecurity + "...");
        Request request = new Request();
        request.setMessage(Interaction.RESET_STRATEGY_LABEL);
        this.sendToViews(request);
        // sinon perte de insertionCharacter entre 2 injections
        // ConnectionUtil.setQueryString(ConnectionUtil.getQueryString() + this.charInsertion);
        this.beginInjection();
        return false;
    } else {
        throw new InjectionFailureException("No injection found");
    }
    if (!this.isScanning) {
        if (!PreferencesUtil.isNotInjectingMetadata()) {
            DataAccess.getDatabaseInfos();
        }
        DataAccess.listDatabases();
    }
    return true;
}
Also used : SuspendableGetVendor(com.jsql.model.suspendable.SuspendableGetVendor) SuspendableGetCharInsertion(com.jsql.model.suspendable.SuspendableGetCharInsertion) Request(com.jsql.model.bean.util.Request) InjectionFailureException(com.jsql.model.exception.InjectionFailureException)

Example 23 with Request

use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.

the class InjectionModel method testParameters.

/**
 * Verify if injection works for specific Method using 3 modes: standard (last param), injection point
 * and full params injection. Special injections like JSON and SOAP are checked.
 * @param methodInjection currently tested (Query, Request or Header)
 * @param paramsAsString to verify if contains injection point
 * @param params from Query, Request or Header as a list of key/value to be tested for insertion character ;
 * Mode standard: last param, mode injection point: no test, mode full: every params.
 * @return true if injection didn't failed
 * @throws JSqlException when no params' integrity, process stopped by user, or injection failure
 */
public boolean testParameters(MethodInjection methodInjection, String paramsAsString, List<SimpleEntry<String, String>> params) throws JSqlException {
    boolean hasFoundInjection = false;
    // or method is selected by user.
    if (!PreferencesUtil.isCheckingAllParam() && ConnectionUtil.getMethodInjection() != methodInjection) {
        return hasFoundInjection;
    }
    // Force injection method of model to current running method
    ConnectionUtil.setMethodInjection(methodInjection);
    // Default injection: last param tested only and no injection point
    if (!methodInjection.isCheckingAllParam() && !paramsAsString.contains(InjectionModel.STAR)) {
        // Injection point defined on last parameter
        params.stream().reduce((a, b) -> b).ifPresent(e -> e.setValue(e.getValue() + InjectionModel.STAR));
        // Will check param value by user.
        // Notice options 'Inject each URL params' and 'inject JSON' must be checked both
        // for JSON injection of last param
        hasFoundInjection = this.testStrategies(IS_PARAM_BY_USER, !IS_JSON, params.stream().reduce((a, b) -> b).get());
    // Injection by injection point
    } else if (paramsAsString.contains(InjectionModel.STAR)) {
        LOGGER.info("Checking single " + methodInjection.name() + " parameter with injection point at *");
        // Will keep param value as is,
        // Does not test for insertion character (param is null)
        hasFoundInjection = this.testStrategies(!IS_PARAM_BY_USER, !IS_JSON, null);
    // Injection of every params: isCheckingAllParam() == true.
    // Params are tested one by one in two loops:
    // - inner loop erases * from previous param
    // - outer loop adds * to current param
    } else {
        // inner loop will erase mark * otherwise
        for (SimpleEntry<String, String> paramBase : params) {
            // For standard value mark * is simply added to the end of its value.
            for (SimpleEntry<String, String> paramStar : params) {
                if (paramStar == paramBase) {
                    // Will test if current value is a JSON entity
                    Object jsonEntity = null;
                    try {
                        // Test for JSON Object: {...}
                        jsonEntity = new JSONObject(paramStar.getValue());
                    } catch (JSONException exceptionJSONObject) {
                        try {
                            // Test for JSON Array: [...]
                            jsonEntity = new JSONArray(paramStar.getValue());
                        } catch (JSONException exceptionJSONArray) {
                        // Not a JSON entity
                        }
                    }
                    // Define a tree of JSON attributes with path as the key: root.a => value of a
                    List<SimpleEntry<String, String>> attributesJson = JsonUtil.loopThroughJson(jsonEntity, "root", null);
                    // Marks * are erased between each tests.
                    if (PreferencesUtil.isCheckingAllJSONParam() && !attributesJson.isEmpty()) {
                        // Loop through each JSON values
                        for (SimpleEntry<String, String> parentXPath : attributesJson) {
                            // Erase previously defined *
                            JsonUtil.loopThroughJson(jsonEntity, "root", null);
                            // Add * to current parameter's value
                            JsonUtil.loopThroughJson(jsonEntity, "root", parentXPath);
                            // Replace param value by marked one.
                            // paramStar and paramBase are the same object
                            paramStar.setValue(jsonEntity.toString());
                            try {
                                LOGGER.info("Checking JSON " + methodInjection.name() + " parameter " + parentXPath.getKey() + "=" + parentXPath.getValue().replace(InjectionModel.STAR, ""));
                                // Test current JSON value marked with * for injection
                                // Keep original param
                                hasFoundInjection = this.testStrategies(IS_PARAM_BY_USER, IS_JSON, paramBase);
                                // Injection successful
                                break;
                            } catch (JSqlException e) {
                                // Injection failure
                                LOGGER.warn("No " + methodInjection.name() + " injection found for JSON " + methodInjection.name() + " parameter " + parentXPath.getKey() + "=" + parentXPath.getValue().replace(InjectionModel.STAR, ""), e);
                            } finally {
                                // Erase * at the end of each params
                                params.stream().forEach(e -> e.setValue(e.getValue().replaceAll(Pattern.quote(InjectionModel.STAR) + "$", "")));
                                // Erase * from JSON if failure
                                if (!hasFoundInjection) {
                                    paramStar.setValue(paramStar.getValue().replace("*", ""));
                                }
                            }
                        }
                    // Standard non JSON injection
                    } else {
                        // Add * to end of value
                        paramStar.setValue(paramStar.getValue() + InjectionModel.STAR);
                        try {
                            LOGGER.info("Checking " + methodInjection.name() + " parameter " + paramBase.getKey() + "=" + paramBase.getValue().replace(InjectionModel.STAR, ""));
                            // Test current standard value marked with * for injection
                            // Keep original param
                            hasFoundInjection = this.testStrategies(IS_PARAM_BY_USER, !IS_JSON, paramBase);
                            // Injection successful
                            break;
                        } catch (JSqlException e) {
                            // Injection failure
                            LOGGER.warn("No " + methodInjection.name() + " injection found for parameter " + paramBase.getKey() + "=" + paramBase.getValue().replace(InjectionModel.STAR, "") + " (" + e.getMessage() + ")", e);
                        } finally {
                            // Erase * at the end of each params
                            params.stream().forEach(e -> e.setValue(e.getValue().replaceAll(Pattern.quote(InjectionModel.STAR) + "$", "")));
                        }
                    }
                }
            }
            // If injection successful then add * at the end of value
            if (hasFoundInjection) {
                paramBase.setValue(paramBase.getValue().replace("*", "") + "*");
                break;
            }
        }
    }
    return hasFoundInjection;
}
Also used : HttpURLConnection(java.net.HttpURLConnection) LoginException(javax.security.auth.login.LoginException) URL(java.net.URL) ParameterUtil(com.jsql.util.ParameterUtil) SuspendableGetCharInsertion(com.jsql.model.suspendable.SuspendableGetCharInsertion) StringUtils(org.apache.commons.lang3.StringUtils) StrategyInjection(com.jsql.model.injection.strategy.StrategyInjection) Logger(org.apache.log4j.Logger) InjectionFailureException(com.jsql.model.exception.InjectionFailureException) JSONException(org.json.JSONException) Matcher(java.util.regex.Matcher) JSONObject(org.json.JSONObject) DataOutputStream(java.io.DataOutputStream) Document(org.w3c.dom.Document) JsonUtil(com.jsql.model.injection.JsonUtil) Map(java.util.Map) I18n(com.jsql.i18n.I18n) MethodInjection(com.jsql.model.injection.method.MethodInjection) ThreadUtil(com.jsql.util.ThreadUtil) EnumMap(java.util.EnumMap) HeaderUtil(com.jsql.util.HeaderUtil) SuspendableGetVendor(com.jsql.model.suspendable.SuspendableGetVendor) JSqlException(com.jsql.model.exception.JSqlException) GSSException(org.ietf.jgss.GSSException) Interaction(com.jsql.model.bean.util.Interaction) List(java.util.List) Stream(java.util.stream.Stream) Pattern(java.util.regex.Pattern) ShowOnConsole(com.jsql.util.GitUtil.ShowOnConsole) PreferencesUtil(com.jsql.util.PreferencesUtil) Vendor(com.jsql.model.injection.vendor.Vendor) SpnegoHttpURLConnection(net.sourceforge.spnego.SpnegoHttpURLConnection) Header(com.jsql.model.bean.util.Header) Request(com.jsql.model.bean.util.Request) Charset(java.nio.charset.Charset) ConnectionUtil(com.jsql.util.ConnectionUtil) DataAccess(com.jsql.model.accessible.DataAccess) SimpleEntry(java.util.AbstractMap.SimpleEntry) ProxyUtil(com.jsql.util.ProxyUtil) PrivilegedActionException(java.security.PrivilegedActionException) MalformedURLException(java.net.MalformedURLException) Files(java.nio.file.Files) IOException(java.io.IOException) Paths(java.nio.file.Paths) RessourceAccess(com.jsql.model.accessible.RessourceAccess) SoapUtil(com.jsql.model.injection.SoapUtil) StrategyInjectionNormal(com.jsql.model.injection.strategy.StrategyInjectionNormal) JSONArray(org.json.JSONArray) AuthenticationUtil(com.jsql.util.AuthenticationUtil) JSqlException(com.jsql.model.exception.JSqlException) JSONObject(org.json.JSONObject) SimpleEntry(java.util.AbstractMap.SimpleEntry) JSONArray(org.json.JSONArray) JSONException(org.json.JSONException) JSONObject(org.json.JSONObject) List(java.util.List)

Example 24 with Request

use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.

the class DataAccess method listDatabases.

/**
 * Get database names and table counts and send them to the view.<br>
 * Use readable text (not hexa) and parse this pattern:<br>
 * => hh[database name 1]jj[table count]hhgghh[database name 2]jj[table count]hhggh...hi<br>
 * Data window can be cut before the end of the request but the process helps to obtain
 * the rest of the unreachable data. The process can be interrupted by the user (stop/pause).
 * @return list of databases found
 * @throws JSqlException when injection failure or stopped by user
 */
public static List<Database> listDatabases() throws JSqlException {
    LOGGER.trace(I18n.valueByKey("LOG_FETCHING_DATABASES"));
    List<Database> databases = new ArrayList<>();
    String resultToParse = "";
    try {
        String[] sourcePage = { "" };
        resultToParse = new SuspendableGetRows().run(MediatorModel.model().getVendor().instance().sqlDatabases(), sourcePage, true, 0, null);
    } catch (SlidingException e) {
        LOGGER.warn(e.getMessage(), e);
        // Get pieces of data already retreived instead of losing them
        if (!"".equals(e.getSlidingWindowAllRows())) {
            resultToParse = e.getSlidingWindowAllRows();
        } else if (!"".equals(e.getSlidingWindowCurrentRows())) {
            resultToParse = e.getSlidingWindowCurrentRows();
        }
    } catch (Exception e) {
        LOGGER.warn(e.getMessage(), e);
    }
    // Parse all data we have retrieved
    Matcher regexSearch = Pattern.compile(MODE + ENCLOSE_VALUE_RGX + CELL_TABLE + ENCLOSE_VALUE_RGX).matcher(resultToParse);
    if (!regexSearch.find()) {
        throw new InjectionFailureException();
    }
    regexSearch.reset();
    // Build an array of Database objects from the data we have parsed
    while (regexSearch.find()) {
        String databaseName = regexSearch.group(1);
        String tableCount = regexSearch.group(2);
        Database newDatabase = new Database(databaseName, tableCount);
        databases.add(newDatabase);
    }
    Request request = new Request();
    request.setMessage(Interaction.ADD_DATABASES);
    request.setParameters(databases);
    MediatorModel.model().sendToViews(request);
    return databases;
}
Also used : SlidingException(com.jsql.model.exception.SlidingException) SuspendableGetRows(com.jsql.model.suspendable.SuspendableGetRows) Matcher(java.util.regex.Matcher) AbstractElementDatabase(com.jsql.model.bean.database.AbstractElementDatabase) Database(com.jsql.model.bean.database.Database) ArrayList(java.util.ArrayList) Request(com.jsql.model.bean.util.Request) SlidingException(com.jsql.model.exception.SlidingException) IgnoreMessageException(com.jsql.model.exception.IgnoreMessageException) JSqlException(com.jsql.model.exception.JSqlException) InjectionFailureException(com.jsql.model.exception.InjectionFailureException) InjectionFailureException(com.jsql.model.exception.InjectionFailureException)

Example 25 with Request

use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.

the class DataAccess method listTables.

/**
 * Get tables name and row count and send them to the view.<br>
 * Use readable text (not hexa) and parse this pattern:<br>
 * => hh[table name 1]jj[rows count]hhgghh[table name 2]jj[rows count]hhggh...hi<br>
 * Data window can be cut before the end of the request but the process helps to obtain
 * the rest of the unreachable data. The process can be interrupted by the user (stop/pause).
 * @param database which contains tables to find
 * @return list of tables found
 * @throws JSqlException when injection failure or stopped by user
 */
public static List<Table> listTables(Database database) throws JSqlException {
    // Reset stoppedByUser if list of Databases is partial
    // and some Tables are still reachable
    MediatorModel.model().setIsStoppedByUser(false);
    List<Table> tables = new ArrayList<>();
    // Inform the view that database has just been used
    Request requestStartProgress = new Request();
    requestStartProgress.setMessage(Interaction.START_PROGRESS);
    requestStartProgress.setParameters(database);
    MediatorModel.model().sendToViews(requestStartProgress);
    String tableCount = Integer.toString(database.getChildCount());
    String resultToParse = "";
    try {
        String[] pageSource = { "" };
        resultToParse = new SuspendableGetRows().run(MediatorModel.model().getVendor().instance().sqlTables(database), pageSource, true, Integer.parseInt(tableCount), database);
    } catch (SlidingException e) {
        LOGGER.warn(e.getMessage(), e);
        // Get pieces of data already retreived instead of losing them
        if (!"".equals(e.getSlidingWindowAllRows())) {
            resultToParse = e.getSlidingWindowAllRows();
        } else if (!"".equals(e.getSlidingWindowCurrentRows())) {
            resultToParse = e.getSlidingWindowCurrentRows();
        }
    } catch (Exception e) {
        LOGGER.warn(e.getMessage(), e);
    }
    // Parse all the data we have retrieved
    Matcher regexSearch = Pattern.compile(MODE + ENCLOSE_VALUE_RGX + CELL_TABLE + ENCLOSE_VALUE_RGX).matcher(resultToParse);
    Request requestEndProgress = new Request();
    requestEndProgress.setMessage(Interaction.END_PROGRESS);
    requestEndProgress.setParameters(database);
    MediatorModel.model().sendToViews(requestEndProgress);
    if (!regexSearch.find()) {
        throw new InjectionFailureException();
    }
    regexSearch.reset();
    // Build an array of Table objects from the data we have parsed
    while (regexSearch.find()) {
        String tableName = regexSearch.group(1);
        String rowCount = regexSearch.group(2);
        Table newTable = new Table(tableName, rowCount, database);
        tables.add(newTable);
    }
    Request requestAddTables = new Request();
    requestAddTables.setMessage(Interaction.ADD_TABLES);
    requestAddTables.setParameters(tables);
    MediatorModel.model().sendToViews(requestAddTables);
    return tables;
}
Also used : Table(com.jsql.model.bean.database.Table) SlidingException(com.jsql.model.exception.SlidingException) SuspendableGetRows(com.jsql.model.suspendable.SuspendableGetRows) Matcher(java.util.regex.Matcher) ArrayList(java.util.ArrayList) Request(com.jsql.model.bean.util.Request) SlidingException(com.jsql.model.exception.SlidingException) IgnoreMessageException(com.jsql.model.exception.IgnoreMessageException) JSqlException(com.jsql.model.exception.JSqlException) InjectionFailureException(com.jsql.model.exception.InjectionFailureException) InjectionFailureException(com.jsql.model.exception.InjectionFailureException)

Aggregations

Request (com.jsql.model.bean.util.Request)47 ArrayList (java.util.ArrayList)13 Header (com.jsql.model.bean.util.Header)12 EnumMap (java.util.EnumMap)12 ExecutorCompletionService (java.util.concurrent.ExecutorCompletionService)11 ExecutorService (java.util.concurrent.ExecutorService)11 JSqlException (com.jsql.model.exception.JSqlException)10 SuspendableGetRows (com.jsql.model.suspendable.SuspendableGetRows)9 IOException (java.io.IOException)9 ThreadFactoryCallable (com.jsql.model.suspendable.callable.ThreadFactoryCallable)8 ExecutionException (java.util.concurrent.ExecutionException)8 InjectionFailureException (com.jsql.model.exception.InjectionFailureException)7 ItemList (com.jsql.view.swing.list.ItemList)7 MalformedURLException (java.net.MalformedURLException)6 HttpRequest (java.net.http.HttpRequest)6 URL (java.net.URL)5 List (java.util.List)5 Matcher (java.util.regex.Matcher)5 IgnoreMessageException (com.jsql.model.exception.IgnoreMessageException)4 StoppedByUserSlidingException (com.jsql.model.exception.StoppedByUserSlidingException)4