Commit 23ef575f authored by Guus der Kinderen's avatar Guus der Kinderen Committed by daryl herzmann

OF-1313: Add CSRF protection to the MoTD plugin. (#773)

In an annoying quest to reproduce a bug related to JSTL and plugins I completely redid the MoTD plugin admin console page. I added CSRF protection to justify my changes.

Never did reproduce that bug...
parent 89b37591
...@@ -42,6 +42,12 @@ ...@@ -42,6 +42,12 @@
<h1>MotD Plugin Changelog</h1> <h1>MotD Plugin Changelog</h1>
<p><b>1.2.1</b> -- April 14, 2017</p>
<ul>
<li>Added Cross-Site Request Forgery protection in the admin console page.</li>
<li>Minor visual changed on the admin console page.</li>
</ul>
<p><b>1.2.0</b> -- October 12, 2015</p> <p><b>1.2.0</b> -- October 12, 2015</p>
<ul> <ul>
<li>[<a href='http://www.igniterealtime.org/issues/browse/OF-953'>OF-953</a>] - Updated JSP libraries.</li> <li>[<a href='http://www.igniterealtime.org/issues/browse/OF-953'>OF-953</a>] - Updated JSP libraries.</li>
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
<name>MotD (Message of the Day)</name> <name>MotD (Message of the Day)</name>
<description>Allows admins to have a message sent to users each time they log in.</description> <description>Allows admins to have a message sent to users each time they log in.</description>
<author>Ryan Graham</author> <author>Ryan Graham</author>
<version>1.2.0</version> <version>1.2.1</version>
<date>10/12/2015</date> <date>04/14/2017</date>
<minServerVersion>4.0.0</minServerVersion> <minServerVersion>4.0.0</minServerVersion>
<adminconsole> <adminconsole>
......
...@@ -3,6 +3,7 @@ login.title=Admin Console ...@@ -3,6 +3,7 @@ login.title=Admin Console
motd.title=MotD (Message of the Day) motd.title=MotD (Message of the Day)
motd.options=MotD Options motd.options=MotD Options
motd.saved.success=Settings saved successfully. motd.saved.success=Settings saved successfully.
motd.required=Required fields.
motd.enable=Enable MotD message. motd.enable=Enable MotD message.
motd.directions=Enter the message that will be sent to users when they sign-in. motd.directions=Enter the message that will be sent to users when they sign-in.
motd.subject=Subject motd.subject=Subject
......
...@@ -62,7 +62,7 @@ public class MotDPlugin implements Plugin { ...@@ -62,7 +62,7 @@ public class MotDPlugin implements Plugin {
} }
public void setEnabled(boolean enable) { public void setEnabled(boolean enable) {
JiveGlobals.setProperty(ENABLED, enable ? Boolean.toString(true) : Boolean.toString(false)); JiveGlobals.setProperty(ENABLED, Boolean.toString(enable));
} }
public boolean isEnabled() { public boolean isEnabled() {
......
<%@ page <%@ page
import="org.jivesoftware.openfire.XMPPServer, import="org.jivesoftware.openfire.XMPPServer,
org.jivesoftware.openfire.plugin.MotDPlugin, org.jivesoftware.openfire.plugin.MotDPlugin,
org.jivesoftware.util.CookieUtils,
org.jivesoftware.util.ParamUtils, org.jivesoftware.util.ParamUtils,
java.util.HashMap, org.jivesoftware.util.StringUtils,
java.util.Map" java.util.HashMap"
errorPage="error.jsp"%> errorPage="error.jsp"%>
<%@ page import="java.util.Map" %>
<%@ taglib uri="admin" prefix="admin" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%>
<% <%
boolean save = request.getParameter("save") != null; final boolean save = request.getParameter( "save" ) != null;
boolean motdEnabled = ParamUtils.getBooleanParameter(request, "motdenabled", false); final boolean motdEnabled = ParamUtils.getBooleanParameter( request, "motdenabled", false );
String motdSubject = ParamUtils.getParameter(request, "motdSubject"); final String motdSubject = ParamUtils.getParameter( request, "motdSubject" );
String motdMessage = ParamUtils.getParameter(request, "motdMessage"); final String motdMessage = ParamUtils.getParameter( request, "motdMessage" );
MotDPlugin plugin = (MotDPlugin) XMPPServer.getInstance().getPluginManager().getPlugin("motd"); final Cookie csrfCookie = CookieUtils.getCookie( request, "csrf" );
final String csrfParam = ParamUtils.getParameter( request, "csrf" );
Map<String, String> errors = new HashMap<String, String>();
if (save) { final MotDPlugin plugin = (MotDPlugin) XMPPServer.getInstance().getPluginManager().getPlugin( "motd" );
if (motdSubject == null || motdSubject.trim().length() < 1) {
errors.put("missingMotdSubject", "missingMotdSubject"); final Map<String, String> errors = new HashMap<>();
} if ( save )
{
if (motdMessage == null || motdMessage.trim().length() < 1) { if ( csrfCookie == null || csrfParam == null || !csrfCookie.getValue().equals( csrfParam ) )
errors.put("missingMotdMessage", "missingMotdMessage"); {
} errors.put( "csrf", "CSRF Failure!" );
}
if (errors.size() == 0) {
plugin.setEnabled(motdEnabled); if ( motdSubject == null || motdSubject.trim().length() < 1 )
plugin.setSubject(motdSubject); {
plugin.setMessage(motdMessage); errors.put( "missingMotdSubject", "missingMotdSubject" );
}
response.sendRedirect("motd-form.jsp?settingsSaved=true");
return; if ( motdMessage == null || motdMessage.trim().length() < 1 )
} {
} errors.put( "missingMotdMessage", "missingMotdMessage" );
}
motdEnabled = plugin.isEnabled();
motdSubject = plugin.getSubject(); if ( errors.isEmpty() )
motdMessage = plugin.getMessage(); {
plugin.setEnabled( motdEnabled );
plugin.setSubject( motdSubject );
plugin.setMessage( motdMessage );
response.sendRedirect( "motd-form.jsp?settingsSaved=true" );
return;
}
}
final String csrf = StringUtils.randomString( 15 );
CookieUtils.setCookie( request, response, "csrf", csrf, -1 );
pageContext.setAttribute( "csrf", csrf );
pageContext.setAttribute( "errors", errors );
pageContext.setAttribute( "motdEnabled", plugin.isEnabled() );
pageContext.setAttribute( "motdSubject", plugin.getSubject() );
pageContext.setAttribute( "motdMessage", plugin.getMessage() );
%> %>
<html> <html>
...@@ -49,59 +69,60 @@ ...@@ -49,59 +69,60 @@
</head> </head>
<body> <body>
<form action="motd-form.jsp?save" method="post"> <c:choose>
<c:when test="${not empty param.settingsSaved and empty errors}">
<div class="jive-contentBoxHeader"><fmt:message key="motd.options" /></div> <admin:infoBox type="success"><fmt:message key="motd.saved.success" /></admin:infoBox>
<div class="jive-contentBox"> </c:when>
<c:otherwise>
<% if (ParamUtils.getBooleanParameter(request, "settingsSaved")) { %> <c:forEach var="err" items="${errors}">
<admin:infobox type="error">
<div class="jive-success"> <c:choose>
<table cellpadding="0" cellspacing="0" border="0"> <c:when test="${err.key eq 'missingMotdSubject'}"><fmt:message key="motd.subject.missing"/></c:when>
<tbody> <c:when test="${err.key eq 'missingMotdMessage'}"><fmt:message key="motd.message.missing"/></c:when>
<tr> <c:otherwise>
<td class="jive-icon"><img src="images/success-16x16.gif" width="16" height="16" border="0"></td> <c:if test="${not empty err.value}">
<td class="jive-icon-label"><fmt:message key="motd.saved.success" /></td> <c:out value="${err.value}"/>
</tr> </c:if>
</tbody> (<c:out value="${err.key}"/>)
</table> </c:otherwise>
</div> </c:choose>
</admin:infobox>
<% } %> </c:forEach>
</c:otherwise>
<table cellpadding="3" cellspacing="0" border="0" width="100%"> </c:choose>
<tbody>
<tr>
<td width="1%" align="center" nowrap><input type="checkbox" name="motdenabled" <%=motdEnabled ? "checked" : "" %>></td>
<td width="99%" align="left"><fmt:message key="motd.enable" /></td>
</tr>
</tbody>
</table>
<br><br>
<p><fmt:message key="motd.directions" /></p> <p><fmt:message key="motd.directions" /></p>
<table cellpadding="3" cellspacing="0" border="0" width="100%"> <form action="motd-form.jsp?save" method="post">
<tbody>
<tr> <fmt:message key="motd.options" var="boxtitle"/>
<td width="5%" valign="top"><fmt:message key="motd.subject" />:&nbsp;</td> <admin:contentBox title="${boxtitle}">
<td width="95%"><input type="text" name="motdSubject" value="<%= motdSubject %>"></td>
<% if (errors.containsKey("missingMotdSubject")) { %> <p><input type="checkbox" name="motdenabled" id="motdenabled" ${ motdEnabled ? 'checked' : '' }/> <label for="motdenabled"><fmt:message key="motd.enable" /></label></p>
<span class="jive-error-text"><fmt:message key="motd.subject.missing" /></span>
<% } %> <table cellpadding="3" cellspacing="0" border="0" width="100%">
</tr> <tr>
<tr> <td width="5%" valign="top"><fmt:message key="motd.subject" />:&nbsp;*</td>
<td width="5%" valign="top"><fmt:message key="motd.message" />:&nbsp;</td> <td width="95%"><input type="text" name="motdSubject" value="${motdSubject}"></td>
<td width="95%"><textarea cols="45" rows="5" wrap="virtual" name="motdMessage"><%= motdMessage %></textarea></td> </tr>
<% if (errors.containsKey("missingMotdMessage")) { %> <tr>
<span class="jive-error-text"><fmt:message key="motd.message.missing" /></span> <td width="5%" valign="top"><fmt:message key="motd.message" />:&nbsp;*</td>
<% } %> <td width="95%"><textarea cols="45" rows="5" wrap="virtual" name="motdMessage"><c:out value="${motdMessage}"/></textarea></td>
</tr> </tr>
</tbody> <tr>
</table> <td colspan="2" style="padding-top: 10px"><input type="submit" value="<fmt:message key="motd.button.save" />"/></td>
</div> </tr>
<input type="submit" value="<fmt:message key="motd.button.save" />"/> </table>
</form>
</admin:contentBox>
<span class="jive-description">
* <fmt:message key="motd.required" />
</span>
<input type="hidden" name="csrf" value="${csrf}">
</form>
</body> </body>
</html> </html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment