/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright The ZAP Development team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.parosproxy.paros.core.scanner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.parosproxy.paros.network.HttpMalformedHeaderException;
import org.parosproxy.paros.network.HttpMessage;
public class VariantUserDefined implements Variant {
private static Map<String, int[][]> injectionPointMap = new HashMap<String, int[][]>();
private int headerLength;
private int bodyLength;
private int[][] injectionPoints = null;
private static final Logger logger = Logger.getLogger(VariantUserDefined.class);
public VariantUserDefined() {
super();
}
public static void setInjectionPoints(String url, int[][] injectionPoints) {
/*
* Variants are initialised at a fairly low level in the code, which means the higher levels
* cant access them directly.
* However this sort of variant only makes sense under the direct control of the user, hence
* this rather nasty static method which associates user defined injection points with URLs
*/
injectionPointMap.put(url, injectionPoints);
}
@Override
public void setMessage(HttpMessage msg) {
headerLength = msg.getRequestHeader().toString().length();
bodyLength = msg.getRequestBody().toString().length();
String url = msg.getRequestHeader().getURI().toString();
this.injectionPoints = injectionPointMap.get(url);
}
@Override
public List<NameValuePair> getParamList() {
List<NameValuePair> list = new ArrayList<NameValuePair>();
if (this.injectionPoints!= null) {
for (int i=0; i < this.injectionPoints.length; i++) {
if (isInHeader(this.injectionPoints[i]) || isInBody(this.injectionPoints[i]) ) {
list.add(new NameValuePair(NameValuePair.TYPE_UNDEFINED, "", "", i));
} else {
logger.warn("Invalid injection point: " + java.util.Arrays.toString(this.injectionPoints[i]));
}
}
}
return list;
}
@Override
public String setParameter(HttpMessage msg, NameValuePair originalPair, String param, String value) {
int[] injPoint = this.injectionPoints[originalPair.getPosition()];
if (isInHeader(injPoint)) {
String header = msg.getRequestHeader().toString();
StringBuilder sb = new StringBuilder(header.length());
sb.append(header.substring(0, injPoint[0]));
sb.append(value);
sb.append(header.substring(injPoint[1]));
try {
msg.getRequestHeader().setMessage(sb.toString());
} catch (HttpMalformedHeaderException e) {
logger.error(e.getMessage(), e);
}
} else {
String body = msg.getRequestBody().toString();
StringBuilder sb = new StringBuilder(body.length());
sb.append(body.substring(0, injPoint[0] - headerLength));
sb.append(value);
sb.append(body.substring(injPoint[1] - headerLength));
msg.getRequestBody().setBody(sb.toString());
}
return "value";
}
@Override
public String setEscapedParameter(HttpMessage msg, NameValuePair originalPair, String param, String value) {
return this.setParameter(msg, originalPair, param, value);
}
private boolean isInHeader(int[] injPoint) {
return injPoint[0] < headerLength && injPoint[1] < headerLength;
}
private boolean isInBody(int[] injPoint) {
return injPoint[0] > headerLength && injPoint[1] > headerLength &&
injPoint[0] - headerLength < bodyLength && injPoint[1] - headerLength < bodyLength;
}
}