is this kind of attack feasible? wicket urls are session-relative, so the
url of the form is not stable.
-igor
On 5/7/07, Mark Sandori <[EMAIL PROTECTED]> wrote:
I am looking at making a version of the Form component that supports the
"action token" pattern for securing forms against cross-site request
forgery
(XSRF) and cross-site script includes (XSSI). The basic idea is to have
the
form generate a unique id that must be submitted along with the form. This
verifies that the form was not forged and generated outside of the
application.
I would love your input as to whether this will work (I am not an expert
on
all the versioning and pagemap stuff yet, but I think the form should
always
be submitted to the same instance regardless of back button, etc.) and
whether this should be part of the base form component.
Below is the version of the form that I have created. The verification of
the token happens in an overriden validate() method. I would have
preferred
to override onFormSubmitted, but it is marked as final (at least in
1.2.5which is what I am using). In
2.0 there appears to be "fake submit" handling, but it is not clear how
this
should work. If this is already being handled, let me know...
Thanks for your time.
public class SecureForm extends Form
{
private final transient Logger logger = LoggerFactory.getLogger(
SecureForm.class);
private String actionToken;
public SecureForm(final String id) {
this(id, null);
}
public SecureForm(final String id, IModel model)
{
super(id, model);
//generate a unique action token stored with this form
actionToken = UUID.randomUUID().toString();
}
@Override
protected void onComponentTagBody(final MarkupStream markupStream,
final
ComponentTag openTag)
{
// render the hidden field
AppendingStringBuffer buffer = new AppendingStringBuffer("<div
style=\"display:none\"><input type=\"hidden\" name=\"");
buffer.append(getActionTokenHiddenFieldId())
.append("\" id=\"")
.append(getActionTokenHiddenFieldId())
.append("\" value=\"")
.append(actionToken)
.append("\" /></div>");
getResponse().write(buffer);
// do the rest of the processing
super.onComponentTagBody(markupStream, openTag);
}
@Override
protected void validate() {
//verify that the token was provided
String token =
getRequest().getParameter(getActionTokenHiddenFieldId());
if (!actionToken.equals(token)) {
logger.warn("Attempted unauthorized form submission.");
throw new UnauthorizedActionException(this, new Action("
SECUREFORM.SUBMIT"));
}
super.validate();
}
private String getActionTokenHiddenFieldId() {
return "_actiontoken";
}
}