//NAME=Validate Input //DESCRIPTION=Validate input and protect output. //VERSION=1.2[R] import java.util.Hashtable; import java.util.Enumeration; import org.htmlparser.Node; import org.htmlparser.RemarkNode; import org.htmlparser.Parser; import org.htmlparser.tags.InputTag; import org.htmlparser.tags.LinkTag; import org.htmlparser.tags.SelectTag; import org.htmlparser.tags.OptionTag; import org.htmlparser.tags.FormTag; import org.htmlparser.tags.HeadTag; import org.htmlparser.util.NodeIterator; import org.htmlparser.util.NodeList; import org.htmlparser.util.ParserException; import org.htmlparser.util.SimpleNodeIterator; import org.htmlparser.filters.NodeClassFilter; import org.htmlparser.visitors.TagFindingVisitor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServlet; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.jsp.JspWriter; import javax.servlet.jsp.PageContext; import javax.servlet.http.Cookie; import java.io.Writer; import java.io.PrintWriter; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import javax.crypto.Cipher; import com.unisys.security.input.validation.Validator; import com.unisys.security.input.validation.ValidatorFactory; import com.unisys.security.input.validation.ValidatorSupport; import com.unisys.security.input.validation.CustomInput; aspect Protect_Validate { public static String APP_NAME = ""; private static String DIR_PROPERTY = ""; private static String BASE_DIR = ""; private static final byte[] encodedKey = {}; // Nationalizable strings private static String FORCED1 = "Forced browsing [URL="; private static String FORCED2 = "Forced browsing!"; private static String TAMPERED1 = " changed to "; private static String TAMPERED2 = " tampered!"; private static String BADCOOKIE1 = "Bad cookie ["; private static String BADCOOKIE2 = "Bad cookie!"; private static String BADHEADER1 = "Bad header ["; private static String BADHEADER2 = "Bad header!"; private static String SESSION1 = "Session riding [URL="; private static String SESSION2 = "Session riding!"; private static String MISSING = "Missing "; private static String MISSING_COOKIE1 = MISSING + "cookie "; private static String MISSING_COOKIE2 = MISSING + "cookie!"; // End private static String HIDDEN = "hidden"; private static String RADIO = "radio"; private static String CHECKBOX = "checkbox"; private static String READONLY = "readonly"; private static String MAXLENGTH = "maxlength"; private static String PASSWORD = "password"; private static String[] TYPES = {HIDDEN, RADIO, CHECKBOX, READONLY, MAXLENGTH, PASSWORD}; private static String SELECT = "select"; private static String FORCED = "forced"; private static String RANDOM = "random"; private static String THIS_URL = "url"; private static boolean FORCED_BROWSING = true; private static boolean HTML_FORMS = true; private static boolean REMOVE_COMMENTS = true; private static boolean ACTIVE_MODE = true; private static boolean COOKIES = true; private static boolean HEADERS = true; private static boolean SUPPRESS_STACKTRACE = true; private static boolean SESSION_RIDING = false; private static boolean DEBUG = false; private static boolean CUSTOM = false; private ThreadLocal httpRequest = new ThreadLocal(); private ThreadLocal respString = new ThreadLocal(); private ThreadLocal httpResponse = new ThreadLocal(); private ThreadLocal redirected = new ThreadLocal(); private ThreadLocal randomTLS = new ThreadLocal(); private ThreadLocal forcedTLS = new ThreadLocal(); private ThreadLocal selectTLS = new ThreadLocal(); private ThreadLocal[] variousTLS = new ThreadLocal[TYPES.length]; private static Validator v = ValidatorFactory.getValidator(APP_NAME, DIR_PROPERTY); private static ValidatorSupport support = new ValidatorSupport(BASE_DIR); private static CustomInput custom; private static String host = null; private static int port = 0; private static boolean firstTime = true; private static SecretKey key; private static Cipher cipher; private java.util.Random random = new java.util.Random(); static { try { cipher = Cipher.getInstance("DES/ECB/PKCS5Padding"); key = new SecretKeySpec(encodedKey, "DES"); } catch (Exception e) { System.out.println(e); } } private String encryptString(String encryptString) { if (encryptString == null) return null; try { cipher.init(Cipher.ENCRYPT_MODE, key); byte[] encrypted = cipher.doFinal(encryptString.getBytes("UTF8")); return new sun.misc.BASE64Encoder().encode(encrypted); } catch (Exception e) { System.out.println(e + ": encrypting " + encryptString); return encryptString; } } private String decryptString(String decryptString) { if (decryptString == null) return null; try { byte[] decoded = new sun.misc.BASE64Decoder().decodeBuffer(decryptString); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decrypted = cipher.doFinal(decoded); return new String(decrypted, "UTF8"); } catch (Exception e) { System.out.println(e + ": decrypting " + decryptString); return decryptString; } } private static boolean checkForOption(String option) { try { Class.forName("Protect_" + option + ""); return true; } catch (ClassNotFoundException e) { return false; } } private static boolean checkForCustom() { try { Object[] args = new Object[0]; Class[] params = new Class[0]; Class c = Class.forName("Custom_Input"); custom = (CustomInput)c.getConstructor(params).newInstance(args); return true; } catch (Exception e) { return false; } } static { FORCED_BROWSING = checkForOption("ForcedBrowsing"); HTML_FORMS = checkForOption("HTMLForms"); REMOVE_COMMENTS = checkForOption("RemoveComments"); ACTIVE_MODE = checkForOption("ActiveMode"); COOKIES = checkForOption("Cookies"); HEADERS = checkForOption("Headers"); SUPPRESS_STACKTRACE = checkForOption("SuppressStackTrace"); DEBUG = checkForOption("DebugOn"); CUSTOM = checkForCustom(); if (CUSTOM) SESSION_RIDING = custom.supportsSessionRiding(); } pointcut withinProtect(): within(Protect*); pointcut withinCustom(): within(Custom*); pointcut suppressStackTrace(Throwable t): call(public void *.printStackTrace(..)) && target(t); pointcut write(String value): (call(public void Writer+.write(String, ..)) || call(public void JspWriter+.write(String, ..)) || call(public void PrintWriter+.write(String, ..))) && args(value) && !withinProtect() && !withinCustom(); pointcut writeChar(char value): (call(public void Writer+.write(char)) || call(public void JspWriter+.write(char)) || call(public void PrintWriter+.write(char))) && args(value) && !withinProtect() && !withinCustom(); pointcut writeChars(char[] value): (call(public void Writer+.write(char[], ..)) && call(public void JspWriter+.write(char[], ..)) || call(public void PrintWriter+.write(char[], ..))) && args(value) && !withinProtect() && !withinCustom(); pointcut writeInt(int value): (call(public void Writer+.write(int)) && call(public void JspWriter+.write(int)) || call(public void PrintWriter+.write(int))) && args(value) && !withinProtect() && !withinCustom(); pointcut print(String value): (call(public void JspWriter+.print*(String, ..)) || call(public void PrintWriter+.print*(String, ..))) && args(value) && !withinProtect() && !withinCustom(); pointcut printChar(char value): (call(public void JspWriter+.print*(char)) || call(public void PrintWriter+.print*(char))) && args(value) && !withinProtect() && !withinCustom(); pointcut printChars(char[] value): (call(public void JspWriter+.print*(char[], ..)) || call(public void PrintWriter+.print*(char[], ..))) && args(value) && !withinProtect() && !withinCustom(); pointcut printInt(int value): (call(public void JspWriter+.print*(int)) || call(public void PrintWriter+.print*(int))) && args(value) && !withinProtect() && !withinCustom(); pointcut printFloat(float value): (call(public void JspWriter+.print*(float)) || call(public void PrintWriter+.print*(float))) && args(value) && !withinProtect() && !withinCustom(); pointcut printDouble(double value): (call(public void JspWriter+.print*(double)) || call(public void PrintWriter+.print*(double))) && args(value) && !withinProtect() && !withinCustom(); pointcut printLong(long value): (call(public void JspWriter+.print*(long)) || call(public void PrintWriter+.print*(long))) && args(value) && !withinProtect() && !withinCustom(); pointcut printObject(Object value): (call(public void JspWriter+.print*(Object)) || call(public void PrintWriter+.print*(Object))) && args(value) && !withinProtect() && !withinCustom(); pointcut handlePageException(): call(public void PageContext.handlePageException(..)) && !withinProtect() && !withinCustom(); pointcut doIt( HttpServletRequest request, HttpServletResponse response, HttpServlet servlet): (execution(public void *._jspService(HttpServletRequest, HttpServletResponse)) || execution(public void *.doGet(HttpServletRequest, HttpServletResponse)) || execution(public void *.doPost(HttpServletRequest, HttpServletResponse))) && args(request, response) && target(servlet) && !withinProtect() && !withinCustom(); pointcut Params(String param, HttpServletRequest request): call (public String[] ServletRequest+.getParameterValues(String)) && args(param) && target(request) && !withinCustom() && !withinProtect(); pointcut Param(String param, HttpServletRequest request): call (public String ServletRequest+.getParameter(String)) && args(param) && target(request) && !withinCustom() && !withinProtect() && excludeThese(); pointcut excludeThese(): !within(org.springframework..*) && !within(org.apache.struts..*) && !within(*.taglib..*) && !within(org.apache.taglibs..*) && !within(org.displaytag..*); pointcut redirectOrForward(String value): (call(public void PageContext.forward(String)) || call(public void HttpServletResponse.sendRedirect(String))) && args(value); private boolean hasBeenTampered( String name, String value, String[] values) { if (CUSTOM) if (custom.skipThisField(name)) return false; for (int i = 0; i < values.length; i++) { String[] vals = values[i].split("--"); if (name.equals(vals[0])) { if (vals.length > 1) { if (value.equals(vals[1])) return false; } else if (value.equals("")) return false; } } return true; } private void error( String log, String display, HttpServletRequest request, HttpServletResponse response) { String user = request.getRemoteUser(); String remote = request.getRemoteHost(); v.logger.logFatal(log + " [" + user + ", " + remote + "]"); if (ACTIVE_MODE) try { response.sendError(500, display); HttpSession session = request.getSession(); if (session != null) session.invalidate(); } catch (Exception e) {} } private String getStateString(String[] state, int index) { try { String[] temp = state[index].split("=="); if (temp.length < 2) return null; return temp[1]; } catch (Exception e) { return null; } } private String currentURL(HttpServletRequest request) { String path = request.getRequestURL().toString(); String queryString = request.getQueryString(); String URL = path; if (queryString != null) { URL = URL + "?" + queryString; } return URL; } private static String convertMetachars(String token) { String result = token; int mci = 0; int mcLocation = 0; char[] metaChar = {'&', '<', '>', '"', '\t', '\n'}; String[] htmlCode = {"&", "<", ">", """, " ", "
"}; for (; mci < metaChar.length; mci += 1) { mcLocation = 0; while ((mcLocation = result.indexOf(metaChar[mci], mcLocation)) > -1) { result = result.substring(0, mcLocation) + htmlCode[mci] + result.substring(mcLocation + 1); mcLocation += 1; } } return (result); } private boolean forcedBrowsing( String state[], HttpServletRequest request, HttpServletResponse response) { if (!FORCED_BROWSING) return false; if (redirected.get() != null) { return false; } String URL = currentURL(request); if (CUSTOM) { int result = custom.triggerURL(URL); if (result != 0) { String URLs = getStateString(state, TYPES.length + 1); if (URLs != null) { Hashtable forced = (Hashtable)forcedTLS.get(); if (forced == null) forced = new Hashtable(); String[] values = URLs.split("::"); for (int i = 0; i < values.length; i++) forced.put(values[i], values[i]); forcedTLS.set(forced); } if (result == 2) return false; } } String URLs = getStateString(state, TYPES.length + 1); if (URLs == null) return false; if (DEBUG) { System.out.println("URL=" + URL); System.out.println("Links=" + URLs); } String[] values = URLs.split("::"); String convertedURL = convertMetachars(URL); for (int i = 0; i < values.length; i++) { String link = values[i]; if (URL.endsWith(link) || link.endsWith(URL)) return false; if (convertedURL.endsWith(link) || link.endsWith(convertedURL)) return false; } if (CUSTOM) { if (custom.skipForcedBrowsingErrorOn(URL)) return false; } error(FORCED1 + URL + "].", FORCED2, request, response); if (ACTIVE_MODE) return true; return false; } private int readStateCookie( HttpServletRequest request, HttpServletResponse response, HttpSession s) { String name = support.COOKIE_NAME; Cookie[] cookies = request.getCookies(); if (cookies != null) { for (int i = 0; i < cookies.length; i++) { if (name.equals(cookies[i].getName())) { String encrypted = cookies[i].getValue(); String value = decryptString(encrypted); if (value == null) { error(MISSING_COOKIE1 + name.toUpperCase() + ".", MISSING_COOKIE2, request, response); if (ACTIVE_MODE) return 2; return 0; } else if (value.equals(encrypted)) { // decryption failed. try { if (s.getAttribute("first") == null) return 1; } catch (IllegalStateException e) { return 1; } } try { String[] values = value.split("::"); host = values[0]; port = Integer.parseInt(values[1]); } catch (Exception e) { error( name.toUpperCase() + TAMPERED2, name.toUpperCase() + TAMPERED2, request, response); if (ACTIVE_MODE) return 2; } return 0; } } } try { if (s.getAttribute("first") == null) return 1; } catch (IllegalStateException e) { return 1; } error(MISSING_COOKIE1 + name.toUpperCase() + ".", MISSING_COOKIE2, request, response); if (ACTIVE_MODE) return 2; return 0; } private void writeStateCookie( String host, int port, HttpServletResponse response) { Cookie uni = new Cookie(ValidatorSupport.COOKIE_NAME, ""); uni.setValue(encryptString(host + "::" + String.valueOf(port))); uni.setPath("/"); response.addCookie(uni); } private boolean validate( String[] types, String[] state, HttpServletRequest request, HttpServletResponse response) { if (!HTML_FORMS) return true; String[] values = new String[0]; String value = null; String key = null; // Validate TYPES for (int i = 0; i < types.length; i++) { String type = types[i]; String temp = getStateString(state, i); if (temp == null) continue; values = temp.split("::"); for (int j = 0; j < values.length; j++) { key = values[j].split("--")[0]; value = request.getParameter(key); if (value == null) { if (type.equals(PASSWORD)) { error(MISSING + type.toUpperCase() + ": " + key, MISSING + type.toUpperCase(), request, response); if (ACTIVE_MODE) return false; } } else { if (DEBUG) System.out.println("Checking " + type.toUpperCase() + ": " + key + "=" + value); if (type.equals(MAXLENGTH)) { int maxLength = 0; String max = null; try { max = values[1]; if (max.indexOf("--") != -1) max = max.substring(max.indexOf("--") + 2, max.length()); maxLength = Integer.parseInt(max); } catch (Exception e) { System.out.println(max + ": " + e); } if ((value.length() > maxLength) && (maxLength > 0)) { error( type.toUpperCase() + " " + key + TAMPERED1 + value + ".", type.toUpperCase() + TAMPERED2, request, response); if (ACTIVE_MODE) return false; } } else if (!type.equals(PASSWORD)) { if (hasBeenTampered(key, value, values)) { error( type.toUpperCase() + " " + key + TAMPERED1 + value + ".", type.toUpperCase() + TAMPERED2, request, response); if (ACTIVE_MODE) return false; } } } } } // Validate SELECT options. String temp = getStateString(state, TYPES.length); if (temp == null) return true; String[] selects = temp.split("@@"); try { for (int i = 0; i < selects.length; i++) { String[] keyValue = selects[i].split("--"); key = keyValue[0]; value = request.getParameter(key); if (value != null) { values = keyValue[1].split("::"); if (DEBUG) System.out.println("Checking " + SELECT.toUpperCase() + ": " + key + "=" + value); boolean OK = false; for (int j = 0; j < values.length; j++) { if (values[j].startsWith(value)) { OK = true; break; } } if (!OK) { error( SELECT.toUpperCase() + " " + key + TAMPERED1 + value + ".", SELECT.toUpperCase() + TAMPERED2, request, response); if (ACTIVE_MODE) return false; } } } } catch (Exception e) { error(SELECT.toUpperCase() + TAMPERED2, SELECT.toUpperCase() + TAMPERED2, request, response); if (ACTIVE_MODE) return false; } return true; } private void clearTLS() { httpRequest.set(null); httpResponse.set(null); respString.set(null); for (int i = 0; i < TYPES.length; i++) variousTLS[i].set(null); forcedTLS.set(null); selectTLS.set(null); randomTLS.set(null); redirected.set(null); } private void writeState(String host, int port, String sessionId) { if (!HTML_FORMS && !FORCED_BROWSING && !SESSION_RIDING) return; String state = ""; for (int i = 0; i < TYPES.length; i++) { String temp = (String)variousTLS[i].get(); if (temp == null) temp = ""; if (state.equals("")) state = TYPES[i] + "==" + temp; else state = state + "\n" + TYPES[i] + "==" + temp; } String values = ""; Hashtable h = (Hashtable)selectTLS.get(); if (h != null) { for (Enumeration e = h.keys(); e.hasMoreElements();) { String key = (String)e.nextElement(); String value = (String)h.get(key); if (values.equals("")) values = key + "--" + value; else values = values + "@@" + key + "--" + value; } } state = state + "\n" + SELECT + "==" + values; values = ""; h = (Hashtable)forcedTLS.get(); if (h != null) { for (Enumeration e = h.elements(); e.hasMoreElements();) if (values.equals("")) values = (String)e.nextElement(); else values = values + "::" + (String)e.nextElement(); } state = state + "\n" + FORCED + "==" + values; state = state + "\n" + RANDOM + "==" + (String)randomTLS.get(); support.writeState( host, port, encryptString(APP_NAME), encryptString(sessionId), encryptString(state)); } private void findAndStore( String[] types, Node[] inputs) { for (int i = 0; i < types.length; i++) { String type = types[i]; String values = (String)variousTLS[i].get(); if (values == null) values = ""; String value = null; String name = null; for (int j = 0; j < inputs.length; j++) { InputTag inputTag = (InputTag)inputs[j]; if (type.equals(MAXLENGTH) || type.equals(READONLY)) { value = inputTag.getAttribute(type); if (value != null) { if (type.equals(READONLY)) value = inputTag.getAttribute("value"); if ((value != null) && !value.equals("")) { name = inputTag.getAttribute("name"); if (DEBUG) System.out.println(type.toUpperCase() + " for " + name + "=" + value); if (values.equals("")) values = name + "--" + value; else values = values + "::" + name + "--" + value; } } } else { if (inputTag.getAttribute("type") == null) continue; if (inputTag.getAttribute("type").toLowerCase().equals(type)) { value = inputTag.getAttribute("value"); if (value == null) value = ""; name = inputTag.getAttribute("name"); if (type.equals(PASSWORD) && name.equals("j_password")) continue; if (DEBUG) System.out.println("Found " + type.toUpperCase() + ": " + name + "=" + value); if (values.equals("")) values = name + "--" + value; else values = values + "::" + name + "--" + value; } } } variousTLS[i].set(values); } } private void protectOutput( String output, HttpServletRequest request) { if (output == null) return; Parser parser = new Parser(); parser.setFeedback(Parser.noFeedback); if (HTML_FORMS) { // Look for static fields (HIDDEN, RADIO, etc.). Node[] inputs = null; try { parser.setInputHTML(output); inputs = parser.extractAllNodesThatAre(InputTag.class); } catch (ParserException e) { System.out.println(e); } if (inputs != null) { findAndStore(TYPES, inputs); } // Look for SELECT options. Node[] selects = null; try { parser.reset(); String[] tagsToBeFound = {SELECT}; TagFindingVisitor visitor = new TagFindingVisitor(tagsToBeFound); parser.visitAllNodesWith(visitor); selects = visitor.getTags(0); if (selects != null) { Hashtable h = (Hashtable)selectTLS.get(); if (h == null) h = new Hashtable(); for (int i = 0; i < selects.length; i++) { String choices = null; SelectTag select = null; if (selects[i] instanceof SelectTag) select = (SelectTag)selects[i]; if (select != null) { for (SimpleNodeIterator children = select.children(); children.hasMoreNodes();) { Node node = children.nextNode(); if (node instanceof OptionTag) { OptionTag child = (OptionTag)node; String value = child.getValue(); if (value == null) value = child.getOptionText(); if (choices == null) choices = value; else choices = choices + "::" + value; } } } if (choices != null) { String name = select.getAttribute("name"); if (name != null) { if (DEBUG) System.out.println("Found SELECT: " + name + "=" + choices); h.put(name, choices); } } } selectTLS.set(h); } } catch (ParserException e) { System.out.println(e); } } // Extract HREFs and FORM ACTIONs if (!FORCED_BROWSING) return; Hashtable linksAndActions = (Hashtable)forcedTLS.get(); if (linksAndActions == null) linksAndActions = new Hashtable(); Node[] refs = null; try { parser.setInputHTML(output); refs = parser.extractAllNodesThatAre(LinkTag.class); } catch (ParserException e) { System.out.println(e); } if (refs != null) { for (int i = 0; i < refs.length; i++) { LinkTag link = (LinkTag)refs[i]; String extracted = link.extractLink(); if (link.isHTTPLikeLink()) { if ((extracted != null) && !extracted.equals("")) linksAndActions.put(extracted, extracted); } else if ((extracted != null) && !extracted.equals("")) { String delimeter = ""; if (extracted.indexOf("window.open") != -1) { if (extracted.indexOf("\"") != -1) delimeter = "\""; else if (extracted.indexOf("'") != -1) delimeter = "'"; else continue; extracted = extracted.substring(extracted.indexOf(delimeter) + 1, extracted.length()); extracted = extracted.substring(0, extracted.indexOf(delimeter)); linksAndActions.put(extracted, extracted); } } } } Node[] forms = null; try { parser.reset(); refs = parser.extractAllNodesThatAre(FormTag.class); } catch (ParserException e) { System.out.println(e); } if (refs != null) { for (int i = 0; i < refs.length; i++) { FormTag form = (FormTag)refs[i]; String action = form.getFormLocation(); if ((action != null) && !action.equals("")) linksAndActions.put(action, action); } } Node[] makeWindows = null; try { parser.reset(); makeWindows = parser.extractAllNodesThatAre(InputTag.class); } catch (ParserException e) { System.out.println(e); } if (makeWindows != null) { for (int i = 0; i < makeWindows.length; i++) { InputTag input = (InputTag)makeWindows[i]; String onClick = input.getAttribute("onClick"); if (onClick != null) { if (onClick.toLowerCase().startsWith("makewindow")) { String[] parsed = onClick.split("'"); String URL = parsed[1].trim(); linksAndActions.put(URL, URL); } } } } forcedTLS.set(linksAndActions); } private String appendAndClean(String value) { if (value == null) return value; // Remove comments from HTML. String reAssembled = ""; if (REMOVE_COMMENTS) { String[] comments = value.split("!--"); if ((comments != null) && (comments.length > 0)) { reAssembled = comments[0]; for (int i = 1; i < comments.length; i++) { String comment = comments[i]; if ((comment.indexOf("--") == -1) || (comment.indexOf("// --") != -1) || (comment.indexOf("//--") != -1)) reAssembled = reAssembled + "!-- " + comment; else reAssembled = reAssembled + "!-- ******* " + comment.substring(comment.indexOf("--"), comment.length()); } if (value.endsWith("!--")) reAssembled = reAssembled + "!--"; } } else reAssembled = value; if (SESSION_RIDING) reAssembled = custom.sessionRiding(reAssembled, (String)randomTLS.get()); if (CUSTOM) { HttpServletRequest request = (HttpServletRequest)httpRequest.get(); String url = currentURL(request); if (custom.skipURL(url)) return reAssembled; } if (HTML_FORMS || FORCED_BROWSING) { String response = (String)respString.get(); if (response == null) respString.set(reAssembled); else respString.set(response + reAssembled); } return reAssembled; } void around(String value): write(value) { proceed(appendAndClean(value)); } void around(char value): writeChar(value) { appendAndClean(Character.toString(value)); proceed(value); } void around(char[] value): writeChars(value) { appendAndClean(new String(value)); proceed(value); } void around(int value): writeInt(value) { appendAndClean(Character.toString((char)value)); proceed(value); } void around(String value): print(value) { proceed(appendAndClean(value)); } void around(char value): printChar(value) { appendAndClean(String.valueOf(value)); proceed(value); } void around(char[] value): printChars(value) { appendAndClean(new String(value)); proceed(value); } void around(int value): printInt(value) { appendAndClean(String.valueOf(value)); proceed(value); } void around(float value): printFloat(value) { appendAndClean(String.valueOf(value)); proceed(value); } void around(double value): printDouble(value) { appendAndClean(String.valueOf(value)); proceed(value); } void around(long value): printLong(value) { appendAndClean(String.valueOf(value)); proceed(value); } void around(Object value): printObject(value) { appendAndClean(String.valueOf(value)); proceed(value); } before (): handlePageException() { respString.set(null); } before(String value): redirectOrForward(value) { redirected.set(value); } String[] around (String param, HttpServletRequest request): Params(param, request) { String[] results = proceed(param, request); if (results == null) { return results; } String[] validatedResults = new String[results.length]; for (int i = 0; i < results.length; i++) { if (DEBUG) System.out.println("Params: " + param + "=" + results[i]); String result = results[i]; if (CUSTOM) result = custom.preProcess(param, result, v, request); validatedResults[i] = v.validateParameter(param, result); if (CUSTOM) validatedResults[i] = custom.postProcess(param, validatedResults[i], v, request); } return validatedResults; } String around (String param, HttpServletRequest request): Param(param, request) { String result = proceed(param, request); if (DEBUG) System.out.println("Param: " + param + "=" + result); if (CUSTOM) result = custom.preProcess(param, result, v, request); result = v.validateParameter(param, result); if (CUSTOM) result = custom.postProcess(param, result, v, request); return result; } private void cookiesAndHeaders( HttpServletRequest request, HttpServletResponse response) { if (COOKIES) { javax.servlet.http.Cookie[] results = request.getCookies(); if (results == null) return; for (int i = 0; i < results.length; i++) { String name = results[i].getName(); if (!name.equals(ValidatorSupport.COOKIE_NAME)) { String value = results[i].getValue(); if (DEBUG) System.out.println("COOKIE " + name + "=" + value); if (!v.validateCookie(name, value).equals(value)) { error( BADCOOKIE1 + name + "=" + value + "].", BADCOOKIE2, request, response); if (ACTIVE_MODE) return; } } } } if (HEADERS) { java.util.Enumeration headers = request.getHeaderNames(); while (headers.hasMoreElements()) { String name = (String)headers.nextElement(); String header = request.getHeader(name); if (DEBUG) System.out.println("HEADER " + name + "=" + header); if (!name.equals("referer")) { if (!v.validateHeader(request, name, header).equals(header)) { error( BADHEADER1 + name + "=" + header + "].", BADHEADER2, request, response); if (ACTIVE_MODE) return; } } } } } void around(Throwable t): suppressStackTrace(t) { if (SUPPRESS_STACKTRACE) { java.lang.StackTraceElement elem[] = t.getStackTrace(); System.out.println(t.getMessage()); if (elem != null) for (int i = 0; i < elem.length; i++) System.out.println(elem[i].toString()); } else proceed(t); } private boolean sessionRiding( String[] state, HttpServletRequest request, HttpServletResponse response) { if (!SESSION_RIDING) return false; if (custom.skipSessionRidingErrorOn(currentURL(request))) return false; String r = getStateString(state, TYPES.length + 2); if (r == null) return false; String value = request.getParameter("secret"); if ((value == null) || (!value.equals(r))) { error(SESSION1 + currentURL(request) + "].", SESSION2, request, response); if (ACTIVE_MODE) return true; } return false; } void around( HttpServletRequest request, HttpServletResponse response, HttpServlet servlet): doIt(request, response, servlet) { if (httpRequest.get() != null) { proceed(request, response, servlet); protectOutput((String)respString.get(), request); respString.set(null); return; } cookiesAndHeaders(request, response); HttpSession s = request.getSession(); String id = s.getId(); host = support.localHost; port = support.port; if (firstTime) { for (int i = 0; i < TYPES.length; i++) { variousTLS[i] = new ThreadLocal(); } firstTime = false; } String[] state = null; if (HTML_FORMS || FORCED_BROWSING || SESSION_RIDING) { int result = readStateCookie(request, response, s); if (result == 2) return; if (result == 0) { String temp = (String)support.readAndRemoveState( host, port, encryptString(APP_NAME), encryptString(id)); if (temp == null) port = 0; else { if (!temp.equals(ValidatorSupport.NO_STATE)) temp = decryptString(temp); state = temp.split("\n"); if (request.getMethod().equals("POST")) { if (!validate(TYPES, state, request, response)) { support.writeState( host, port, encryptString(APP_NAME), encryptString(id), encryptString(temp)); return; } } if (sessionRiding(state, request, response)) { support.writeState( host, port, encryptString(APP_NAME), encryptString(id), encryptString(temp)); return; } if (forcedBrowsing(state, request, response)) { support.writeState( host, port, encryptString(APP_NAME), encryptString(id), encryptString(temp)); return; } } } } httpRequest.set(request); httpResponse.set(response); if (state != null) randomTLS.set(getStateString(state, TYPES.length+2)); else randomTLS.set(String.valueOf(random.nextInt(100000)).trim()); if (HTML_FORMS || FORCED_BROWSING || SESSION_RIDING) { if (port == 0) writeStateCookie(support.localHost, support.port, response); else writeStateCookie(host, port, response); } proceed(request, response, servlet); protectOutput((String)respString.get(), request); if (HTML_FORMS || FORCED_BROWSING || SESSION_RIDING) { if (port == 0) writeState(support.localHost, support.port, id); else writeState(host, port, id); } clearTLS(); v.generateRules(); } }