/* * Zed Attack Proxy (ZAP) and its related class files. * * ZAP is an HTTP/HTTPS proxy for assessing web application security. * * Copyright 2016 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.zaproxy.zap.extension.ruleconfig; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.parosproxy.paros.common.AbstractParam; /** * Manages the Rule Configurations saved in the configuration file. * <p> * It also exposes the names of the (core) rules that can be accessed by the scanners (through the {@code Configuration} * set/used by the passive/active scans). * * @since 2.6.0 */ public class RuleConfigParam extends AbstractParam { /** * The name of the rule to obtain the time, in seconds, for time-based attacks. * @see #RULE_DEFAULT_COMMON_SLEEP_TIME */ public static final String RULE_COMMON_SLEEP_TIME = "rules.common.sleep"; /** * The name of the rule to obtain the string containing a comma separated list of names/IDs of forms that should be ignored * when checking for CSRF issues. */ public static final String RULE_CSRF_IGNORE_LIST = "rules.csrf.ignorelist"; /** * The name of an HTML attribute that can be used to indicate that a form does not need an Anti CSRF Token. * If 'rules.csrf.ignore.attvalue' is specified then this must also match the attribute's value. * If found any related alerts will be raised at INFO level. */ public static final String RULE_CSRF_IGNORE_ATT_NAME = "rules.csrf.ignore.attname"; /** * The value of an HTML attribute named by 'rules.csrf.ignore.attname' that can be used to indicate that a form does not need an Anti CSRF Token. * If found any related alerts will be raised at INFO level. */ public static final String RULE_CSRF_IGNORE_ATT_VALUE = "rules.csrf.ignore.attvalue"; /** * The name of the rule to obtain the string containing a comma separated list of cookies that should be ignored * when checking for issues. */ public static final String RULE_COOKIE_IGNORE_LIST = "rules.cookie.ignorelist"; /** * The default time, in seconds, to use for time-based attacks * @see #RULE_COMMON_SLEEP_TIME */ public static final int RULE_DEFAULT_COMMON_SLEEP_TIME = 15; private static final String RULES_BASE_KEY = "rules"; private static final String RULES_DEFAULT_KEY_EXT = ".default"; private Map<String, RuleConfig> ruleConfigs = new HashMap<String, RuleConfig>(); public RuleConfigParam() { } @Override protected void parse() { // Add the built in rule configs this.addRuleConfig(new RuleConfig(RULE_COMMON_SLEEP_TIME, Integer.toString(RULE_DEFAULT_COMMON_SLEEP_TIME))); this.addRuleConfig(new RuleConfig(RULE_CSRF_IGNORE_LIST, "")); this.addRuleConfig(new RuleConfig(RULE_CSRF_IGNORE_ATT_NAME, "")); this.addRuleConfig(new RuleConfig(RULE_CSRF_IGNORE_ATT_VALUE, "")); this.addRuleConfig(new RuleConfig(RULE_COOKIE_IGNORE_LIST, "")); Iterator<String> iter = this.getConfig().getKeys(RULES_BASE_KEY); RuleConfig rc; while (iter.hasNext()) { String key = iter.next(); if (ruleConfigs.containsKey(key)) { ruleConfigs.get(key).setValue(this.getConfig().getString(key)); } else { // Rules can specify an optional default value in the config file rc = new RuleConfig( key, this.getConfig().getString(key + RULES_DEFAULT_KEY_EXT, ""), this.getConfig().getString(key)); this.ruleConfigs.put(rc.getKey(), rc); } } } public void addRuleConfig (RuleConfig rc) { this.ruleConfigs.put(rc.getKey(), rc); if (! this.getConfig().containsKey(rc.getKey())) { // Dont overwrite an existing value this.getConfig().setProperty(rc.getKey(), rc.getValue()); } } public void addRuleConfig (String key, String defaultValue, String value) { this.ruleConfigs.put(key, new RuleConfig(key, defaultValue, value)); if (! this.getConfig().containsKey(key)) { // Dont overwrite an existing value this.getConfig().setProperty(key, value); } } public RuleConfig getRuleConfig (String key) { if (ruleConfigs.containsKey(key)) { return ruleConfigs.get(key).clone(); } return null; } public List<RuleConfig> getAllRuleConfigs () { ArrayList<RuleConfig> list = new ArrayList<RuleConfig>(); for (RuleConfig rc : ruleConfigs.values()) { list.add(rc.clone()); } return list; } public String getRuleConfigValue (String key) { if (ruleConfigs.containsKey(key)) { return ruleConfigs.get(key).getValue(); } return null; } public String getRuleConfigDefaultValue (String key) { if (ruleConfigs.containsKey(key)) { return ruleConfigs.get(key).getDefaultValue(); } return null; } public void setRuleConfigValue(String key, String value) { if (ruleConfigs.containsKey(key)) { ruleConfigs.get(key).setValue(value); this.getConfig().setProperty(key, value); } else { throw new IllegalArgumentException("No such key"); } } public void resetRuleConfigValue(String key) { if (ruleConfigs.containsKey(key)) { String value = ruleConfigs.get(key).getDefaultValue(); ruleConfigs.get(key).setValue(value); this.getConfig().setProperty(key, value); } else { throw new IllegalArgumentException("No such key"); } } public void resetAllRuleConfigValues() { for (RuleConfig rc : ruleConfigs.values()) { rc.reset(); this.getConfig().setProperty(rc.getKey(), rc.getValue()); } } }