Last active
March 14, 2023 00:02
-
-
Save picodotdev/7044756 to your computer and use it in GitHub Desktop.
Solución al problema de seguridad CSRF en Apache Tapestry
http://elblogdepicodev.blogspot.com/2013/10/solucion-al-problema-de-seguridad-csrf.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.annotation; | |
import java.lang.annotation.Documented; | |
import java.lang.annotation.ElementType; | |
import java.lang.annotation.Retention; | |
import java.lang.annotation.RetentionPolicy; | |
import java.lang.annotation.Target; | |
@Target(ElementType.METHOD) | |
@Retention(RetentionPolicy.RUNTIME) | |
@Documented | |
public @interface Csrf { | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Contribute(ComponentClassTransformWorker2.class) | |
public static void contributeWorkers(OrderedConfiguration<ComponentClassTransformWorker2> configuration) { | |
configuration.addInstance("CSRF", CsrfWorker.class); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.mixins; | |
import org.apache.tapestry5.ComponentResources; | |
import org.apache.tapestry5.MarkupWriter; | |
import org.apache.tapestry5.annotations.InjectContainer; | |
import org.apache.tapestry5.annotations.MixinAfter; | |
import org.apache.tapestry5.annotations.SessionState; | |
import org.apache.tapestry5.corelib.components.ActionLink; | |
import org.apache.tapestry5.corelib.components.BeanEditForm; | |
import org.apache.tapestry5.corelib.components.EventLink; | |
import org.apache.tapestry5.corelib.components.Form; | |
import org.apache.tapestry5.dom.Element; | |
import org.apache.tapestry5.dom.Node; | |
import org.apache.tapestry5.ioc.annotations.Inject; | |
import org.apache.tapestry5.runtime.Component; | |
import org.apache.tapestry5.services.Request; | |
import es.com.blogspot.elblogdepicodev.plugintapestry.services.sso.Sid; | |
@MixinAfter | |
public class Csrf { | |
@SessionState(create = false) | |
private Sid sid; | |
@Inject | |
private Request request; | |
@Inject | |
private ComponentResources resources; | |
@InjectContainer | |
private Component container; | |
void beginRender(MarkupWriter writer) { | |
if (container instanceof EventLink || container instanceof ActionLink) { | |
buildSid(); | |
Element element = writer.getElement(); | |
String href = element.getAttribute("href"); | |
String character = (href.indexOf('?') == -1) ? "?" : "&"; | |
element.forceAttributes("href", String.format("%s%st:sid=%s", href, character, sid.getSid())); | |
} | |
} | |
void afterRenderTemplate(MarkupWriter writer) { | |
if (container instanceof BeanEditForm) { | |
Element form = null; | |
for (Node node : writer.getElement().getChildren()) { | |
if (node instanceof Element) { | |
Element element = (Element) node; | |
if (element.getName().equals("form")) { | |
form = element; | |
break; | |
} | |
} | |
} | |
if (form != null) { | |
buildSid(); | |
Element e = form.element("input", "type", "hidden", "name", "t:sid", "value", sid.getSid()); | |
e.moveToTop(form); | |
} | |
} | |
} | |
void beforeRenderBody(MarkupWriter writer) { | |
if (container instanceof Form) { | |
buildSid(); | |
Element form = (Element) writer.getElement(); | |
form.element("input", "type", "hidden", "name", "t:sid", "value", sid.getSid()); | |
} else if (container instanceof BeanEditForm) { | |
buildSid(); | |
Element form = (Element) writer.getElement(); | |
form.element("input", "type", "hidden", "name", "t:sid", "value", sid.getSid()); | |
} | |
} | |
private void buildSid() { | |
if (sid == null) { | |
sid = Sid.newInstance(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.workers; | |
import org.apache.tapestry5.model.MutableComponentModel; | |
import org.apache.tapestry5.plastic.MethodAdvice; | |
import org.apache.tapestry5.plastic.MethodInvocation; | |
import org.apache.tapestry5.plastic.PlasticClass; | |
import org.apache.tapestry5.plastic.PlasticMethod; | |
import org.apache.tapestry5.services.ApplicationStateManager; | |
import org.apache.tapestry5.services.Request; | |
import org.apache.tapestry5.services.transform.ComponentClassTransformWorker2; | |
import org.apache.tapestry5.services.transform.TransformationSupport; | |
import es.com.blogspot.elblogdepicodev.plugintapestry.services.annotation.Csrf; | |
import es.com.blogspot.elblogdepicodev.plugintapestry.services.exceptions.CSRFException; | |
import es.com.blogspot.elblogdepicodev.plugintapestry.services.sso.Sid; | |
public class CsrfWorker implements ComponentClassTransformWorker2 { | |
private Request request; | |
private ApplicationStateManager manager; | |
public CsrfWorker(Request request, ApplicationStateManager manager) { | |
this.request = request; | |
this.manager = manager; | |
} | |
public void transform(PlasticClass plasticClass, TransformationSupport support, MutableComponentModel model) { | |
MethodAdvice advice = new MethodAdvice() { | |
public void advise(MethodInvocation invocation) { | |
String rsid = request.getParameter("t:sid"); | |
Sid sid = manager.getIfExists(Sid.class); | |
if (sid != null && sid.isValid(rsid)) { | |
invocation.proceed(); | |
} else { | |
invocation.setCheckedException(new CSRFException("El parámetro sid de la petición no se corresponde con el sid de la sesión. Esta petición no es válida (Posible ataque CSRF).")); | |
invocation.rethrow(); | |
} | |
} | |
}; | |
for (PlasticMethod method : plasticClass.getMethodsWithAnnotation(Csrf.class)) { | |
method.addAdvice(advice); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ git clone git://github.com/picodotdev/elblogdepicodev.git | |
$ cd elblogdepicodev/PlugInTapestry | |
$ ./gradlew tomcatRun | |
# Abrir en el navegador http://localhost:8080/PlugInTapestry/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@Csrf | |
void onSuccessFromCsrfForm() { | |
cuenta += 1; | |
renderer.addRender("zone", zone).addRender("submitOneZone", submitOneZone).addRender("csrfZone", csrfZone); | |
} | |
@Csrf | |
void onSumar1CuentaCsrf() { | |
cuenta += 1; | |
renderer.addRender("zone", zone).addRender("submitOneZone", submitOneZone).addRender("csrfZone", csrfZone); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<h4>Solución al CSRF</h4> | |
<p> | |
Cuenta: <t:zone t:id="csrfZone" id="csrfZone" elementName="span">${cuenta}</t:zone> | |
<div class="row"> | |
<div class="col-md-4"> | |
<h5>En formulario</h5> | |
<form t:id="csrfForm" t:type="form" t:zone="csrfZone" t:mixins="csrf"> | |
<input t:type="submit" value="Sumar 1"/> | |
</form> | |
</div> | |
<div class="col-md-4"> | |
<h5>En enlace</h5> | |
<a t:type="eventlink" t:event="sumar1CuentaCsrf" t:zone="csrfZone" t:mixins="csrf">Sumar 1</a> | |
</div> | |
<div class="col-md-4"> | |
<h5>Fallo seguridad</h5> | |
<a t:type="eventlink" t:event="sumar1CuentaCsrf" t:zone="csrfZone" t:parameters="prop:{'t:sid':'dummy-attack'}">Sumar 1</a> | |
</div> | |
</div> | |
</p> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package es.com.blogspot.elblogdepicodev.plugintapestry.services.sso; | |
import java.io.Serializable; | |
import java.util.UUID; | |
public class Sid implements Serializable { | |
private static final long serialVersionUID = -4552333438930728660L; | |
private String sid; | |
protected Sid(String sid) { | |
this.sid = sid; | |
} | |
public static Sid newInstance() { | |
return new Sid(UUID.randomUUID().toString()); | |
} | |
public String getSid() { | |
return sid; | |
} | |
public boolean isValid(String sid) { | |
return this.sid.equals(sid); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi! I cant pass from here "Failure creating embedded component 'inputs' of foo.bar.pages.inicio.ModEMail: Unable to resolve 'csrf' to a mixin class name."