Merge remote-tracking branch 'origin/master'

This commit is contained in:
dushitaoyuan
2019-11-02 23:15:31 +08:00
34 changed files with 1752 additions and 21 deletions

View File

@@ -53,3 +53,6 @@
## esapi 介绍
此jar包为一个比较全面的安全库,控制较为全面,业务较为复杂的可自行扩展

View File

@@ -82,11 +82,16 @@
<version>4.0.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- java web防控包-->
<dependency>
<groupId>org.owasp.esapi</groupId>
<artifactId>esapi</artifactId>
<version>2.2.0.0</version>
</dependency>
</dependencies>
<build>

View File

@@ -17,6 +17,9 @@ public class ServiceException extends RuntimeException {
super(msg);
this.errorCode=errorCode;
}
public Integer getErrorCode(){
return getErrorCode();
}
}

View File

@@ -9,6 +9,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
@@ -27,11 +28,11 @@ public class SystemExceptionHandler implements HandlerExceptionResolver {
public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception e) {
if (isJson(request)) {
if (isJson(request, handler)) {
doHandleException(request, response, handler, e);
return new ModelAndView();
} else {
ModelAndView modelAndView=new ModelAndView();
ModelAndView modelAndView = new ModelAndView();
//todo跳转到页面
return modelAndView;
@@ -43,10 +44,12 @@ public class SystemExceptionHandler implements HandlerExceptionResolver {
Throwable e) {
Result result = null;
HttpStatus httpStatus = HttpStatus.OK;
if (e instanceof ValidatorException) {//参数异常
if (e instanceof ValidatorException) {
//参数异常
result = ResultBuilder.failed(ResultCode.PARAM_ERROR.code, e.getMessage());
} else if (e instanceof ServiceException) {
result = ResultBuilder.failed(ResultCode.BUSSINESS_ERROR.code, e.getMessage());
ServiceException exception = (ServiceException) e;
result = ResultBuilder.failed(exception.getErrorCode(), e.getMessage());
} else if (e instanceof UnAuthException) {
httpStatus = HttpStatus.UNAUTHORIZED;
result = ResultBuilder.failed(ResultCode.UNAUTHORIZED.code, e.getMessage());
@@ -59,11 +62,13 @@ public class SystemExceptionHandler implements HandlerExceptionResolver {
} else if (e instanceof JSONException) {
result = ResultBuilder.failed(ResultCode.PARAM_ERROR.code, "参数异常,json格式非法:" + e.getMessage());
} else if (e instanceof ServletException) {
httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
result = ResultBuilder.failed(e.getMessage());
} else if (e instanceof NoHandlerFoundException) {
httpStatus = HttpStatus.NOT_FOUND;
result = ResultBuilder.failed(ResultCode.NOT_FOUND.code, "接口 [" + ((NoHandlerFoundException) e).getRequestURL() + "] 不存在");
} else {
httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
result = ResultBuilder.failed(ResultCode.INTERNAL_SERVER_ERROR.code, "接口 [" + request.getRequestURI() + "] 内部错误,请联系管理员");
if (handler != null && handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
@@ -78,10 +83,16 @@ public class SystemExceptionHandler implements HandlerExceptionResolver {
}
public static boolean isJson(HttpServletRequest request) {
public static boolean isJson(HttpServletRequest request, Object handler) {
if (handler != null && handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
if (handlerMethod.hasMethodAnnotation(ResponseBody.class)) {
return true;
}
}
String contentType = request.getHeader("Content-Type");
String accept = request.getHeader("Accept");
if ((accept != null && accept.contains("json"))||(contentType != null && contentType.contains("json"))) {
if ((accept != null && accept.contains("json")) || (contentType != null && contentType.contains("json"))) {
return true;
} else {
return false;

View File

@@ -63,7 +63,7 @@ public class RateLimitAspect {
if (type == null) {
key = methodName;
if (LOG.isDebugEnabled()) {
LOG.debug("限流策略未定义,采用[]限流策略", methodName, RateLimitType.METHOD);
LOG.debug("{}限流策略未定义,采用[{}]限流策略", methodName, RateLimitType.METHOD);
}
} else {
switch (type) {
@@ -79,7 +79,6 @@ public class RateLimitAspect {
key = methodName;
break;
case SERVICE_KEY:
break;
case GLOBAL:
key = "global";
@@ -91,7 +90,7 @@ public class RateLimitAspect {
}
if (type.equals(RateLimitType.TOTAL_COUNT)) {
if (!rateLimiter.tryCount(1, key, rateLimit.totalCount())) {
throw new LimitException("访问数已达最大限制:" + rateLimit.totalCount() + ",请稍后再试");
throw new LimitException("访问数已达最大限制:" + rateLimit.totalCount() + ",请稍后再试");
}
} else {
if (!rateLimiter.tryAcquire(key, rateLimit.limit())) {

View File

@@ -8,8 +8,8 @@ package com.taoyuanx.securitydemo.security;
public enum RateLimitType {
IP(0, "IP限流"), METHOD(1, "方法名"),
SERVICE_KEY(3, "业务自定义key"),
GLOBAL(4,"系统全局"),
TOTAL_COUNT(5,"总次数限制");
GLOBAL(4, "系统全局"),
TOTAL_COUNT(5, "总次数限制");
private int code;
private String desc;
@@ -29,7 +29,6 @@ public enum RateLimitType {
return METHOD;
case 3:
return SERVICE_KEY;
case 4:
return GLOBAL;
case 5:

View File

@@ -19,7 +19,8 @@ public abstract class AbstractRateLimiter {
public boolean tryAcquire(String key, Double limit){
return doTryAcquire(1,key,limit);
}
protected abstract boolean doTryAcquire(int permits, String key, Double limit);
public abstract boolean doTryAcquire(int permits, String key, Double limit);
/**
* 增加资源访问次数 用户可自行持久化记录

View File

@@ -24,7 +24,7 @@ public class GuavaRateLimiter extends AbstractRateLimiter {
*/
private BloomFilter<CharSequence> TOTAL_LIMIT_ZERO_FLAG = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), MAX_HOLDER_SIZE * 20);
protected boolean doTryAcquire(int permits, String key, Double limit) {
public boolean doTryAcquire(int permits, String key, Double limit) {
//超过固定阈值,清空,重构
if (rateHolder.size() > MAX_HOLDER_SIZE) {
rateHolder.clear();

View File

@@ -1,6 +1,5 @@
package com.taoyuanx.securitydemo.security.ratelimit;
import com.sun.org.apache.xml.internal.utils.StringToIntTable;
import com.taoyuanx.securitydemo.utils.StringIntUtil;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -38,7 +37,7 @@ public class RedisRateLimiter extends AbstractRateLimiter {
}
@Override
protected boolean doTryAcquire(int permits, String key, Double limit) {
public boolean doTryAcquire(int permits, String key, Double limit) {
String[] scriptArgs = {limit.longValue() + "", limit.longValue() + "", Instant.now().getEpochSecond() + "", permits + ""};
List<Long> results = redisTemplate.execute(this.tokenScript, getKeys(key), scriptArgs);
return results.get(0) == 1L;
@@ -47,9 +46,8 @@ public class RedisRateLimiter extends AbstractRateLimiter {
@Override
public boolean tryCount(int count, String key, Long totalCount) {
String[] scriptArgs = {count + "", totalCount + "", StringIntUtil.toInt(key) +""};
Long result = redisTemplate.execute(this.countScript, Arrays.asList(key,"zero_flag"), scriptArgs);
String[] scriptArgs = {count + "", totalCount + "", StringIntUtil.toInt(key) + ""};
Long result = redisTemplate.execute(this.countScript, Arrays.asList(key, "zero_flag"), scriptArgs);
return result >= 0;
}

View File

@@ -0,0 +1,73 @@
package com.taoyuanx.securitydemo;
import org.junit.Test;
import org.owasp.esapi.Authenticator;
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.User;
import org.owasp.esapi.codecs.MySQLCodec;
import org.owasp.esapi.errors.AuthenticationException;
import org.owasp.esapi.errors.ValidationException;
import java.util.Set;
/**
* @author dushitaoyuan
* @desc esapi 测试
* @date 2019/9/29
* <p>
* esapi开源地址:https://github.com/ESAPI/esapi-java-legacy 可惜文档较少,不过代码不难理解
* <p>
* api较多,可以参考example使用
*/
public class EsapiTest {
@Test
public void userTest() throws AuthenticationException {
Authenticator instance = ESAPI.authenticator();
String password = instance.generateStrongPassword();
String u = "uuu1";
User user = null;
if (!instance.exists(u)) {
user = instance.createUser(u, password, password);
}
user = instance.getUser(u);
user.addRole("role1");
Set<String> roles = user.getRoles();
}
@Test
public void scriptTest() throws AuthenticationException {
/**
* 转义javascript
*/
String safe = ESAPI.encoder().encodeForJavaScript("<script>alert(1111)</script>");
System.out.println(safe);
safe = ESAPI.encoder().encodeForSQL(new MySQLCodec(MySQLCodec.Mode.STANDARD), "'1' or 1");
System.out.println(safe);
/**
* 转义sql
*/
safe = ESAPI.encoder().encodeForSQL(new MySQLCodec(MySQLCodec.Mode.STANDARD), "'1' or 1");
System.out.println(safe);
}
/**
* 参数校验
* @throws AuthenticationException
* @throws ValidationException
*/
@Test
public void validationTest() throws AuthenticationException, ValidationException {
System.out.println(ESAPI.validator().isValidInput(
"email", "12345", "Email",
200, false));
System.out.println(ESAPI.validator().isValidInput(
"email", "192.168.10.1", "IPAddress",
200, false));
}
}

View File

@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<AccessControlPolicy>
<AccessControlRules>
<AccessControlRule
name="AlwaysTrue"
description="Access is always granted"
class="org.owasp.esapi.reference.accesscontrol.AlwaysTrueACR">
</AccessControlRule>
<AccessControlRule
name="AlwaysFalse"
description="Access is always denied"
class="org.owasp.esapi.reference.accesscontrol.AlwaysFalseACR">
</AccessControlRule>
<AccessControlRule
name="EchoRuntimeParameter"
description="Access depends on the value of the runtime parameter"
class="org.owasp.esapi.reference.accesscontrol.EchoRuntimeParameterACR">
</AccessControlRule>
<AccessControlRule
name="EchoPolicyParameter"
description="Access depends on the value of the policy parameter: isTrue"
class="org.owasp.esapi.reference.accesscontrol.policyloader.EchoDynaBeanPolicyParameterACR">
<Parameters>
<Parameter name="isTrue" type="Boolean" value="true"/>
</Parameters>
</AccessControlRule>
<!--
The following Rules are for backwards compatibility with
the deprecated AcessController 1.0 reference implementation
specification
-->
<AccessControlRule
name="AC 1.0 Data"
description="See delegateClass's code comments"
class="org.owasp.esapi.reference.accesscontrol.DelegatingACR">
<Parameters>
<Parameter name="delegateClass" type="String" value="org.owasp.esapi.reference.accesscontrol.FileBasedACRs"/>
<Parameter name="delegateMethod" type="String" value="isAuthorizedForData"/>
<Parameter name="parameterClasses" type="StringArray" value="java.lang.String, java.lang.Object"/>
</Parameters>
</AccessControlRule>
<AccessControlRule
name="AC 1.0 File"
description="See delegateClass's code comments"
class="org.owasp.esapi.reference.accesscontrol.DelegatingACR">
<Parameters>
<Parameter name="delegateClass" type="String" value="org.owasp.esapi.reference.accesscontrol.FileBasedACRs"/>
<Parameter name="delegateMethod" type="String" value="isAuthorizedForFile"/>
<Parameter name="parameterClasses" type="StringArray" value="java.lang.String"/>
</Parameters>
</AccessControlRule>
<AccessControlRule
name="AC 1.0 Function"
description="See delegateClass's code comments"
class="org.owasp.esapi.reference.accesscontrol.DelegatingACR">
<Parameters>
<Parameter name="delegateClass" type="String" value="org.owasp.esapi.reference.accesscontrol.FileBasedACRs"/>
<Parameter name="delegateMethod" type="String" value="isAuthorizedForFunction"/>
<Parameter name="parameterClasses" type="StringArray" value="java.lang.String"/>
</Parameters>
</AccessControlRule>
<AccessControlRule
name="AC 1.0 Service"
description="See delegateClass's code comments"
class="org.owasp.esapi.reference.accesscontrol.DelegatingACR">
<Parameters>
<Parameter name="delegateClass" type="String" value="org.owasp.esapi.reference.accesscontrol.FileBasedACRs"/>
<Parameter name="delegateMethod" type="String" value="isAuthorizedForService"/>
<Parameter name="parameterClasses" type="StringArray" value="java.lang.String"/>
</Parameters>
</AccessControlRule>
<AccessControlRule
name="AC 1.0 URL"
description="See delegateClass's code comments"
class="org.owasp.esapi.reference.accesscontrol.DelegatingACR">
<Parameters>
<Parameter name="delegateClass" type="String" value="org.owasp.esapi.reference.accesscontrol.FileBasedACRs"/>
<Parameter name="delegateMethod" type="String" value="isAuthorizedForURL"/>
<Parameter name="parameterClasses" type="StringArray" value="java.lang.String"/>
</Parameters>
</AccessControlRule>
<!-- End Rules for backwards compatibility with Access Controller 1.0 -->
</AccessControlRules>
</AccessControlPolicy>
<!--
We have these as runtime tests, but not as policy file load tests yet.
<AccessControlRule
name="EchoRuntimeParameterClassCastException"
description="Access depends on the value of the runtime parameter"
class="org.owasp.esapi.reference.accesscontrol.EchoPolicyParameterACR">
<Parameters>
<Parameter name="isTrue" type="Boolean" value="This is not a boolean"/>
</Parameters>
</AccessControlRule>
<AccessControlRule
name="EchoRuntimeParameterValueNull"
description="Access depends on the value of the runtime parameter"
class="org.owasp.esapi.reference.accesscontrol.EchoPolicyParameterACR">
<Parameters>
<Parameter name="isTrue" type="Boolean" value="null"/>
</Parameters>
</AccessControlRule>
<AccessControlRule
name="EchoRuntimeParameterValueEmpty"
description="Access depends on the value of the runtime parameter"
class="org.owasp.esapi.reference.accesscontrol.EchoPolicyParameterACR">
<Parameters>
<Parameter name="isTrue" type="Boolean" value=""/>
</Parameters>
</AccessControlRule>
<AccessControlRule
name="EchoRuntimeParameterValueMissing"
description="Access depends on the value of the runtime parameter"
class="org.owasp.esapi.reference.accesscontrol.EchoPolicyParameterACR">
<Parameters>
<Parameter name="isTrue" type="Boolean"/>
</Parameters>
</AccessControlRule>
-->
<!-- we should add tests for name and type errors too -->

View File

@@ -0,0 +1,497 @@
#
# OWASP Enterprise Security API (ESAPI) Properties file -- PRODUCTION Version
#
# This file is part of the Open Web Application Security Project (OWASP)
# Enterprise Security API (ESAPI) project. For details, please see
# http://www.owasp.org/index.php/ESAPI.
#
# Copyright (c) 2008,2009 - The OWASP Foundation
#
# DISCUSS: This may cause a major backwards compatibility issue, etc. but
# from a name space perspective, we probably should have prefaced
# all the property names with ESAPI or at least OWASP. Otherwise
# there could be problems is someone loads this properties file into
# the System properties. We could also put this file into the
# esapi.jar file (perhaps as a ResourceBundle) and then allow an external
# ESAPI properties be defined that would overwrite these defaults.
# That keeps the application's properties relatively simple as usually
# they will only want to override a few properties. If looks like we
# already support multiple override levels of this in the
# DefaultSecurityConfiguration class, but I'm suggesting placing the
# defaults in the esapi.jar itself. That way, if the jar is signed,
# we could detect if those properties had been tampered with. (The
# code to check the jar signatures is pretty simple... maybe 70-90 LOC,
# but off course there is an execution penalty (similar to the way
# that the separate sunjce.jar used to be when a class from it was
# first loaded). Thoughts?
###############################################################################
#
# WARNING: Operating system protection should be used to lock down the .esapi
# resources directory and all the files inside and all the directories all the
# way up to the root directory of the file system. Note that if you are using
# file-based implementations, that some files may need to be read-write as they
# get updated dynamically.
#
#===========================================================================
# ESAPI Configuration
#
# If true, then print all the ESAPI properties set here when they are loaded.
# If false, they are not printed. Useful to reduce output when running JUnit tests.
# If you need to troubleshoot a properties related problem, turning this on may help.
# This is 'false' in the src/test/resources/.esapi version. It is 'true' by
# default for reasons of backward compatibility with earlier ESAPI versions.
ESAPI.printProperties=true
# ESAPI is designed to be easily extensible. You can use the reference implementation
# or implement your own providers to take advantage of your enterprise's security
# infrastructure. The functions in ESAPI are referenced using the ESAPI locator, like:
#
# String ciphertext =
# ESAPI.encryptor().encrypt("Secret message"); // Deprecated in 2.0
# CipherText cipherText =
# ESAPI.encryptor().encrypt(new PlainText("Secret message")); // Preferred
#
# Below you can specify the classname for the provider that you wish to use in your
# application. The only requirement is that it implement the appropriate ESAPI interface.
# This allows you to switch security implementations in the future without rewriting the
# entire application.
#
# ExperimentalAccessController requires ESAPI-AccessControlPolicy.xml in .esapi directory
ESAPI.AccessControl=org.owasp.esapi.reference.DefaultAccessController
# FileBasedAuthenticator requires users.txt file in .esapi directory
ESAPI.Authenticator=org.owasp.esapi.reference.FileBasedAuthenticator
ESAPI.Encoder=org.owasp.esapi.reference.DefaultEncoder
ESAPI.Encryptor=org.owasp.esapi.reference.crypto.JavaEncryptor
ESAPI.Executor=org.owasp.esapi.reference.DefaultExecutor
ESAPI.HTTPUtilities=org.owasp.esapi.reference.DefaultHTTPUtilities
ESAPI.IntrusionDetector=org.owasp.esapi.reference.DefaultIntrusionDetector
# Log4JFactory Requires log4j.xml or log4j.properties in classpath - http://www.laliluna.de/log4j-tutorial.html
#ESAPI.Logger=org.owasp.esapi.reference.Log4JLogFactory
ESAPI.Logger=org.owasp.esapi.reference.JavaLogFactory
# To use the new SLF4J logger in ESAPI (see GitHub issue #129), set
# ESAPI.Logger=org.owasp.esapi.logging.slf4j.Slf4JLogFactory
# and do whatever other normal SLF4J configuration that you normally would do for your application.
ESAPI.Randomizer=org.owasp.esapi.reference.DefaultRandomizer
ESAPI.Validator=org.owasp.esapi.reference.DefaultValidator
#===========================================================================
# ESAPI Authenticator
#
Authenticator.AllowedLoginAttempts=3
Authenticator.MaxOldPasswordHashes=13
Authenticator.UsernameParameterName=username
Authenticator.PasswordParameterName=password
# RememberTokenDuration (in days)
Authenticator.RememberTokenDuration=14
# Session Timeouts (in minutes)
Authenticator.IdleTimeoutDuration=20
Authenticator.AbsoluteTimeoutDuration=120
#===========================================================================
# ESAPI Encoder
#
# ESAPI canonicalizes input before validation to prevent bypassing filters with encoded attacks.
# Failure to canonicalize input is a very common mistake when implementing validation schemes.
# Canonicalization is automatic when using the ESAPI Validator, but you can also use the
# following code to canonicalize data.
#
# ESAPI.Encoder().canonicalize( "%22hello world&#x22;" );
#
# Multiple encoding is when a single encoding format is applied multiple times. Allowing
# multiple encoding is strongly discouraged.
Encoder.AllowMultipleEncoding=false
# Mixed encoding is when multiple different encoding formats are applied, or when
# multiple formats are nested. Allowing multiple encoding is strongly discouraged.
Encoder.AllowMixedEncoding=false
# The default list of codecs to apply when canonicalizing untrusted data. The list should include the codecs
# for all downstream interpreters or decoders. For example, if the data is likely to end up in a URL, HTML, or
# inside JavaScript, then the list of codecs below is appropriate. The order of the list is not terribly important.
Encoder.DefaultCodecList=HTMLEntityCodec,PercentCodec,JavaScriptCodec
#===========================================================================
# ESAPI Encryption
#
# The ESAPI Encryptor provides basic cryptographic functions with a simplified API.
# To get started, generate a new key using java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
# There is not currently any support for key rotation, so be careful when changing your key and salt as it
# will invalidate all signed, encrypted, and hashed data.
#
# WARNING: Not all combinations of algorithms and key lengths are supported.
# If you choose to use a key length greater than 128, you MUST download the
# unlimited strength policy files and install in the lib directory of your JRE/JDK.
# See http://java.sun.com/javase/downloads/index.jsp for more information.
#
# ***** IMPORTANT: Do NOT forget to replace these with your own values! *****
# To calculate these values, you can run:
# java -classpath esapi.jar org.owasp.esapi.reference.crypto.JavaEncryptor
#
Encryptor.MasterKey=12345678123456
Encryptor.MasterSalt=123456781234567845678911
# Provides the default JCE provider that ESAPI will "prefer" for its symmetric
# encryption and hashing. (That is it will look to this provider first, but it
# will defer to other providers if the requested algorithm is not implemented
# by this provider.) If left unset, ESAPI will just use your Java VM's current
# preferred JCE provider, which is generally set in the file
# "$JAVA_HOME/jre/lib/security/java.security".
#
# The main intent of this is to allow ESAPI symmetric encryption to be
# used with a FIPS 140-2 compliant crypto-module. For details, see the section
# "Using ESAPI Symmetric Encryption with FIPS 140-2 Cryptographic Modules" in
# the ESAPI 2.0 Symmetric Encryption User Guide, at:
# http://owasp-esapi-java.googlecode.com/svn/trunk/documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html
# However, this property also allows you to easily use an alternate JCE provider
# such as "Bouncy Castle" without having to make changes to "java.security".
# See Javadoc for SecurityProviderLoader for further details. If you wish to use
# a provider that is not known to SecurityProviderLoader, you may specify the
# fully-qualified class name of the JCE provider class that implements
# java.security.Provider. If the name contains a '.', this is interpreted as
# a fully-qualified class name that implements java.security.Provider.
#
# NOTE: Setting this property has the side-effect of changing it in your application
# as well, so if you are using JCE in your application directly rather than
# through ESAPI (you wouldn't do that, would you? ;-), it will change the
# preferred JCE provider there as well.
#
# Default: Keeps the JCE provider set to whatever JVM sets it to.
Encryptor.PreferredJCEProvider=
# AES is the most widely used and strongest encryption algorithm. This
# should agree with your Encryptor.CipherTransformation property.
# Warning: This property does not control the default reference implementation for
# ESAPI 2.0 using JavaEncryptor. Also, this property will be dropped
# in the future.
# @deprecated
Encryptor.EncryptionAlgorithm=AES
# For ESAPI Java 2.0 - New encrypt / decrypt methods use this.
Encryptor.CipherTransformation=AES/CBC/PKCS5Padding
# Applies to ESAPI 2.0 and later only!
# Comma-separated list of cipher modes that provide *BOTH*
# confidentiality *AND* message authenticity. (NIST refers to such cipher
# modes as "combined modes" so that's what we shall call them.) If any of these
# cipher modes are used then no MAC is calculated and stored
# in the CipherText upon encryption. Likewise, if one of these
# cipher modes is used with decryption, no attempt will be made
# to validate the MAC contained in the CipherText object regardless
# of whether it contains one or not. Since the expectation is that
# these cipher modes support support message authenticity already,
# injecting a MAC in the CipherText object would be at best redundant.
#
# Note that as of JDK 1.5, the SunJCE provider does not support *any*
# of these cipher modes. Of these listed, only GCM and CCM are currently
# NIST approved. YMMV for other JCE providers. E.g., Bouncy Castle supports
# GCM and CCM with "NoPadding" mode, but not with "PKCS5Padding" or other
# padding modes.
Encryptor.cipher_modes.combined_modes=GCM,CCM,IAPM,EAX,OCB,CWC
# Applies to ESAPI 2.0 and later only!
# Additional cipher modes allowed for ESAPI 2.0 encryption. These
# cipher modes are in _addition_ to those specified by the property
# 'Encryptor.cipher_modes.combined_modes'.
# Note: We will add support for streaming modes like CFB & OFB once
# we add support for 'specified' to the property 'Encryptor.ChooseIVMethod'
# (probably in ESAPI 2.1).
# DISCUSS: Better name?
Encryptor.cipher_modes.additional_allowed=CBC
# Default key size to use for cipher specified by Encryptor.EncryptionAlgorithm.
# Note that this MUST be a valid key size for the algorithm being used
# (as specified by Encryptor.EncryptionAlgorithm). So for example, if AES is used,
# it must be 128, 192, or 256. If DESede is chosen, then it must be either 112 or 168.
#
# Note that 128-bits is almost always sufficient and for AES it appears to be more
# somewhat more resistant to related key attacks than is 256-bit AES.)
#
# Defaults to 128-bits if left blank.
#
# NOTE: If you use a key size > 128-bits, then you MUST have the JCE Unlimited
# Strength Jurisdiction Policy files installed!!!
#
Encryptor.EncryptionKeyLength=128
# This is the _minimum_ key size (in bits) that we allow with ANY symmetric
# cipher for doing encryption. (There is no minimum for decryption.)
#
# Generally, if you only use one algorithm, this should be set the same as
# the Encryptor.EncryptionKeyLength property.
Encryptor.MinEncryptionKeyLength=128
# Because 2.x uses CBC mode by default, it requires an initialization vector (IV).
# (All cipher modes except ECB require an IV.) There are two choices: we can either
# use a fixed IV known to both parties or allow ESAPI to choose a random IV. While
# the IV does not need to be hidden from adversaries, it is important that the
# adversary not be allowed to choose it. Also, random IVs are generally much more
# secure than fixed IVs. (In fact, it is essential that feed-back cipher modes
# such as CFB and OFB use a different IV for each encryption with a given key so
# in such cases, random IVs are much preferred. By default, ESAPI 2.0 uses random
# IVs. If you wish to use 'fixed' IVs, set 'Encryptor.ChooseIVMethod=fixed' and
# uncomment the Encryptor.fixedIV.
#
# Valid values: random|fixed|specified 'specified' not yet implemented; planned for 2.3
# 'fixed' is deprecated as of 2.2
# and will be removed in 2.3.
Encryptor.ChooseIVMethod=random
# If you choose to use a fixed IV, then you must place a fixed IV here that
# is known to all others who are sharing your secret key. The format should
# be a hex string that is the same length as the cipher block size for the
# cipher algorithm that you are using. The following is an *example* for AES
# from an AES test vector for AES-128/CBC as described in:
# NIST Special Publication 800-38A (2001 Edition)
# "Recommendation for Block Cipher Modes of Operation".
# (Note that the block size for AES is 16 bytes == 128 bits.)
#
# @Deprecated -- fixed IVs are deprecated as of the 2.2 release and support
# will be removed in the next release (tentatively, 2.3).
# If you MUST use this, at least replace this IV with one
# that your legacy application was using.
Encryptor.fixedIV=0x000102030405060708090a0b0c0d0e0f
# Whether or not CipherText should use a message authentication code (MAC) with it.
# This prevents an adversary from altering the IV as well as allowing a more
# fool-proof way of determining the decryption failed because of an incorrect
# key being supplied. This refers to the "separate" MAC calculated and stored
# in CipherText, not part of any MAC that is calculated as a result of a
# "combined mode" cipher mode.
#
# If you are using ESAPI with a FIPS 140-2 cryptographic module, you *must* also
# set this property to false. That is because ESAPI takes the master key and
# derives 2 keys from it--a key for the MAC and a key for encryption--and
# because ESAPI is not itself FIPS 140-2 verified such intermediary aterations
# to keys from FIPS approved sources would have the effect of making your FIPS
# approved key generation and thus your FIPS approved JCE provider unapproved!
# More details in
# documentation/esapi4java-core-2.0-readme-crypto-changes.html
# documentation/esapi4java-core-2.0-symmetric-crypto-user-guide.html
# You have been warned.
Encryptor.CipherText.useMAC=true
# Whether or not the PlainText object may be overwritten and then marked
# eligible for garbage collection. If not set, this is still treated as 'true'.
Encryptor.PlainText.overwrite=true
# Do not use DES except in a legacy situations. 56-bit is way too small key size.
#Encryptor.EncryptionKeyLength=56
#Encryptor.MinEncryptionKeyLength=56
#Encryptor.EncryptionAlgorithm=DES
# TripleDES is considered strong enough for most purposes.
# Note: There is also a 112-bit version of DESede. Using the 168-bit version
# requires downloading the special jurisdiction policy from Sun.
#Encryptor.EncryptionKeyLength=168
#Encryptor.MinEncryptionKeyLength=112
#Encryptor.EncryptionAlgorithm=DESede
Encryptor.HashAlgorithm=SHA-512
Encryptor.HashIterations=1024
Encryptor.DigitalSignatureAlgorithm=SHA1withDSA
Encryptor.DigitalSignatureKeyLength=1024
Encryptor.RandomAlgorithm=SHA1PRNG
Encryptor.CharacterEncoding=UTF-8
# This is the Pseudo Random Function (PRF) that ESAPI's Key Derivation Function
# (KDF) normally uses. Note this is *only* the PRF used for ESAPI's KDF and
# *not* what is used for ESAPI's MAC. (Currently, HmacSHA1 is always used for
# the MAC, mostly to keep the overall size at a minimum.)
#
# Currently supported choices for JDK 1.5 and 1.6 are:
# HmacSHA1 (160 bits), HmacSHA256 (256 bits), HmacSHA384 (384 bits), and
# HmacSHA512 (512 bits).
# Note that HmacMD5 is *not* supported for the PRF used by the KDF even though
# the JDKs support it. See the ESAPI 2.0 Symmetric Encryption User Guide
# further details.
Encryptor.KDF.PRF=HmacSHA256
#===========================================================================
# ESAPI HttpUtilties
#
# The HttpUtilities provide basic protections to HTTP requests and responses. Primarily these methods
# protect against malicious data from attackers, such as unprintable characters, escaped characters,
# and other simple attacks. The HttpUtilities also provides utility methods for dealing with cookies,
# headers, and CSRF tokens.
#
# Default file upload location (remember to escape backslashes with \\)
HttpUtilities.UploadDir=C:\\ESAPI\\testUpload
HttpUtilities.UploadTempDir=C:\\temp
# Force flags on cookies, if you use HttpUtilities to set cookies
HttpUtilities.ForceHttpOnlySession=false
HttpUtilities.ForceSecureSession=false
HttpUtilities.ForceHttpOnlyCookies=true
HttpUtilities.ForceSecureCookies=true
# Maximum size of HTTP header key--the validator regex may have additional values.
HttpUtilities.MaxHeaderNameSize=256
# Maximum size of HTTP header value--the validator regex may have additional values.
HttpUtilities.MaxHeaderValueSize=4096
# Maximum size of JSESSIONID for the application--the validator regex may have additional values.
HttpUtilities.HTTPJSESSIONIDLENGTH=50
# Maximum length of a URL (see https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers)
HttpUtilities.URILENGTH=2000
# Maximum length of a redirect
HttpUtilities.maxRedirectLength=512
# Maximum length for an http scheme
HttpUtilities.HTTPSCHEMELENGTH=10
# Maximum length for an http host
HttpUtilities.HTTPHOSTLENGTH=100
# Maximum length for an http path
HttpUtilities.HTTPPATHLENGTH=150
#Maximum length for a context path
HttpUtilities.contextPathLength=150
#Maximum length for an httpServletPath
HttpUtilities.HTTPSERVLETPATHLENGTH=100
#Maximum length for an http query parameter name
HttpUtilities.httpQueryParamNameLength=100
#Maximum length for an http query parameter -- old default was 2000, but that's the max length for a URL...
HttpUtilities.httpQueryParamValueLength=500
# File upload configuration
HttpUtilities.ApprovedUploadExtensions=.pdf,.doc,.docx,.ppt,.pptx,.xls,.xlsx,.rtf,.txt,.jpg,.png
HttpUtilities.MaxUploadFileBytes=500000000
# Using UTF-8 throughout your stack is highly recommended. That includes your database driver,
# container, and any other technologies you may be using. Failure to do this may expose you
# to Unicode transcoding injection attacks. Use of UTF-8 does not hinder internationalization.
HttpUtilities.ResponseContentType=text/html; charset=UTF-8
# This is the name of the cookie used to represent the HTTP session
# Typically this will be the default "JSESSIONID"
HttpUtilities.HttpSessionIdName=JSESSIONID
#Sets whether or not we will overwrite http status codes to 200.
HttpUtilities.OverwriteStatusCodes=true
#Sets the application's base character encoding. This is forked from the Java Encryptor property.
HttpUtilities.CharacterEncoding=UTF-8
#===========================================================================
# ESAPI Executor
# CHECKME - This should be made OS independent. Don't use unsafe defaults.
# # Examples only -- do NOT blindly copy!
# For Windows:
# Executor.WorkingDirectory=C:\\Windows\\Temp
# Executor.ApprovedExecutables=C:\\Windows\\System32\\cmd.exe,C:\\Windows\\System32\\runas.exe
# For *nux, MacOS:
# Executor.WorkingDirectory=/tmp
# Executor.ApprovedExecutables=/bin/bash
Executor.WorkingDirectory=
Executor.ApprovedExecutables=
#===========================================================================
# ESAPI Logging
# Set the application name if these logs are combined with other applications
Logger.ApplicationName=ExampleApplication
# If you use an HTML log viewer that does not properly HTML escape log data, you can set LogEncodingRequired to true
Logger.LogEncodingRequired=false
# Determines whether ESAPI should log the application name. This might be clutter in some single-server/single-app environments.
Logger.LogApplicationName=true
# Determines whether ESAPI should log the server IP and port. This might be clutter in some single-server environments.
Logger.LogServerIP=true
# LogFileName, the name of the logging file. Provide a full directory path (e.g., C:\\ESAPI\\ESAPI_logging_file) if you
# want to place it in a specific directory.
Logger.LogFileName=ESAPI_logging_file
# MaxLogFileSize, the max size (in bytes) of a single log file before it cuts over to a new one (default is 10,000,000)
Logger.MaxLogFileSize=10000000
#===========================================================================
# ESAPI Intrusion Detection
#
# Each event has a base to which .count, .interval, and .action are added
# The IntrusionException will fire if we receive "count" events within "interval" seconds
# The IntrusionDetector is configurable to take the following actions: log, logout, and disable
# (multiple actions separated by commas are allowed e.g. event.test.actions=log,disable
#
# Custom Events
# Names must start with "event." as the base
# Use IntrusionDetector.addEvent( "test" ) in your code to trigger "event.test" here
# You can also disable intrusion detection completely by changing
# the following parameter to true
#
IntrusionDetector.Disable=false
#
IntrusionDetector.event.test.count=2
IntrusionDetector.event.test.interval=10
IntrusionDetector.event.test.actions=disable,log
# Exception Events
# All EnterpriseSecurityExceptions are registered automatically
# Call IntrusionDetector.getInstance().addException(e) for Exceptions that do not extend EnterpriseSecurityException
# Use the fully qualified classname of the exception as the base
# any intrusion is an attack
IntrusionDetector.org.owasp.esapi.errors.IntrusionException.count=1
IntrusionDetector.org.owasp.esapi.errors.IntrusionException.interval=1
IntrusionDetector.org.owasp.esapi.errors.IntrusionException.actions=log,disable,logout
# for test purposes
# CHECKME: Shouldn't there be something in the property name itself that designates
# that these are for testing???
IntrusionDetector.org.owasp.esapi.errors.IntegrityException.count=10
IntrusionDetector.org.owasp.esapi.errors.IntegrityException.interval=5
IntrusionDetector.org.owasp.esapi.errors.IntegrityException.actions=log,disable,logout
# rapid validation errors indicate scans or attacks in progress
# org.owasp.esapi.errors.ValidationException.count=10
# org.owasp.esapi.errors.ValidationException.interval=10
# org.owasp.esapi.errors.ValidationException.actions=log,logout
# sessions jumping between hosts indicates session hijacking
IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.count=2
IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.interval=10
IntrusionDetector.org.owasp.esapi.errors.AuthenticationHostException.actions=log,logout
#===========================================================================
# ESAPI Validation
#
# The ESAPI Validator works on regular expressions with defined names. You can define names
# either here, or you may define application specific patterns in a separate file defined below.
# This allows enterprises to specify both organizational standards as well as application specific
# validation rules.
#
# Use '\p{L}' (without the quotes) within the character class to match
# any Unicode LETTER. You can also use a range, like: \u00C0-\u017F
# You can also use any of the regex flags as documented at
# https://docs.oracle.com/javase/tutorial/essential/regex/pattern.html, e.g. (?u)
#
Validator.ConfigurationFile=validation.properties
# Validators used by ESAPI
Validator.AccountName=^[a-zA-Z0-9]{3,20}$
Validator.SystemCommand=^[a-zA-Z\\-\\/]{1,64}$
Validator.RoleName=^[a-z0-9]{1,20}$
#the word TEST below should be changed to your application
#name - only relative URL's are supported
Validator.Redirect=^\\/test.*$
# Global HTTP Validation Rules
# Values with Base64 encoded data (e.g. encrypted state) will need at least [a-zA-Z0-9\/+=]
Validator.HTTPScheme=^(http|https)$
Validator.HTTPServerName=^[a-zA-Z0-9_.\\-]*$
Validator.HTTPCookieName=^[a-zA-Z0-9\\-_]{1,32}$
Validator.HTTPCookieValue=^[a-zA-Z0-9\\-\\/+=_ ]*$
# Note that headerName and Value length is also configured in the HTTPUtilities section
Validator.HTTPHeaderName=^[a-zA-Z0-9\\-_]{1,256}$
Validator.HTTPHeaderValue=^[a-zA-Z0-9()\\-=\\*\\.\\?;,+\\/:&_ ]*$
Validator.HTTPServletPath=^[a-zA-Z0-9.\\-\\/_]*$
Validator.HTTPPath=^[a-zA-Z0-9.\\-_]*$
Validator.HTTPURL=^.*$
Validator.HTTPJSESSIONID=^[A-Z0-9]{10,32}$
# Contributed by Fraenku@gmx.ch
# Github Issue 126 https://github.com/ESAPI/esapi-java-legacy/issues/126
Validator.HTTPParameterName=^[a-zA-Z0-9_\\-]{1,32}$
Validator.HTTPParameterValue=^[\\p{L}\\p{N}.\\-/+=_ !$*?@]{0,1000}$
Validator.HTTPContextPath=^/[a-zA-Z0-9.\\-_]*$
Validator.HTTPQueryString=^([a-zA-Z0-9_\\-]{1,32}=[\\p{L}\\p{N}.\\-/+=_ !$*?@%]*&?)*$
Validator.HTTPURI=^/([a-zA-Z0-9.\\-_]*/?)*$
# Validation of file related input
Validator.FileName=^[a-zA-Z0-9!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
Validator.DirectoryName=^[a-zA-Z0-9:/\\\\!@#$%^&{}\\[\\]()_+\\-=,.~'` ]{1,255}$
# Validation of dates. Controls whether or not 'lenient' dates are accepted.
# See DataFormat.setLenient(boolean flag) for further details.
Validator.AcceptLenientDates=false

View File

@@ -0,0 +1,492 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
W3C rules retrieved from:
http://www.w3.org/TR/html401/struct/global.html
-->
<!--
Slashdot allowed tags taken from "Reply" page:
<b> <i> <p> <br> <a> <ol> <ul> <li> <dl> <dt> <dd> <em> <strong> <tt> <blockquote> <div> <ecode> <quote>
-->
<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="antisamy.xsd">
<directives>
<directive name="omitXmlDeclaration" value="true"/>
<directive name="omitDoctypeDeclaration" value="true"/>
<directive name="maxInputSize" value="500000"/>
<directive name="embedStyleSheets" value="false"/>
</directives>
<common-regexps>
<!--
From W3C:
This attribute assigns a class name or set of class names to an
element. Any number of elements may be assigned the same class
name or names. Multiple class names must be separated by white
space characters.
-->
<regexp name="htmlTitle" value="[a-zA-Z0-9\s-_',:\[\]!\./\\\(\)]*"/> <!-- force non-empty with a '+' at the end instead of '*' -->
<regexp name="onsiteURL" value="([\w\\/\.\?=&amp;;\#-~]+|\#(\w)+)"/>
<regexp name="offsiteURL" value="(\s)*((ht|f)tp(s?)://|mailto:)[A-Za-z0-9]+[~a-zA-Z0-9-_\.@#$%&amp;;:,\?=/\+!]*(\s)*"/>
</common-regexps>
<!--
Tag.name = a, b, div, body, etc.
Tag.action = filter: remove tags, but keep content, validate: keep content as long as it passes rules, remove: remove tag and contents
Attribute.name = id, class, href, align, width, etc.
Attribute.onInvalid = what to do when the attribute is invalid, e.g., remove the tag (removeTag), remove the attribute (removeAttribute), filter the tag (filterTag)
Attribute.description = What rules in English you want to tell the users they can have for this attribute. Include helpful things so they'll be able to tune their HTML
-->
<!--
Some attributes are common to all (or most) HTML tags. There aren't many that qualify for this. You have to make sure there's no
collisions between any of these attribute names with attribute names of other tags that are for different purposes.
-->
<common-attributes>
<attribute name="lang" description="The 'lang' attribute tells the browser what language the element's attribute values and content are written in">
<regexp-list>
<regexp value="[a-zA-Z]{2,20}"/>
</regexp-list>
</attribute>
<attribute name="title" description="The 'title' attribute provides text that shows up in a 'tooltip' when a user hovers their mouse over the element">
<regexp-list>
<regexp name="htmlTitle"/>
</regexp-list>
</attribute>
<attribute name="href" onInvalid="filterTag">
<regexp-list>
<regexp name="onsiteURL"/>
<regexp name="offsiteURL"/>
</regexp-list>
</attribute>
<attribute name="align" description="The 'align' attribute of an HTML element is a direction word, like 'left', 'right' or 'center'">
<literal-list>
<literal value="center"/>
<literal value="left"/>
<literal value="right"/>
<literal value="justify"/>
<literal value="char"/>
</literal-list>
</attribute>
</common-attributes>
<!--
This requires normal updates as browsers continue to diverge from the W3C and each other. As long as the browser wars continue
this is going to continue. I'm not sure war is the right word for what's going on. Doesn't somebody have to win a war after
a while?
-->
<global-tag-attributes>
<attribute name="title"/>
<attribute name="lang"/>
</global-tag-attributes>
<tag-rules>
<!-- Tags related to JavaScript -->
<tag name="script" action="remove"/>
<tag name="noscript" action="remove"/>
<!-- Frame & related tags -->
<tag name="iframe" action="remove"/>
<tag name="frameset" action="remove"/>
<tag name="frame" action="remove"/>
<tag name="noframes" action="remove"/>
<!-- All reasonable formatting tags -->
<tag name="p" action="validate">
<attribute name="align"/>
</tag>
<tag name="div" action="validate"/>
<tag name="i" action="validate"/>
<tag name="b" action="validate"/>
<tag name="em" action="validate"/>
<tag name="blockquote" action="validate"/>
<tag name="tt" action="validate"/>
<tag name="br" action="truncate"/>
<!-- Custom Slashdot tags, though we're trimming the idea of having a possible mismatching end tag with the endtag="" attribute -->
<tag name="quote" action="validate"/>
<tag name="ecode" action="validate"/>
<!-- Anchor and anchor related tags -->
<tag name="a" action="validate">
<attribute name="href" onInvalid="filterTag"/>
<attribute name="nohref">
<literal-list>
<literal value="nohref"/>
<literal value=""/>
</literal-list>
</attribute>
<attribute name="rel">
<literal-list>
<literal value="nofollow"/>
</literal-list>
</attribute>
</tag>
<!-- List tags -->
<tag name="ul" action="validate"/>
<tag name="ol" action="validate"/>
<tag name="li" action="validate"/>
</tag-rules>
<!-- No CSS on Slashdot posts -->
<css-rules>
</css-rules>
<html-entities>
<entity name="amp" cdata="&amp;"/>
<entity name="nbsp" cdata="&amp;#160;"/>
<entity name="iexcl" cdata="&amp;#161;"/> <!--inverted exclamation mark, U+00A1 ISOnum -->
<entity name="cent" cdata="&amp;#162;"/> <!--cent sign, U+00A2 ISOnum -->
<entity name="pound" cdata="&amp;#163;"/> <!--pound sign, U+00A3 ISOnum -->
<entity name="curren" cdata="&amp;#164;"/> <!--currency sign, U+00A4 ISOnum -->
<entity name="yen" cdata="&amp;#165;"/> <!--yen sign = yuan sign, U+00A5 ISOnum -->
<entity name="brvbar" cdata="&amp;#166;"/> <!--broken bar = broken vertical bar, U+00A6 ISOnum -->
<entity name="sect" cdata="&amp;#167;"/> <!--section sign, U+00A7 ISOnum -->
<entity name="uml" cdata="&amp;#168;"/> <!--diaeresis = spacing diaeresis, U+00A8 ISOdia -->
<entity name="copy" cdata="&amp;#169;"/> <!--copyright sign, U+00A9 ISOnum -->
<entity name="ordf" cdata="&amp;#170;"/> <!--feminine ordinal indicator, U+00AA ISOnum -->
<entity name="laquo" cdata="&amp;#171;"/> <!--left-pointing double angle quotation mark = left pointing guillemet, U+00AB ISOnum -->
<entity name="not" cdata="&amp;#172;"/> <!--not sign, U+00AC ISOnum -->
<entity name="shy" cdata="&amp;#173;"/> <!--soft hyphen = discretionary hyphen,U+00AD ISOnum -->
<entity name="reg" cdata="&amp;#174;"/> <!--registered sign = registered trade mark sign, U+00AE ISOnum -->
<entity name="macr" cdata="&amp;#175;"/> <!--macron = spacing macron = overline = APL overbar, U+00AF ISOdia -->
<entity name="deg" cdata="&amp;#176;"/> <!--degree sign, U+00B0 ISOnum -->
<entity name="plusmn" cdata="&amp;#177;"/> <!--plus-minus sign = plus-or-minus sign, U+00B1 ISOnum -->
<entity name="sup2" cdata="&amp;#178;"/> <!--superscript two = superscript digit two = squared, U+00B2 ISOnum -->
<entity name="sup3" cdata="&amp;#179;"/> <!--superscript three = superscript digit three= cubed, U+00B3 ISOnum -->
<entity name="acute" cdata="&amp;#180;"/> <!--acute accent = spacing acute, U+00B4 ISOdia -->
<entity name="micro" cdata="&amp;#181;"/> <!--micro sign, U+00B5 ISOnum -->
<entity name="para" cdata="&amp;#182;"/> <!--pilcrow sign = paragraph sign, U+00B6 ISOnum -->
<entity name="middot" cdata="&amp;#183;"/> <!--middle dot = Georgian comma = Greek middle dot, U+00B7 ISOnum -->
<entity name="cedil" cdata="&amp;#184;"/> <!--cedilla = spacing cedilla, U+00B8 ISOdia -->
<entity name="sup1" cdata="&amp;#185;"/> <!--superscript one = superscript digit one,U+00B9 ISOnum -->
<entity name="ordm" cdata="&amp;#186;"/> <!--masculine ordinal indicator, U+00BA ISOnum -->
<entity name="raquo" cdata="&amp;#187;"/> <!--right-pointing double angle quotation mark = right pointing guillemet, U+00BB ISOnum -->
<entity name="frac14" cdata="&amp;#188;"/> <!--vulgar fraction one quarter = fraction one quarter, U+00BC ISOnum -->
<entity name="frac12" cdata="&amp;#189;"/> <!--vulgar fraction one half = fraction one half, U+00BD ISOnum -->
<entity name="frac34" cdata="&amp;#190;"/> <!--vulgar fraction three quarters = fraction three quarters, U+00BE ISOnum -->
<entity name="iquest" cdata="&amp;#191;"/> <!--inverted question mark = turned question mark, U+00BF ISOnum -->
<entity name="Agrave" cdata="&amp;#192;"/> <!--latin capital letter A with grave = latin capital letter A grave,U+00C0 ISOlat1 -->
<entity name="Aacute" cdata="&amp;#193;"/> <!--latin capital letter A with acute,U+00C1 ISOlat1 -->
<entity name="Acirc" cdata="&amp;#194;"/> <!--latin capital letter A with circumflex,U+00C2 ISOlat1 -->
<entity name="Atilde" cdata="&amp;#195;"/> <!--latin capital letter A with tilde,U+00C3 ISOlat1 -->
<entity name="Auml" cdata="&amp;#196;"/> <!--latin capital letter A with diaeresis,U+00C4 ISOlat1 -->
<entity name="Aring" cdata="&amp;#197;"/> <!--latin capital letter A with ring above = latin capital letter A ring, U+00C5 ISOlat1 -->
<entity name="AElig" cdata="&amp;#198;"/> <!--latin capital letter AE = latin capital ligature AE, U+00C6 ISOlat1 -->
<entity name="Ccedil" cdata="&amp;#199;"/> <!--latin capital letter C with cedilla, U+00C7 ISOlat1 -->
<entity name="Egrave" cdata="&amp;#200;"/> <!--latin capital letter E with grave, U+00C8 ISOlat1 -->
<entity name="Eacute" cdata="&amp;#201;"/> <!--latin capital letter E with acute,U+00C9 ISOlat1 -->
<entity name="Ecirc" cdata="&amp;#202;"/> <!--latin capital letter E with circumflex,U+00CA ISOlat1 -->
<entity name="Euml" cdata="&amp;#203;"/> <!--latin capital letter E with diaeresis, U+00CB ISOlat1 -->
<entity name="Igrave" cdata="&amp;#204;"/> <!--latin capital letter I with grave, U+00CC ISOlat1 -->
<entity name="Iacute" cdata="&amp;#205;"/> <!--latin capital letter I with acute, U+00CD ISOlat1 -->
<entity name="Icirc" cdata="&amp;#206;"/> <!--latin capital letter I with circumflex, U+00CE ISOlat1 -->
<entity name="Iuml" cdata="&amp;#207;"/> <!--latin capital letter I with diaeresis, U+00CF ISOlat1 -->
<entity name="ETH" cdata="&amp;#208;"/> <!--latin capital letter ETH, U+00D0 ISOlat1 -->
<entity name="Ntilde" cdata="&amp;#209;"/> <!--latin capital letter N with tilde, U+00D1 ISOlat1 -->
<entity name="Ograve" cdata="&amp;#210;"/> <!--latin capital letter O with grave, U+00D2 ISOlat1 -->
<entity name="Oacute" cdata="&amp;#211;"/> <!--latin capital letter O with acute, U+00D3 ISOlat1 -->
<entity name="Ocirc" cdata="&amp;#212;"/> <!--latin capital letter O with circumflex, U+00D4 ISOlat1 -->
<entity name="Otilde" cdata="&amp;#213;"/> <!--latin capital letter O with tilde, U+00D5 ISOlat1 -->
<entity name="Ouml" cdata="&amp;#214;"/> <!--latin capital letter O with diaeresis, U+00D6 ISOlat1 -->
<entity name="times" cdata="&amp;#215;"/> <!--multiplication sign, U+00D7 ISOnum -->
<entity name="Oslash" cdata="&amp;#216;"/> <!--latin capital letter O with stroke = latin capital letter O slash, U+00D8 ISOlat1 -->
<entity name="Ugrave" cdata="&amp;#217;"/> <!--latin capital letter U with grave, U+00D9 ISOlat1 -->
<entity name="Uacute" cdata="&amp;#218;"/> <!--latin capital letter U with acute, U+00DA ISOlat1 -->
<entity name="Ucirc" cdata="&amp;#219;"/> <!--latin capital letter U with circumflex, U+00DB ISOlat1 -->
<entity name="Uuml" cdata="&amp;#220;"/> <!--latin capital letter U with diaeresis, U+00DC ISOlat1 -->
<entity name="Yacute" cdata="&amp;#221;"/> <!--latin capital letter Y with acute, U+00DD ISOlat1 -->
<entity name="THORN" cdata="&amp;#222;"/> <!--latin capital letter THORN, U+00DE ISOlat1 -->
<entity name="szlig" cdata="&amp;#223;"/> <!--latin small letter sharp s = ess-zed, U+00DF ISOlat1 -->
<entity name="agrave" cdata="&amp;#224;"/> <!--latin small letter a with grave = latin small letter a grave, U+00E0 ISOlat1 -->
<entity name="aacute" cdata="&amp;#225;"/> <!--latin small letter a with acute, U+00E1 ISOlat1 -->
<entity name="acirc" cdata="&amp;#226;"/> <!--latin small letter a with circumflex, U+00E2 ISOlat1 -->
<entity name="atilde" cdata="&amp;#227;"/> <!--latin small letter a with tilde, U+00E3 ISOlat1 -->
<entity name="auml" cdata="&amp;#228;"/> <!--latin small letter a with diaeresis, U+00E4 ISOlat1 -->
<entity name="aring" cdata="&amp;#229;"/> <!--latin small letter a with ring above = latin small letter a ring, U+00E5 ISOlat1 -->
<entity name="aelig" cdata="&amp;#230;"/> <!--latin small letter ae = latin small ligature ae, U+00E6 ISOlat1 -->
<entity name="ccedil" cdata="&amp;#231;"/> <!--latin small letter c with cedilla, U+00E7 ISOlat1 -->
<entity name="egrave" cdata="&amp;#232;"/> <!--latin small letter e with grave, U+00E8 ISOlat1 -->
<entity name="eacute" cdata="&amp;#233;"/> <!--latin small letter e with acute, U+00E9 ISOlat1 -->
<entity name="ecirc" cdata="&amp;#234;"/> <!--latin small letter e with circumflex, U+00EA ISOlat1 -->
<entity name="euml" cdata="&amp;#235;"/> <!--latin small letter e with diaeresis, U+00EB ISOlat1 -->
<entity name="igrave" cdata="&amp;#236;"/> <!--latin small letter i with grave, U+00EC ISOlat1 -->
<entity name="iacute" cdata="&amp;#237;"/> <!--latin small letter i with acute, U+00ED ISOlat1 -->
<entity name="icirc" cdata="&amp;#238;"/> <!--latin small letter i with circumflex, U+00EE ISOlat1 -->
<entity name="iuml" cdata="&amp;#239;"/> <!--latin small letter i with diaeresis, U+00EF ISOlat1 -->
<entity name="eth" cdata="&amp;#240;"/> <!--latin small letter eth, U+00F0 ISOlat1 -->
<entity name="ntilde" cdata="&amp;#241;"/> <!--latin small letter n with tilde, U+00F1 ISOlat1 -->
<entity name="ograve" cdata="&amp;#242;"/> <!--latin small letter o with grave, U+00F2 ISOlat1 -->
<entity name="oacute" cdata="&amp;#243;"/> <!--latin small letter o with acute, U+00F3 ISOlat1 -->
<entity name="ocirc " cdata="&amp;#244;"/> <!--latin small letter o with circumflex, U+00F4 ISOlat1 -->
<entity name="otilde" cdata="&amp;#245;"/> <!--latin small letter o with tilde, U+00F5 ISOlat1 -->
<entity name="ouml" cdata="&amp;#246;"/> <!--latin small letter o with diaeresis, U+00F6 ISOlat1 -->
<entity name="divide" cdata="&amp;#247;"/> <!--division sign, U+00F7 ISOnum -->
<entity name="oslash" cdata="&amp;#248;"/> <!--latin small letter o with stroke, = latin small letter o slash, U+00F8 ISOlat1 -->
<entity name="ugrave" cdata="&amp;#249;"/> <!--latin small letter u with grave, U+00F9 ISOlat1 -->
<entity name="uacute" cdata="&amp;#250;"/> <!--latin small letter u with acute, U+00FA ISOlat1 -->
<entity name="ucirc" cdata="&amp;#251;"/> <!--latin small letter u with circumflex, U+00FB ISOlat1 -->
<entity name="uuml" cdata="&amp;#252;"/> <!--latin small letter u with diaeresis, U+00FC ISOlat1 -->
<entity name="yacute" cdata="&amp;#253;"/> <!--latin small letter y with acute, U+00FD ISOlat1 -->
<entity name="thorn" cdata="&amp;#254;"/> <!--latin small letter thorn, U+00FE ISOlat1 -->
<entity name="yuml" cdata="&amp;#255;"/> <!--latin small letter y with diaeresis, U+00FF ISOlat1 -->
<entity name="fnof" cdata="&amp;#402;"/> <!--latin small f with hook = function = florin, U+0192 ISOtech -->
<!-- Greek -->
<entity name="Alpha" cdata="&amp;#913;"/> <!--greek capital letter alpha, U+0391 -->
<entity name="Beta" cdata="&amp;#914;"/> <!--greek capital letter beta, U+0392 -->
<entity name="Gamma" cdata="&amp;#915;"/> <!--greek capital letter gamma, U+0393 ISOgrk3 -->
<entity name="Delta" cdata="&amp;#916;"/> <!--greek capital letter delta, U+0394 ISOgrk3 -->
<entity name="Epsilon" cdata="&amp;#917;"/> <!--greek capital letter epsilon, U+0395 -->
<entity name="Zeta" cdata="&amp;#918;"/> <!--greek capital letter zeta, U+0396 -->
<entity name="Eta" cdata="&amp;#919;"/> <!--greek capital letter eta, U+0397 -->
<entity name="Theta" cdata="&amp;#920;"/> <!--greek capital letter theta, U+0398 ISOgrk3 -->
<entity name="Iota" cdata="&amp;#921;"/> <!--greek capital letter iota, U+0399 -->
<entity name="Kappa" cdata="&amp;#922;"/> <!--greek capital letter kappa, U+039A -->
<entity name="Lambda" cdata="&amp;#923;"/> <!--greek capital letter lambda, U+039B ISOgrk3 -->
<entity name="Mu" cdata="&amp;#924;"/> <!--greek capital letter mu, U+039C -->
<entity name="Nu" cdata="&amp;#925;"/> <!--greek capital letter nu, U+039D -->
<entity name="Xi" cdata="&amp;#926;"/> <!--greek capital letter xi, U+039E ISOgrk3 -->
<entity name="Omicron" cdata="&amp;#927;"/> <!--greek capital letter omicron, U+039F -->
<entity name="Pi" cdata="&amp;#928;"/> <!--greek capital letter pi, U+03A0 ISOgrk3 -->
<entity name="Rho" cdata="&amp;#929;"/> <!--greek capital letter rho, U+03A1 -->
<!-- there is no Sigmaf, and no U+03A2 character either -->
<entity name="Sigma" cdata="&amp;#931;"/> <!--greek capital letter sigma, U+03A3 ISOgrk3 -->
<entity name="Tau" cdata="&amp;#932;"/> <!--greek capital letter tau, U+03A4 -->
<entity name="Upsilon" cdata="&amp;#933;"/> <!--greek capital letter upsilon,U+03A5 ISOgrk3 -->
<entity name="Phi" cdata="&amp;#934;"/> <!--greek capital letter phi,U+03A6 ISOgrk3 -->
<entity name="Chi" cdata="&amp;#935;"/> <!--greek capital letter chi, U+03A7 -->
<entity name="Psi" cdata="&amp;#936;"/> <!--greek capital letter psi,U+03A8 ISOgrk3 -->
<entity name="Omega" cdata="&amp;#937;"/> <!--greek capital letter omega,U+03A9 ISOgrk3 -->
<entity name="alpha" cdata="&amp;#945;"/> <!--greek small letter alpha,U+03B1 ISOgrk3 -->
<entity name="beta" cdata="&amp;#946;"/> <!--greek small letter beta, U+03B2 ISOgrk3 -->
<entity name="gamma" cdata="&amp;#947;"/> <!--greek small letter gamma,U+03B3 ISOgrk3 -->
<entity name="delta" cdata="&amp;#948;"/> <!--greek small letter delta,U+03B4 ISOgrk3 -->
<entity name="epsilon" cdata="&amp;#949;"/> <!--greek small letter epsilon,U+03B5 ISOgrk3 -->
<entity name="zeta" cdata="&amp;#950;"/> <!--greek small letter zeta, U+03B6 ISOgrk3 -->
<entity name="eta" cdata="&amp;#951;"/> <!--greek small letter eta, U+03B7 ISOgrk3 -->
<entity name="theta" cdata="&amp;#952;"/> <!--greek small letter theta, U+03B8 ISOgrk3 -->
<entity name="iota" cdata="&amp;#953;"/> <!--greek small letter iota, U+03B9 ISOgrk3 -->
<entity name="kappa" cdata="&amp;#954;"/> <!--greek small letter kappa,U+03BA ISOgrk3 -->
<entity name="lambda" cdata="&amp;#955;"/> <!--greek small letter lambda, U+03BB ISOgrk3 -->
<entity name="mu" cdata="&amp;#956;"/> <!--greek small letter mu, U+03BC ISOgrk3 -->
<entity name="nu" cdata="&amp;#957;"/> <!--greek small letter nu, U+03BD ISOgrk3 -->
<entity name="xi" cdata="&amp;#958;"/> <!--greek small letter xi, U+03BE ISOgrk3 -->
<entity name="omicron" cdata="&amp;#959;"/> <!--greek small letter omicron, U+03BF NEW -->
<entity name="pi" cdata="&amp;#960;"/> <!--greek small letter pi, U+03C0 ISOgrk3 -->
<entity name="rho" cdata="&amp;#961;"/> <!--greek small letter rho, U+03C1 ISOgrk3 -->
<entity name="sigmaf" cdata="&amp;#962;"/> <!--greek small letter final sigma, U+03C2 ISOgrk3 -->
<entity name="sigma" cdata="&amp;#963;"/> <!--greek small letter sigma, U+03C3 ISOgrk3 -->
<entity name="tau" cdata="&amp;#964;"/> <!--greek small letter tau, U+03C4 ISOgrk3 -->
<entity name="upsilon" cdata="&amp;#965;"/> <!--greek small letter upsilon, U+03C5 ISOgrk3 -->
<entity name="phi" cdata="&amp;#966;"/> <!--greek small letter phi, U+03C6 ISOgrk3 -->
<entity name="chi" cdata="&amp;#967;"/> <!--greek small letter chi, U+03C7 ISOgrk3 -->
<entity name="psi" cdata="&amp;#968;"/> <!--greek small letter psi, U+03C8 ISOgrk3 -->
<entity name="omega" cdata="&amp;#969;"/> <!--greek small letter omega, U+03C9 ISOgrk3 -->
<entity name="thetasym" cdata="&amp;#977;"/> <!--greek small letter theta symbol, U+03D1 NEW -->
<entity name="upsih" cdata="&amp;#978;"/> <!--greek upsilon with hook symbol, U+03D2 NEW -->
<entity name="piv" cdata="&amp;#982;"/> <!--greek pi symbol, U+03D6 ISOgrk3 -->
<!-- General Punctuation -->
<entity name="bull" cdata="&amp;#8226;"/> <!--bullet = black small circle, U+2022 ISOpub -->
<!-- bullet is NOT the same as bullet operator, U+2219 -->
<entity name="hellip" cdata="&amp;#8230;"/> <!--horizontal ellipsis = three dot leader, U+2026 ISOpub -->
<entity name="prime" cdata="&amp;#8242;"/> <!--prime = minutes = feet, U+2032 ISOtech -->
<entity name="Prime" cdata="&amp;#8243;"/> <!--double prime = seconds = inches, U+2033 ISOtech -->
<entity name="oline" cdata="&amp;#8254;"/> <!--overline = spacing overscore, U+203E NEW -->
<entity name="frasl" cdata="&amp;#8260;"/> <!--fraction slash, U+2044 NEW -->
<!-- Letterlike Symbols -->
<entity name="weierp" cdata="&amp;#8472;"/> <!--script capital P = power set = Weierstrass p, U+2118 ISOamso -->
<entity name="image" cdata="&amp;#8465;"/> <!--blackletter capital I = imaginary part, U+2111 ISOamso -->
<entity name="real" cdata="&amp;#8476;"/> <!--blackletter capital R = real part symbol, U+211C ISOamso -->
<entity name="trade" cdata="&amp;#8482;"/> <!--trade mark sign, U+2122 ISOnum -->
<entity name="alefsym" cdata="&amp;#8501;"/> <!--alef symbol = first transfinite cardinal, U+2135 NEW -->
<!-- alef symbol is NOT the same as hebrew letter alef,
U+05D0 although the same glyph could be used to depict both characters -->
<!-- Arrows -->
<entity name="larr" cdata="&amp;#8592;"/> <!--leftwards arrow, U+2190 ISOnum -->
<entity name="uarr" cdata="&amp;#8593;"/> <!--upwards arrow, U+2191 ISOnum-->
<entity name="rarr" cdata="&amp;#8594;"/> <!--rightwards arrow, U+2192 ISOnum -->
<entity name="darr" cdata="&amp;#8595;"/> <!--downwards arrow, U+2193 ISOnum -->
<entity name="harr" cdata="&amp;#8596;"/> <!--left right arrow, U+2194 ISOamsa -->
<entity name="crarr" cdata="&amp;#8629;"/> <!--downwards arrow with corner leftwards
= carriage return, U+21B5 NEW -->
<entity name="lArr" cdata="&amp;#8656;"/> <!--leftwards double arrow, U+21D0 ISOtech -->
<!-- ISO 10646 does not say that lArr is the same as the 'is implied by' arrow
but also does not have any other character for that function. So ? lArr can
be used for 'is implied by' as ISOtech suggests -->
<entity name="uArr" cdata="&amp;#8657;"/> <!--upwards double arrow, U+21D1 ISOamsa -->
<entity name="rArr" cdata="&amp;#8658;"/> <!--rightwards double arrow, U+21D2 ISOtech -->
<!-- ISO 10646 does not say this is the 'implies' character but does not have
another character with this function so ?
rArr can be used for 'implies' as ISOtech suggests -->
<entity name="dArr" cdata="&amp;#8659;"/> <!--downwards double arrow, U+21D3 ISOamsa -->
<entity name="hArr" cdata="&amp;#8660;"/> <!--left right double arrow, U+21D4 ISOamsa -->
<!-- Mathematical Operators -->
<entity name="forall" cdata="&amp;#8704;"/> <!--for all, U+2200 ISOtech -->
<entity name="part" cdata="&amp;#8706;"/> <!--partial differential, U+2202 ISOtech -->
<entity name="exist" cdata="&amp;#8707;"/> <!--there exists, U+2203 ISOtech -->
<entity name="empty" cdata="&amp;#8709;"/> <!--empty set = null set = diameter,U+2205 ISOamso -->
<entity name="nabla" cdata="&amp;#8711;"/> <!--nabla = backward difference, U+2207 ISOtech -->
<entity name="isin" cdata="&amp;#8712;"/> <!--element of, U+2208 ISOtech -->
<entity name="notin" cdata="&amp;#8713;"/> <!--not an element of, U+2209 ISOtech -->
<entity name="ni" cdata="&amp;#8715;"/> <!--contains as member, U+220B ISOtech -->
<!-- should there be a more memorable name than 'ni'? -->
<entity name="prod" cdata="&amp;#8719;"/> <!--n-ary product = product sign, U+220F ISOamsb -->
<!-- prod is NOT the same character as U+03A0 'greek capital letter pi' though
the same glyph might be used for both -->
<entity name="sum" cdata="&amp;#8721;"/> <!--n-ary sumation, U+2211 ISOamsb -->
<!-- sum is NOT the same character as U+03A3 'greek capital letter sigma'
though the same glyph might be used for both -->
<entity name="minus" cdata="&amp;#8722;"/> <!--minus sign, U+2212 ISOtech -->
<entity name="lowast" cdata="&amp;#8727;"/> <!--asterisk operator, U+2217 ISOtech -->
<entity name="radic" cdata="&amp;#8730;"/> <!--square root = radical sign, U+221A ISOtech -->
<entity name="prop" cdata="&amp;#8733;"/> <!--proportional to, U+221D ISOtech -->
<entity name="infin" cdata="&amp;#8734;"/> <!--infinity, U+221E ISOtech -->
<entity name="ang" cdata="&amp;#8736;"/> <!--angle, U+2220 ISOamso -->
<entity name="and" cdata="&amp;#8743;"/> <!--logical and = wedge, U+2227 ISOtech -->
<entity name="or" cdata="&amp;#8744;"/> <!--logical or = vee, U+2228 ISOtech -->
<entity name="cap" cdata="&amp;#8745;"/> <!--intersection = cap, U+2229 ISOtech -->
<entity name="cup" cdata="&amp;#8746;"/> <!--union = cup, U+222A ISOtech -->
<entity name="int" cdata="&amp;#8747;"/> <!--integral, U+222B ISOtech -->
<entity name="there4" cdata="&amp;#8756;"/> <!--therefore, U+2234 ISOtech -->
<entity name="sim" cdata="&amp;#8764;"/> <!--tilde operator = varies with = similar to, U+223C ISOtech -->
<!-- tilde operator is NOT the same character as the tilde, U+007E,
although the same glyph might be used to represent both -->
<entity name="cong" cdata="&amp;#8773;"/> <!--approximately equal to, U+2245 ISOtech -->
<entity name="asymp" cdata="&amp;#8776;"/> <!--almost equal to = asymptotic to, U+2248 ISOamsr -->
<entity name="ne" cdata="&amp;#8800;"/> <!--not equal to, U+2260 ISOtech -->
<entity name="equiv" cdata="&amp;#8801;"/> <!--identical to, U+2261 ISOtech -->
<entity name="le" cdata="&amp;#8804;"/> <!--less-than or equal to, U+2264 ISOtech -->
<entity name="ge" cdata="&amp;#8805;"/> <!--greater-than or equal to, U+2265 ISOtech -->
<entity name="sub" cdata="&amp;#8834;"/> <!--subset of, U+2282 ISOtech -->
<entity name="sup" cdata="&amp;#8835;"/> <!--superset of, U+2283 ISOtech -->
<!-- note that nsup, 'not a superset of, U+2283' is not covered by the Symbol
font encoding and is not included. Should it be, for symmetry?
It is in ISOamsn -->
<entity name="nsub" cdata="&amp;#8836;"/> <!--not a subset of, U+2284 ISOamsn -->
<entity name="sube" cdata="&amp;#8838;"/> <!--subset of or equal to, U+2286 ISOtech -->
<entity name="supe" cdata="&amp;#8839;"/> <!--superset of or equal to, U+2287 ISOtech -->
<entity name="oplus" cdata="&amp;#8853;"/> <!--circled plus = direct sum, U+2295 ISOamsb -->
<entity name="otimes" cdata="&amp;#8855;"/> <!--circled times = vector product, U+2297 ISOamsb -->
<entity name="perp" cdata="&amp;#8869;"/> <!--up tack = orthogonal to = perpendicular, U+22A5 ISOtech -->
<entity name="sdot" cdata="&amp;#8901;"/> <!--dot operator, U+22C5 ISOamsb -->
<!-- dot operator is NOT the same character as U+00B7 middle dot -->
<!-- Miscellaneous Technical -->
<entity name="lceil" cdata="&amp;#8968;"/> <!--left ceiling = apl upstile, U+2308 ISOamsc -->
<entity name="rceil" cdata="&amp;#8969;"/> <!--right ceiling, U+2309 ISOamsc -->
<entity name="lfloor" cdata="&amp;#8970;"/> <!--left floor = apl downstile, U+230A ISOamsc -->
<entity name="rfloor" cdata="&amp;#8971;"/> <!--right floor, U+230B ISOamsc -->
<entity name="lang" cdata="&amp;#9001;"/> <!--left-pointing angle bracket = bra, U+2329 ISOtech -->
<!-- lang is NOT the same character as U+003C 'less than'
or U+2039 'single left-pointing angle quotation mark' -->
<entity name="rang" cdata="&amp;#9002;"/> <!--right-pointing angle bracket = ket, U+232A ISOtech -->
<!-- rang is NOT the same character as U+003E 'greater than' or U+203A 'single right-pointing angle quotation mark' -->
<!-- Geometric Shapes -->
<entity name="loz" cdata="&amp;#9674;"/> <!--lozenge, U+25CA ISOpub -->
<!-- Miscellaneous Symbols -->
<entity name="spades" cdata="&amp;#9824;"/> <!--black spade suit, U+2660 ISOpub -->
<!-- black here seems to mean filled as opposed to hollow -->
<entity name="clubs" cdata="&amp;#9827;"/> <!--black club suit = shamrock, U+2663 ISOpub -->
<entity name="hearts" cdata="&amp;#9829;"/> <!--black heart suit = valentine, U+2665 ISOpub -->
<entity name="diams" cdata="&amp;#9830;"/> <!--black diamond suit, U+2666 ISOpub -->
<entity name="quot" cdata="&amp;#34;" /> <!--quotation mark = APL quote, U+0022 ISOnum -->
<!-- Latin Extended-A -->
<entity name="OElig" cdata="&amp;#338;" /> <!--latin capital ligature OE, U+0152 ISOlat2 -->
<entity name="oelig" cdata="&amp;#339;" /> <!--latin small ligature oe, U+0153 ISOlat2 -->
<!-- ligature is a misnomer, this is a separate character in some languages -->
<entity name="Scaron" cdata="&amp;#352;" /> <!--latin capital letter S with caron, U+0160 ISOlat2 -->
<entity name="scaron" cdata="&amp;#353;" /> <!--latin small letter s with caron, U+0161 ISOlat2 -->
<entity name="Yuml" cdata="&amp;#376;" /> <!--latin capital letter Y with diaeresis, U+0178 ISOlat2 -->
<!-- Spacing Modifier Letters -->
<entity name="circ" cdata="&amp;#710;" /> <!--modifier letter circumflex accent, U+02C6 ISOpub -->
<entity name="tilde" cdata="&amp;#732;" /> <!--small tilde, U+02DC ISOdia -->
<!-- General Punctuation -->
<entity name="ensp" cdata="&amp;#8194;"/> <!--en space, U+2002 ISOpub -->
<entity name="emsp" cdata="&amp;#8195;"/> <!--em space, U+2003 ISOpub -->
<entity name="thinsp" cdata="&amp;#8201;"/> <!--thin space, U+2009 ISOpub -->
<entity name="zwnj" cdata="&amp;#8204;"/> <!--zero width non-joiner, U+200C NEW RFC 2070 -->
<entity name="zwj" cdata="&amp;#8205;"/> <!--zero width joiner, U+200D NEW RFC 2070 -->
<entity name="lrm" cdata="&amp;#8206;"/> <!--left-to-right mark, U+200E NEW RFC 2070 -->
<entity name="rlm" cdata="&amp;#8207;"/> <!--right-to-left mark, U+200F NEW RFC 2070 -->
<entity name="ndash" cdata="&amp;#8211;"/> <!--en dash, U+2013 ISOpub -->
<entity name="mdash" cdata="&amp;#8212;"/> <!--em dash, U+2014 ISOpub -->
<entity name="lsquo" cdata="&amp;#8216;"/> <!--left single quotation mark, U+2018 ISOnum -->
<entity name="rsquo" cdata="&amp;#8217;"/> <!--right single quotation mark, U+2019 ISOnum -->
<entity name="sbquo" cdata="&amp;#8218;"/> <!--single low-9 quotation mark, U+201A NEW -->
<entity name="ldquo" cdata="&amp;#8220;"/> <!--left double quotation mark, U+201C ISOnum -->
<entity name="rdquo" cdata="&amp;#8221;"/> <!--right double quotation mark, U+201D ISOnum -->
<entity name="bdquo" cdata="&amp;#8222;"/> <!--double low-9 quotation mark, U+201E NEW -->
<entity name="dagger" cdata="&amp;#8224;"/> <!--dagger, U+2020 ISOpub -->
<entity name="Dagger" cdata="&amp;#8225;"/> <!--double dagger, U+2021 ISOpub -->
<entity name="permil" cdata="&amp;#8240;"/> <!--per mille sign, U+2030 ISOtech -->
<entity name="lsaquo" cdata="&amp;#8249;"/> <!--single left-pointing angle quotation mark, U+2039 ISO proposed -->
<!-- lsaquo is proposed but not yet ISO standardized -->
<entity name="rsaquo" cdata="&amp;#8250;"/> <!--single right-pointing angle quotation mark, U+203A ISO proposed -->
<!-- rsaquo is proposed but not yet ISO standardized -->
<entity name="euro" cdata="&amp;#8364;" /> <!--euro sign, U+20AC NEW -->
</html-entities>
</anti-samy-rules>

View File

@@ -0,0 +1,4 @@
# This is the user file associated with the ESAPI library from http://www.owasp.org
# accountId | accountName | hashedPassword | roles | locked | enabled | csrfToken | oldPasswordHashes | lastPasswordChangeTime | lastLoginTime | lastFailedLoginTime | expirationTime | failedLoginCount
1796576143730101883 | uuu1 | idNZxxHXBaDpKFXw3vHH09ScBjeYEEBK1hOMn7AuxkJnKXFwJ2ijS/m7bm5rj82S8pZzPkbhdgd4qvMey4Y92A== | | unlocked | disabled | | unknown | 0 | 0 | 0 | 9223372036854775807 | 0

View File

@@ -0,0 +1,29 @@
# The ESAPI validator does many security checks on input, such as canonicalization
# and whitelist validation. Note that all of these validation rules are applied *after*
# canonicalization. Double-encoded characters (even with different encodings involved,
# are never allowed.
#
# To use:
#
# First set up a pattern below. You can choose any name you want, prefixed by the word
# "Validation." For example:
# Validation.Email=^[A-Za-z0-9._%-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
#
# Then you can validate in your code against the pattern like this:
# ESAPI.validator().isValidInput("User Email", input, "Email", maxLength, allowNull);
# Where maxLength and allowNull are set for you needs, respectively.
#
# But note, when you use boolean variants of validation functions, you lose critical
# canonicalization. It is preferable to use the "get" methods (which throw exceptions) and
# and use the returned user input which is in canonical form. Consider the following:
#
# try {
# someObject.setEmail(ESAPI.validator().getValidInput("User Email", input, "Email", maxLength, allowNull));
#
Validator.SafeString=^[.\\p{Alnum}\\p{Space}]{0,1024}$
Validator.Email=^[A-Za-z0-9._%'-]+@[A-Za-z0-9.-]+\\.[a-zA-Z]{2,4}$
Validator.IPAddress=^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$
Validator.URL=^(ht|f)tp(s?)\\:\\/\\/[0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*(:(0-9)*)*(\\/?)([a-zA-Z0-9\\-\\.\\?\\,\\:\\'\\/\\\\\\+=&;%\\$#_]*)?$
Validator.CreditCard=^(\\d{4}[- ]?){3}\\d{4}$
Validator.SSN=^(?!000)([0-6]\\d{2}|7([0-6]\\d|7[012]))([ -]?)(?!00)\\d\\d\\3(?!0000)\\d{4}$

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies an add-header rule.
Protection #1: Any response for a resource will contain a header "FOO" with
a value "BAR".
Exception #1: Any request for /marketing/* will not have any such header
returned.
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<outbound-rules>
<add-header name="FOO" value="BAR" path="/.*">
<path-exception type="regex">/marketing/.*</path-exception>
</add-header>
</outbound-rules>
</policy>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies an add-http-flag rule.
Protection #1: Any cookie set by the application will have the HttpOnly flag set. This
should apply to the application session ID as well as any custom cookies.
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<outbound-rules>
<add-http-only-flag>
<cookie name=".*"/>
</add-http-only-flag>
</outbound-rules>
</policy>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies an add-secure-flag rule.
Protection #1: Any cookie set by the application will have the secure flag set. This
should apply to the application session ID as well as any custom cookies.
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<outbound-rules>
<add-secure-flag>
<cookie name=".*"/>
</add-secure-flag>
</outbound-rules>
</policy>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies an authentication rule.
Authentication applies to: /.*
Session variable whose existence implies authentication: sessionUserObjKey
Static exception: <path-exception>/index.html</path-exception>
Pattern exception: <path-exception type="regex">/images/.*</path-exception>
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>>
<!--
Set authentication rules by path.
-->
<authentication-rules path="/.*" key="sessionUserObjKey" >
<path-exception>/index.html</path-exception>
<path-exception type="regex">/images/.*</path-exception>
</authentication-rules>
</policy>

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies different custom bean shell rules.
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<!--
Import the rules.
-->
<bean-shell-rules>
<bean-shell-script
name="example1"
file="src/test/resources/.esapi/waf-policies/bean-shell-rule.bsh"
stage="before-request-body"/>
</bean-shell-rules>
</policy>

View File

@@ -0,0 +1,5 @@
import org.owasp.esapi.waf.actions.*;
session.setAttribute("simple_waf_test", "true");
action = new RedirectAction();

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a detect-content rule.
Protection #1: The rule should fire whenever the string "2008" appears in
a response body.
Exception #1: The rule should -not- fire when the content type is anything
but text/*.
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<outbound-rules>
<detect-content content-type=".*text/.*" pattern=".*2008.*" />
</outbound-rules>
</policy>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a dynamic-insertion rule.
Protection #1: All instances of "</body>" in the response body will be replaced by
"this is a test".
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<outbound-rules>
<dynamic-insertion pattern="&lt;/body&gt;">
<replacement><![CDATA[this is a test]]></replacement>
</dynamic-insertion>
</outbound-rules>
</policy>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies an enforce-https rule.
Protection #1: a request of any kind for /foo should be redirected to secure request with 302.
Exception #1: Static path /index.html
Exception #2: Pattern path /images/.*
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<url-rules>
<enforce-https path="/.*">
<path-exception>/index.html</path-exception>
<path-exception type="regex">/images/.*</path-exception>
</enforce-https>
</url-rules>
</policy>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a must-match rule.
Protection #1:
Protection applies to: /admin/.*
Header name needed to access: x-roles
Header value needs to *contain* the string: admin
Protection #2:
Protection applies to: /superadmin/.*
Header name needed to access: x-roles
Header value needs to *equal* the string: superadmin
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<authorization-rules>
<must-match path="^/admin/.*" variable="request.header.x-roles"
operator="contains" value="admin" />
<must-match path="^/superadmin/.*" variable="request.header.x-roles"
operator="equals" value="superadmin" />
</authorization-rules>
</policy>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a dynamic-insertion rule.
Protection #1: All instances of "</body>" in the response body will be replaced by
"this is a test".
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<outbound-rules>
<dynamic-insertion pattern="&lt;/body&gt;">
<replacement><![CDATA[this is a test]]></replacement>
</dynamic-insertion>
</outbound-rules>
</policy>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a restrict-content-type rule.
Protection #1: any request with a content-type containing the word 'multipart' will be rejected
Exception #1: requests for /fileupload.jsp are allowed to have 'multipart' in content-type
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<header-rules>
<restrict-content-type deny=".*multipart.*">
<path-exception type="regex">/fileupload.jsp</path-exception>
</restrict-content-type>
</header-rules>
</policy>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a restrict-extension rule.
Protection #1: any URI ending with .log will be rejected
Protection #2: any URI ending with .jsp will be allowed
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<url-rules>
<restrict-extension deny=".*\.log$" />
<restrict-extension allow=".*\.jsp$" />
</url-rules>
</policy>

View File

@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a restrict-extension rule.
Protection #1: any URI ending with .log will be rejected
Protection #2: any URI ending with .jsp will be allowed
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<url-rules>
<restrict-extension deny="\.log$" />
<restrict-extension allow="\.jsp$" />
</url-rules>
</policy>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a restrict-source-ip rule.
The restriction applies to: /admin/.*
Pattern exception: (192\.168\.1\\..*|127.0.0.1)
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<authorization-rules>
<restrict-source-ip
type="regex"
ip-regex="(192\.168\.1\\..*|127.0.0.1)">/admin/.*</restrict-source-ip>
</authorization-rules>
</policy>

View File

@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a restrict-user-agent rule.
Protection #1: any request with a user agent containing the word 'GoogleBot' will be rejected
Exception #1: requests for /index.html are allowed to have 'GoogleBot' in user agent
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<header-rules>
<restrict-user-agent deny=".*GoogleBot.*">
<path-exception type="regex">/index.html</path-exception>
</restrict-user-agent>
</header-rules>
</policy>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
This test file exemplifies a virtual-patch rule.
Protection #1: Any request whose URI is /foo.jsp (despite content-type) will have
the 'bar' parameter checked to see if its alphanumeric. If a parameter
fails validation, the message "zomg attax" will be logged.
-->
<policy>
<settings>
<mode>redirect</mode>
<error-handling>
<default-redirect-page>/security/error.jsp</default-redirect-page>
<block-status>403</block-status>
</error-handling>
</settings>
<virtual-patches>
<virtual-patch id="1234" path="/foo.jsp" variable="request.parameters.bar"
pattern="[0-9a-zA-Z]" message="zomg attax" />
</virtual-patches>
</policy>

Binary file not shown.

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false">
<!--定义日志文件的存储地址 勿在 LogBack 的配置中使用相对路径 -->
<property name="LOG_HOME" value="./logs" />
<!-- 控制台输出 -->
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
%msg%n</pattern>
</encoder>
</appender>
<!-- 按照每天生成日志文件 -->
<appender name="FILE"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<!--日志文件输出的文件名 -->
<FileNamePattern>${LOG_HOME}/cert.log.%d{yyyy-MM-dd}.log
</FileNamePattern>
<!--日志文件保留天数 -->
<MaxHistory>30</MaxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!--格式化输出:%d表示日期%thread表示线程名%-5level级别从左显示5个字符宽度%msg日志消息%n是换行符 -->
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} -
%msg%n</pattern>
</encoder>
<!--日志文件最大的大小 -->
<triggeringPolicy
class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy">
<MaxFileSize>10MB</MaxFileSize>
</triggeringPolicy>
</appender>
<!-- 日志输出级别 -->
<root level="DEBUG">
<appender-ref ref="STDOUT" />
</root>
</configuration>