use of com.jsql.model.injection.method.MethodInjection 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;
}
Aggregations