/*********************************************************************** * * $CVSHeader$ * * This file is part of WebScarab, an Open Web Application Security * Project utility. For details, please see http://www.owasp.org/ * * Copyright (c) 2002 - 2004 Rogan Dawes * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Getting Source * ============== * * Source for this application is maintained at Sourceforge.net, a * repository for free software projects. * * For details, please see http://www.sourceforge.net/projects/owasp * */ /* * RevealHidden.java * * Created on July 13, 2003, 7:39 PM */ package org.owasp.webscarab.plugin.proxy; // import org.owasp.util.StringUtil; import org.owasp.webscarab.httpclient.HTTPClient; import org.owasp.webscarab.model.Preferences; import org.owasp.webscarab.model.Request; import org.owasp.webscarab.model.Response; import org.owasp.webscarab.plugin.proxy.ProxyPlugin; import java.io.IOException; import java.util.regex.Pattern; import java.util.regex.Matcher; /** * * @author rdawes */ public class RevealHidden extends ProxyPlugin { private boolean _enabled = false; /** Creates a new instance of RevealHidden */ public RevealHidden() { parseProperties(); } public void parseProperties() { String prop = "RevealHidden.enabled"; String value = Preferences.getPreference(prop, "false"); _enabled = ("true".equalsIgnoreCase( value ) || "yes".equalsIgnoreCase( value )); } public String getPluginName() { return new String("Reveal Hidden"); } public void setEnabled(boolean bool) { _enabled = bool; String prop = "RevealHidden.enabled"; Preferences.setPreference(prop,Boolean.toString(bool)); } public boolean getEnabled() { return _enabled; } public HTTPClient getProxyPlugin(HTTPClient in) { return new Plugin(in); } private class Plugin implements HTTPClient { private HTTPClient _in; public Plugin(HTTPClient in) { _in = in; } public Response fetchResponse(Request request) throws IOException { Response response = _in.fetchResponse(request); if (_enabled) { String ct = response.getHeader("Content-Type"); if (ct != null && ct.matches("text/.*")) { byte[] content = response.getContent(); if (content != null) { response.setContent(revealHidden(content)); response.addHeader("X-RevealHidden", "possibly modified"); } } } return response; } private byte[] revealHidden(byte[] content) { /* We split this pattern into two parts, one before "hidden" and one after * Then it is simple to concatenate part 1 + "text" + part 2 to get an * "unhidden" input tag */ Pattern inputPattern = Pattern.compile("(<input.+?type\\s*=\\s*[\"']{0,1})hidden([\"']{0,1}.+?>)", Pattern.CASE_INSENSITIVE); Matcher inputMatcher = inputPattern.matcher(new String(content)); StringBuffer outbuf = new StringBuffer(); /* matched hidden input parameter */ while(inputMatcher.find()) { String input = inputMatcher.group(); String name = "noname"; // extract hidden field name Pattern namePattern = Pattern.compile("name=[\"']{0,1}(\\w+)[\"']{0,1}", Pattern.CASE_INSENSITIVE); Matcher nameMatcher = namePattern.matcher(input); if (nameMatcher.find() && nameMatcher.groupCount() == 1){ name = nameMatcher.group(1); } // make hidden field a text field - there MUST be 2 groups // Note: this way we don't have to care about which quotes are being used input = inputMatcher.group(1) + "text" + inputMatcher.group(2); /* insert [hidden] <fieldname> before the field itself */ // inputMatcher.appendReplacement(outbuf, "<STRONG style=\"background-color: white;\"> [hidden field name =\"" + name + "\"]:</STRONG> "+ input + "<BR/>"); inputMatcher.appendReplacement(outbuf, constructReplacement(name, input)); } inputMatcher.appendTail(outbuf); return outbuf.toString().getBytes(); } private String constructReplacement(final String name, final String input) { final StringBuffer result = new StringBuffer(); result.append("<div style=\"background: pink; border: red 1px solid; padding: 2px; margin:4px; text-align: left;\">"); result.append("<p style=\"color: red; text-align: left; margin-top: 0px; font-size: xx-small;\">Hidden Input Field</p>"); result.append("<p style=\"text-align: center; color: black; margin: 0px; font-size: normal;\">"); result.append("[").append(name).append("]").append(" ").append(input); result.append("</p>"); result.append("<p style=\"color: red; text-align: right; margin-bottom: 0px; font-size: xx-small;\">Revealed by WebScarab</p>"); result.append("</div>"); return result.toString(); } } }