mirror of https://github.com/apache/activemq.git
https://issues.apache.org/activemq/browse/AMQ-2613 - prevent CSRF attacks
git-svn-id: https://svn.apache.org/repos/asf/activemq/trunk@915384 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
f24edca190
commit
9dc43f3ffe
|
@ -39,4 +39,10 @@ public class CreateDestination extends DestinationFacade implements Controller {
|
|||
return redirectToBrowseView();
|
||||
}
|
||||
|
||||
public String[] getSupportedHttpMethods() {
|
||||
return new String[]{"POST"};
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -50,5 +50,9 @@ public class CreateSubscriber extends DurableSubscriberFacade implements Control
|
|||
getBrokerAdmin().createDurableSubscriber(getClientId(), getSubscriberName(), getValidDestination(), selector);
|
||||
return new ModelAndView("redirect:subscribers.jsp");
|
||||
}
|
||||
|
||||
public String[] getSupportedHttpMethods() {
|
||||
return new String[]{"POST"};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -230,4 +230,8 @@ public class SendMessage extends DestinationFacade implements Controller {
|
|||
// allow JMSX extensions or non JMS properties
|
||||
return name.startsWith("JMSX") || !name.startsWith("JMS");
|
||||
}
|
||||
|
||||
public String[] getSupportedHttpMethods() {
|
||||
return new String[]{"POST"};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,8 +16,12 @@
|
|||
*/
|
||||
package org.apache.activemq.web.handler;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.activemq.web.DestinationFacade;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.web.bind.ServletRequestDataBinder;
|
||||
|
@ -41,8 +45,21 @@ public class BindingBeanNameUrlHandlerMapping extends BeanNameUrlHandlerMapping
|
|||
HandlerExecutionChain handlerExecutionChain = (HandlerExecutionChain) object;
|
||||
object = handlerExecutionChain.getHandler();
|
||||
}
|
||||
|
||||
|
||||
if (object != null) {
|
||||
// prevent CSRF attacks
|
||||
if (object instanceof DestinationFacade) {
|
||||
// check supported methods
|
||||
if (!Arrays.asList(((DestinationFacade)object).getSupportedHttpMethods()).contains(request.getMethod())) {
|
||||
throw new UnsupportedOperationException("Unsupported method " + request.getMethod() + " for path " + request.getRequestURI());
|
||||
}
|
||||
// check the 'secret'
|
||||
if (!request.getSession().getAttribute("secret").equals(request.getParameter("secret"))) {
|
||||
throw new UnsupportedOperationException("Possible CSRF attack");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(object, "request");
|
||||
try {
|
||||
binder.bind(request);
|
||||
|
@ -56,6 +73,7 @@ public class BindingBeanNameUrlHandlerMapping extends BeanNameUrlHandlerMapping
|
|||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
|
||||
<filter-mapping>
|
||||
<filter-name>spring</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<url-pattern>*.jsp</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
|
||||
|
@ -101,7 +101,7 @@
|
|||
|
||||
<filter-mapping>
|
||||
<filter-name>session</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<url-pattern>*.jsp</url-pattern>
|
||||
</filter-mapping>
|
||||
<filter-mapping>
|
||||
<filter-name>spring-rq</filter-name>
|
||||
|
|
|
@ -49,7 +49,7 @@
|
|||
<td><jms:formatTimestamp timestamp="${row.JMSTimestamp}"/></td>
|
||||
<td>${row.JMSType}</td>
|
||||
<td>
|
||||
<a href="deleteMessage.action?JMSDestination=<c:out value="${row.JMSDestination}"/>&messageId=${row.JMSMessageID}">Delete</a>
|
||||
<a href="deleteMessage.action?JMSDestination=<c:out value="${row.JMSDestination}"/>&messageId=${row.JMSMessageID}&secret=<c:out value='${sessionScope["secret"]}'/>">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
</jms:forEachMessage>
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
<td>${row.JMSTimestamp}</td>
|
||||
<td>${row.JMSType}</td>
|
||||
<td>
|
||||
<a href="deleteDestination.action?destination=${row.JMSMessageID}">Delete</a>
|
||||
<a href="deleteDestination.action?destination=${row.JMSMessageID}&secret=<c:out value='${sessionScope["secret"]}'/>">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
</jms:forEachMessage>
|
||||
|
|
|
@ -130,10 +130,10 @@ No message could be found for ID ${requestContext.messageQuery.id}
|
|||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="2"><a href="deleteMessage.action?JMSDestination=<c:out value="${row.JMSDestination}" />&messageId=${row.JMSMessageID}">Delete</a></td>
|
||||
<td colspan="2"><a href="deleteMessage.action?JMSDestination=<c:out value="${row.JMSDestination}" />&messageId=${row.JMSMessageID}&secret=<c:out value='${sessionScope["secret"]}'/>">Delete</a></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td><a href="javascript:confirmAction('queue', 'copyMessage.action?destination=%target%&JMSDestination=<c:out value="${row.JMSDestination}" />&messageId=${row.JMSMessageID}&JMSDestinationType=queue')">Copy</a></td>
|
||||
<td><a href="javascript:confirmAction('queue', 'copyMessage.action?destination=%target%&JMSDestination=<c:out value="${row.JMSDestination}" />&messageId=${row.JMSMessageID}&JMSDestinationType=queue&secret=<c:out value='${sessionScope["secret"]}'/>')">Copy</a></td>
|
||||
<td rowspan="2">
|
||||
<select id="queue">
|
||||
<option value=""> -- Please select --</option>
|
||||
|
@ -147,7 +147,7 @@ No message could be found for ID ${requestContext.messageQuery.id}
|
|||
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td><a href="javascript:confirmAction('queue', 'moveMessage.action?destination=%target%&JMSDestination=<c:out value="${row.JMSDestination}" />&messageId=${row.JMSMessageID}&JMSDestinationType=queue')">Move</a></td>
|
||||
<td><a href="javascript:confirmAction('queue', 'moveMessage.action?destination=%target%&JMSDestination=<c:out value="${row.JMSDestination}" />&messageId=${row.JMSMessageID}&JMSDestinationType=queue&secret=<c:out value='${sessionScope["secret"]}'/>')">Move</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -21,8 +21,9 @@
|
|||
<body>
|
||||
|
||||
<div>
|
||||
<form action="createDestination.action" method="get">
|
||||
<form action="createDestination.action" method="post">
|
||||
<input type="hidden" name="JMSDestinationType" value="queue"/>
|
||||
<input type="hidden" name="secret" value="<c:out value='${sessionScope["secret"]}'/>"/>
|
||||
|
||||
<label name="destination">Queue Name</label>
|
||||
<input type="text" name="JMSDestination" value=""/>
|
||||
|
@ -63,8 +64,8 @@
|
|||
</td>
|
||||
<td>
|
||||
<a href="send.jsp?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=queue">Send To</a>
|
||||
<a href="purgeDestination.action?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=queue">Purge</a>
|
||||
<a href="deleteDestination.action?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=queue">Delete</a>
|
||||
<a href="purgeDestination.action?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=queue&secret=<c:out value='${sessionScope["secret"]}'/>">Purge</a>
|
||||
<a href="deleteDestination.action?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=queue&secret=<c:out value='${sessionScope["secret"]}'/>">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
<td>${row.period}</td>
|
||||
<td>${row.repeat}</td>
|
||||
<td>
|
||||
<a href="deleteJob.action?jobId=${row.jobId}">Delete</a>
|
||||
<a href="deleteJob.action?jobId=${row.jobId}&secret=<c:out value='${sessionScope["secret"]}'/>">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
<h2>Send a JMS Message</h2>
|
||||
|
||||
<form action="sendMessage.action" method="post">
|
||||
<input type="hidden" name="secret" value="<c:out value='${sessionScope["secret"]}'/>"/>
|
||||
|
||||
<table id="headers" class="autostripe">
|
||||
<thead>
|
||||
|
|
|
@ -20,8 +20,9 @@
|
|||
</head>
|
||||
<body>
|
||||
|
||||
<form action="createSubscriber.action" method="get">
|
||||
<form action="createSubscriber.action" method="post">
|
||||
<input type="hidden" name="JMSDestinationType" value="topic"/>
|
||||
<input type="hidden" name="secret" value="<c:out value='${sessionScope["secret"]}'/>"/>
|
||||
|
||||
<table id="createSubscribers" class="sortable autostripe">
|
||||
<thead>
|
||||
|
@ -102,7 +103,7 @@
|
|||
<td>${row.enqueueCounter}</td>
|
||||
<td>${row.dequeueCounter}</td>
|
||||
<td>
|
||||
<a href="deleteSubscriber.action?clientId=${row.clientId}&subscriberName=${row.subscriptionName}">Delete</a>
|
||||
<a href="deleteSubscriber.action?clientId=${row.clientId}&subscriberName=${row.subscriptionName}&secret=<c:out value='${sessionScope["secret"]}'/>">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
<div>
|
||||
<form action="createDestination.action" method="get">
|
||||
<input type="hidden" name="JMSDestinationType" value="topic"/>
|
||||
<input type="hidden" name="secret" value="<c:out value='${sessionScope["secret"]}'/>"/>
|
||||
|
||||
<label name="destination">Topic Name</label>
|
||||
<input type="text" name="JMSDestination" value=""/>
|
||||
|
@ -52,7 +53,7 @@
|
|||
<td>${row.dequeueCount}</td>
|
||||
<td>
|
||||
<a href="send.jsp?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=topic">Send To</a>
|
||||
<a href="deleteDestination.action?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=topic">Delete</a>
|
||||
<a href="deleteDestination.action?JMSDestination=<c:out value="${row.name}" />&JMSDestinationType=topic&secret=<c:out value='${sessionScope["secret"]}'/>">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
</c:forEach>
|
||||
|
|
|
@ -128,4 +128,8 @@ public class DestinationFacade {
|
|||
protected String getPhysicalDestinationName() {
|
||||
return createDestination().getPhysicalName();
|
||||
}
|
||||
|
||||
public String[] getSupportedHttpMethods() {
|
||||
return new String[]{"GET", "POST"};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
package org.apache.activemq.web;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
|
@ -39,7 +40,8 @@ public class SessionFilter implements Filter {
|
|||
}
|
||||
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
((HttpServletRequest)request).getSession(true);
|
||||
// set secret to prevent CSRF attacks
|
||||
((HttpServletRequest)request).getSession(true).setAttribute("secret", UUID.randomUUID().toString());;
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue