use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.
the class RessourceAccess method runSqlShell.
/**
* Execute SQL request into terminal defined by URL path, eventually override with database user/pass identifiers.
* @param command SQL request to execute
* @param uuidShell Identifier of terminal sending the request
* @param urlShell URL to send SQL request against
* @param username User name [optional]
* @param password USEr password [optional]
*/
public static void runSqlShell(String command, UUID uuidShell, String urlShell, String username, String password) {
String result = "";
try {
result = runCommandShell(urlShell + "?q=" + URLEncoder.encode(command.trim(), "ISO-8859-1") + "&u=" + username + "&p=" + password);
if (result.indexOf("<SQLr>") > -1) {
List<List<String>> listRows = new ArrayList<>();
Matcher rowsMatcher = Pattern.compile("(?si)<tr>(<td>.*?</td>)</tr>").matcher(result);
while (rowsMatcher.find()) {
String values = rowsMatcher.group(1);
Matcher fieldsMatcher = Pattern.compile("(?si)<td>(.*?)</td>").matcher(values);
List<String> listFields = new ArrayList<>();
listRows.add(listFields);
while (fieldsMatcher.find()) {
String field = fieldsMatcher.group(1);
listFields.add(field);
}
}
if (!listRows.isEmpty()) {
List<Integer> listFieldsLength = new ArrayList<>();
for (final int[] indexLongestRowSearch = { 0 }; indexLongestRowSearch[0] < listRows.get(0).size(); indexLongestRowSearch[0]++) {
Collections.sort(listRows, (firstRow, secondRow) -> secondRow.get(indexLongestRowSearch[0]).length() - firstRow.get(indexLongestRowSearch[0]).length());
listFieldsLength.add(listRows.get(0).get(indexLongestRowSearch[0]).length());
}
if (!"".equals(result)) {
StringBuilder tableText = new StringBuilder("+");
for (Integer fieldLength : listFieldsLength) {
tableText.append("-" + StringUtils.repeat("-", fieldLength) + "-+");
}
tableText.append("\n");
for (List<String> listFields : listRows) {
tableText.append("|");
int cursorPosition = 0;
for (String field : listFields) {
tableText.append(" " + field + StringUtils.repeat(" ", listFieldsLength.get(cursorPosition) - field.length()) + " |");
cursorPosition++;
}
tableText.append("\n");
}
tableText.append("+");
for (Integer fieldLength : listFieldsLength) {
tableText.append("-" + StringUtils.repeat("-", fieldLength) + "-+");
}
tableText.append("\n");
result = tableText.toString();
}
}
} else if (result.indexOf("<SQLm>") > -1) {
result = result.replace("<SQLm>", "") + "\n";
} else if (result.indexOf("<SQLe>") > -1) {
result = result.replace("<SQLe>", "") + "\n";
}
} catch (UnsupportedEncodingException e) {
LOGGER.warn("Encoding command to ISO-8859-1 failed: " + e.getMessage(), e);
} catch (IOException e) {
LOGGER.warn("Shell execution error: " + e.getMessage(), e);
} finally {
// Unfroze interface
Request request = new Request();
request.setMessage(Interaction.GET_SQL_SHELL_RESULT);
request.setParameters(uuidShell, result, command);
MediatorModel.model().sendToViews(request);
}
}
use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.
the class HeaderUtil method checkResponseHeader.
/**
* Verify the headers received after a request, detect authentication response and
* send the headers to the view.
* @param connection contains headers response
* @param urlByUser the website to request
* @throws IOException when an error occurs during connection
*/
@SuppressWarnings("unchecked")
public static void checkResponseHeader(HttpURLConnection connection, String urlByUser) throws IOException {
// TODO Extract
Map<Header, Object> msgHeader = new EnumMap<>(Header.class);
msgHeader.put(Header.URL, urlByUser);
msgHeader.put(Header.RESPONSE, HeaderUtil.getHttpHeaders(connection));
Map<String, String> mapResponse = (Map<String, String>) msgHeader.get(Header.RESPONSE);
if (Pattern.matches("4\\d\\d", Integer.toString(connection.getResponseCode())) && mapResponse.containsKey("WWW-Authenticate") && mapResponse.get("WWW-Authenticate") != null && mapResponse.get("WWW-Authenticate").startsWith("Basic ")) {
LOGGER.warn("Basic Authentication detected.\n" + "Please define and enable authentication information in the panel Preferences.\n" + "Or open Advanced panel, add 'Authorization: Basic b3N..3Jk' to the Header, replace b3N..3Jk with the string 'osUserName:osPassword' encoded in Base64. You can use the Coder in jSQL to encode the string.");
} else if (Pattern.matches("4\\d\\d", Integer.toString(connection.getResponseCode())) && mapResponse.containsKey("WWW-Authenticate") && "NTLM".equals(mapResponse.get("WWW-Authenticate"))) {
LOGGER.warn("NTLM Authentication detected.\n" + "Please define and enable authentication information in the panel Preferences.\n" + "Or add username, password and domain information to the URL, e.g. http://domain\\user:password@127.0.0.1/[..]");
} else if (Pattern.matches("4\\d\\d", Integer.toString(connection.getResponseCode())) && mapResponse.containsKey("WWW-Authenticate") && mapResponse.get("WWW-Authenticate") != null && mapResponse.get("WWW-Authenticate").startsWith("Digest ")) {
LOGGER.warn("Digest Authentication detected.\n" + "Please define and enable authentication information in the panel Preferences.");
} else if (Pattern.matches("4\\d\\d", Integer.toString(connection.getResponseCode())) && mapResponse.containsKey("WWW-Authenticate") && "Negotiate".equals(mapResponse.get("WWW-Authenticate"))) {
LOGGER.warn("Negotiate Authentication detected.\n" + "Please add username, password and domain information to the URL, e.g. http://domain\\user:password@127.0.0.1/[..]");
} else if (Pattern.matches("1\\d\\d", Integer.toString(connection.getResponseCode()))) {
LOGGER.trace("Found status HTTP " + connection.getResponseCode() + " Informational");
} else if (Pattern.matches("2\\d\\d", Integer.toString(connection.getResponseCode()))) {
LOGGER.debug("Found status HTTP " + connection.getResponseCode() + " Success");
} else if (Pattern.matches("3\\d\\d", Integer.toString(connection.getResponseCode()))) {
LOGGER.warn("Found status HTTP " + connection.getResponseCode() + " Redirection");
if (!PreferencesUtil.isFollowingRedirection()) {
LOGGER.warn("If injection fails please test again with option 'Follow HTTP redirection' enabled.");
} else {
LOGGER.info("Redirecting to the next page...");
}
} else if (Pattern.matches("4\\d\\d", Integer.toString(connection.getResponseCode()))) {
LOGGER.warn("Found status HTTP " + connection.getResponseCode() + " Client Error");
} else if (Pattern.matches("5\\d\\d", Integer.toString(connection.getResponseCode()))) {
LOGGER.warn("Found status HTTP " + connection.getResponseCode() + " Server Error");
} else {
LOGGER.trace("Found status HTTP " + connection.getResponseCode() + " Unknown");
}
// Request the web page to the server
Exception exception = null;
StringBuilder pageSource = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
char[] buffer = new char[4096];
while (reader.read(buffer) > 0) {
pageSource.append(buffer);
}
reader.close();
} catch (IOException errorInputStream) {
exception = errorInputStream;
InputStream errorStream = connection.getErrorStream();
if (errorStream != null) {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(errorStream))) {
char[] buffer = new char[4096];
while (reader.read(buffer) > 0) {
pageSource.append(buffer);
}
reader.close();
} catch (Exception errorErrorStream) {
exception = new IOException("Exception reading Error Stream", errorErrorStream);
}
}
}
if (PreferencesUtil.isNotTestingConnection()) {
if (exception != null) {
LOGGER.debug("Connection test disabled, ignoring response HTTP " + connection.getResponseCode() + "...");
}
exception = null;
} else if (exception != null) {
LOGGER.info("Please select option 'Disable connection test' and run again");
}
// Form parsing;
// TODO Extract
Elements elementsForm = Jsoup.parse(pageSource.toString()).select("form");
StringBuilder result = new StringBuilder();
Map<Element, List<Element>> mapForms = new HashMap<>();
for (Element form : elementsForm) {
mapForms.put(form, new ArrayList<>());
result.append("\n<form action=\"");
result.append(form.attr("action"));
result.append("\" method=\"");
result.append(form.attr("method"));
result.append("\" />");
for (Element input : form.select("input")) {
result.append("\n <input name=\"");
result.append(input.attr("name"));
result.append("\" value=\"");
result.append(input.attr("value"));
result.append("\" />");
mapForms.get(form).add(input);
}
Collections.reverse(mapForms.get(form));
}
if (!elementsForm.isEmpty()) {
if (!PreferencesUtil.isParsingForm()) {
if (connection.getResponseCode() != 200) {
LOGGER.trace("Found " + elementsForm.size() + " ignored <form> in HTML body:" + result);
LOGGER.info("WAF can detect missing form parameters, you may enable 'Add <input> parameters' in Preferences and retry");
} else {
LOGGER.trace("Found " + elementsForm.size() + " <form> in HTML body while status 200 Success:" + result);
}
} else {
LOGGER.debug("Found " + elementsForm.size() + " <form> in HTML body, adding input(s) to requests:" + result);
for (Entry<Element, List<Element>> form : mapForms.entrySet()) {
for (Element input : form.getValue()) {
if ("get".equalsIgnoreCase(form.getKey().attr("method"))) {
ParameterUtil.getQueryString().add(0, new SimpleEntry<String, String>(input.attr("name"), input.attr("value")));
} else if ("post".equalsIgnoreCase(form.getKey().attr("method"))) {
ParameterUtil.getRequest().add(0, new SimpleEntry<String, String>(input.attr("name"), input.attr("value")));
}
}
}
}
}
// Csrf
// TODO Extract
Optional<SimpleEntry<String, String>> optionalTokenCsrf = Jsoup.parse(pageSource.toString()).select("input").select("[name=csrf_token], [name=csrfToken]").stream().findFirst().map(input -> new SimpleEntry<String, String>(input.attr("name"), input.attr("value")));
if (optionalTokenCsrf.isPresent()) {
SimpleEntry<String, String> tokenCsrfFound = optionalTokenCsrf.get();
if (PreferencesUtil.isProcessingCsrf()) {
LOGGER.debug("Found Csrf token " + tokenCsrfFound.getKey() + "=" + tokenCsrfFound.getValue() + " in HTML body, adding token to querystring, request and header");
ConnectionUtil.setTokenCsrf(tokenCsrfFound);
} else {
LOGGER.warn("Found Csrf token '" + tokenCsrfFound.getKey() + "=" + tokenCsrfFound.getValue() + "' in HTML body");
exception = new IOException("please activate Csrf processing in Preferences");
}
}
msgHeader.put(Header.SOURCE, pageSource.toString());
// Inform the view about the log infos
Request request = new Request();
request.setMessage(Interaction.MESSAGE_HEADER);
request.setParameters(msgHeader);
MediatorModel.model().sendToViews(request);
if (exception != null) {
throw new IOException(exception);
}
}
use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.
the class SuspendableGetVendor method run.
/**
*/
@Override
public Vendor run(Object... args) throws StoppedByUserSlidingException {
Vendor vendor = null;
if (MediatorModel.model().getVendorByUser() != Vendor.AUTO) {
vendor = MediatorModel.model().getVendorByUser();
LOGGER.info(I18n.valueByKey("LOG_DATABASE_TYPE_FORCED_BY_USER") + " [" + vendor + "]");
} else {
// 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("CallableGetVendor"));
CompletionService<CallablePageSource> taskCompletionService = new ExecutorCompletionService<>(taskExecutor);
for (String insertionCharacter : new String[] { "'\"#-)'\"" }) {
taskCompletionService.submit(new CallablePageSource(insertionCharacter, insertionCharacter));
}
int total = 1;
while (0 < total) {
if (this.isSuspended()) {
throw new StoppedByUserSlidingException();
}
try {
CallablePageSource currentCallable = taskCompletionService.take().get();
total--;
String pageSource = currentCallable.getContent();
for (Vendor vendorTest : Stream.of(Vendor.values()).skip(1).toArray(Vendor[]::new)) {
if (pageSource.matches("(?si).*(" + vendorTest.instance().fingerprintErrorsAsRegex() + ").*")) {
vendor = vendorTest;
LOGGER.debug("Found database [" + vendor + "]");
break;
}
}
} catch (InterruptedException | ExecutionException e) {
LOGGER.error("Interruption while determining the type of database", e);
}
}
// End the job
try {
taskExecutor.shutdown();
taskExecutor.awaitTermination(15, TimeUnit.SECONDS);
} catch (InterruptedException e) {
LOGGER.error(e.getMessage(), e);
Thread.currentThread().interrupt();
}
if (vendor == null) {
vendor = Vendor.MYSQL;
LOGGER.warn(I18n.valueByKey("LOG_DATABASE_TYPE_NOT_FOUND") + " [" + vendor + "]");
} else {
LOGGER.info(I18n.valueByKey("LOG_USING_DATABASE_TYPE") + " [" + vendor + "]");
Map<Header, Object> msgHeader = new EnumMap<>(Header.class);
msgHeader.put(Header.URL, ConnectionUtil.getUrlBase() + ParameterUtil.getQueryStringAsString());
msgHeader.put(Header.VENDOR, vendor);
Request requestDatabaseIdentified = new Request();
requestDatabaseIdentified.setMessage(Interaction.DATABASE_IDENTIFIED);
requestDatabaseIdentified.setParameters(msgHeader);
MediatorModel.model().sendToViews(requestDatabaseIdentified);
}
}
Request requestSetVendor = new Request();
requestSetVendor.setMessage(Interaction.SET_VENDOR);
requestSetVendor.setParameters(vendor);
MediatorModel.model().sendToViews(requestSetVendor);
return vendor;
}
use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.
the class AbstractStrategy method markInvulnerable.
public void markInvulnerable(Interaction message, int i) {
Request request = new Request();
request.setMessage(message);
Map<Header, Object> msgHeader = new EnumMap<>(Header.class);
msgHeader.put(Header.SOURCE, i);
request.setParameters(msgHeader);
MediatorModel.model().sendToViews(request);
}
use of com.jsql.model.bean.util.Request in project jsql-injection by ron190.
the class StrategyInjectionBlind method activateStrategy.
@Override
public void activateStrategy() {
LOGGER.info(I18n.valueByKey("LOG_USING_STRATEGY") + " [" + this.getName() + "]");
MediatorModel.model().setStrategy(StrategyInjection.BLIND);
Request requestMarkBlindStrategy = new Request();
requestMarkBlindStrategy.setMessage(Interaction.MARK_BLIND_STRATEGY);
MediatorModel.model().sendToViews(requestMarkBlindStrategy);
}
Aggregations