How to disable #{session} on a JSF page? - java

I am using JSF 2.2. I am trying to use JSF as a pure templating language. However, there is one problem. Any user who is creating a JSF page in my environment can do something like this:
#{session.getAttribute('user').getApiKey()}
Here I have a user object that is stored in the session and getApiKey() method is a getter in that class.
Is there 'web.xml' configuration or some other trick that I can use to disable session object completely on a JSF page?

Is there 'web.xml' configuration or some other trick that I can use to disable session object completely on a JSF page?
No.
Parse the template manually against a whitelist of allowed tags, attributes and EL expressions (note: don't use a blacklist, hackers will find ways you wouldn't have imagined). For instance, the following expressions have the same effect as #{session.getAttribute('user').getApiKey()}:
#{request.session.getAttribute('user').apiKey}
#{sessionScope.user.apiKey}
#{user.apiKey}
#{facesContext.externalContext.sessionMap.user.apiKey}
#{facesContext.externalContext.session.getAttribute('user').apiKey}
After all, JSF/Facelets is likely the wrong tool for the job of offering clients some kind of a template which will be executed in the server. Rather look for BB/Wiki/Markdown-like markup or whitelisted HTML which you display via <h:outputText escape="false">.

Maybe. The implicit variables are contributed by a particular ELResolver. Removing that one from the list of ELResolvers, or prepending an own resolver that always returns null for all implicit variables to that list, should do the trick.
Off hand, I don't know whether JSF offers a public API do this, or the spec even permits something like that.
Either way, if you just need a templating engine, there are easier options that customizing a stateful, component-based web application framework ...

Here is what I did to solve this problem. This class essentially revokes access to all the core objects on the page. Additionally, I've added a utility variable to give access to the context path. I have tried this and it seems to WORK!.
package com.example.templates.jsf;
import javax.el.ELContext;
import javax.el.ELException;
import javax.el.PropertyNotFoundException;
import javax.faces.component.UIComponent;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import com.sun.faces.component.CompositeComponentStackManager;
import com.sun.faces.el.ImplicitObjectELResolver;
import com.sun.faces.util.MessageUtils;
/**
* This class revokes access to server page context objects
*/
public class CustomImplicitObjectELResolver extends ImplicitObjectELResolver {
public static final int CONTEXT_PATH = 19;
public CustomImplicitObjectELResolver(){
super();
// Revoke access to variables that can potentially
// give access to internal class objects.
IMPLICIT_OBJECTS.remove("facesContext");
IMPLICIT_OBJECTS.remove("session");
IMPLICIT_OBJECTS.remove("sessionScope");
IMPLICIT_OBJECTS.remove("application");
IMPLICIT_OBJECTS.remove("applicationScope");
IMPLICIT_OBJECTS.remove("request");
IMPLICIT_OBJECTS.remove("requestScope");
IMPLICIT_OBJECTS.remove("view");
IMPLICIT_OBJECTS.remove("viewScope");
IMPLICIT_OBJECTS.remove("initParam");
IMPLICIT_OBJECTS.remove("component");
IMPLICIT_OBJECTS.remove("cookie");
IMPLICIT_OBJECTS.remove("header");
IMPLICIT_OBJECTS.remove("headerValues");
IMPLICIT_OBJECTS.remove("flowScope");
// My own utility method
IMPLICIT_OBJECTS.put("contextPath", CONTEXT_PATH);
}
#Override
public Object getValue(ELContext context,Object base, Object property)
throws ELException {
// variable resolution is a special case of property resolution
// where the base is null.
if (base != null) {
return null;
}
if (property == null) {
String message = MessageUtils.getExceptionMessageString
(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "property");
throw new PropertyNotFoundException(message);
}
Integer index = IMPLICIT_OBJECTS.get(property.toString());
if (index == null) {
return null;
} else {
FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
ExternalContext extCtx = facesContext.getExternalContext();
switch (index) {
case COMPOSITE_COMPONENT:
// The following five lines violate the specification.
// The specification states that the 'cc' implicit object
// always evaluates to the current composite component,
// however, this isn't desirable behavior when passing
// attributes between nested composite components, so we
// need to alter the behavior so that the components behave
// as the user would expect.
/* BEGIN DEVIATION */
CompositeComponentStackManager manager =
CompositeComponentStackManager.getManager(facesContext);
Object o = manager.peek();
/* END DEVIATION */
if (o == null) {
o = UIComponent.getCurrentCompositeComponent(facesContext);
}
context.setPropertyResolved(o != null);
return o;
case PARAM:
context.setPropertyResolved(true);
return extCtx.getRequestParameterMap();
case PARAM_VALUES:
context.setPropertyResolved(true);
return extCtx.getRequestParameterValuesMap();
case CONTEXT_PATH:
context.setPropertyResolved(true);
return extCtx.getRequestContextPath();
case RESOURCE:
context.setPropertyResolved(true);
return facesContext.getApplication().getResourceHandler();
default:
return null;
}
}
}
}
Next, in faces-config.xml, add the following entry:
<application>
<el-resolver>
com.example.templates.jsf.CustomImplicitObjectELResolver
</el-resolver>
</application>

Related

Using OTEL Java agent, how to create a new Context without using #WithSpan

The opentelemetry-javaagent-all agent (versions 0.17.0 and 1.0.1) has been the starting point for adding trace information to my Java application. Auto-instrumentation works great.
Some of my application cannot be auto-instrumented. For this part of the application, I began by adding #WithSpan annotations to interesting spots in the code.
I now reach the limits of what seems possible with simple #WithSpan annotations. However, the framework underlying my app allows me to register callbacks to be invoked at certain points -- e.g. I can provide handlers that are notified when a client connects / disconnects.
What I think I need is to start a new Span when Foo.onConnect() is called, and set it be the parent for the Spans that correspond to each request.
public class Foo {
void onConnect() {
// called when a client connects to my app
// Here I want to create a Span that will be the parent of the Span created in
// Foo.processEachRequest().
}
#WithSpan
public void processEachRequest() {
// works, but since it is called for each request... each span is in a separate Trace
}
void onDisconnect() {
// called when the client disconnects from my app
// Here I can end the parent Span.
}
}
Other ideas - that didn't work out:
1 - The obvious solution would be to add #WithSpan annotations to the underlying framework. For various reasons, this is not going to be a practical way forward.
2 - Next choice might be to search for a way to tell the javaagent about methods in my underlying framework. (The New Relic agent can do something like this.) That doesn't seem to be a feature of the open-telemetry agent, today anyway.
So, I'm left with looking for a way to do this using the callbacks, as above.
Is there a way to do this?
That should be possible by manually instrumenting your code. You would use the Tracer interface of OpenTelemetry, as described in the OpenTelemetry Java docs.
This should give you a general idea:
public class Foo {
private Span parentSpan; // you might need a Map/List/Stack here
void onConnect() {
Tracer tracer =
openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
Span span = tracer.spanBuilder("my span").startSpan();
this.parentSpan = span; // might need to store span per request/client/connection-id
}
public void processEachRequest() {
final Span parent = this.lookupParentSpan();
if (parent != null) {
try (Scope scope = span.makeCurrent()) {
yourLogic();
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "error message");
throw t;
}
} else {
yourLogic();
}
}
void onDisconnect() {
final Span parent = this.lookupParentSpan();
if (parent != null) {
parent.end();
}
}
private Span lookupParentSpan() {
// you probably want to lookup the span by client or connection id from a (weak) map
return this.parentSpan;
}
}
NB: You must guarantee that a span is always ended and does not leak. Make sure to properly scope your spans and eventually call Span#end().

Custom Annotation JSF

I wanted to make a custom annotation to check security on some functions for my JSF web application. For security I use Tomcat security with JaaS, so I have no application managed security to my disposal.
What actually want to do is make an annotation for my methods in the Backing Beans like Spring Security (#Secured("role")). My security system is implemented so that every function is a role and you can dynamically make "user roles" these are stored in the DB and when somebody logs in all the (function)roles in that "user role" will be set in tomcat security as roles.
So now I have this piece of code to check if my user can access the function:
public static void checkSecurity(final String function) {
final FacesContext facesContext = FacesContext.getCurrentInstance();
try {
if (facesContext.getExternalContext().getRemoteUser() == null) {
facesContext.getExternalContext().redirect("login.xhtml");
return;
}
if (!facesContext.getExternalContext().isUserInRole(function)) {
facesContext.getExternalContext().redirect("restricted.xhtml");
return;
}
} catch (final Exception ex /* Mandatory "IOException e" will be caught + all other exceptions. */) {
facesContext.getExternalContext().setResponseStatus(403); // HTTP Status 403: Forbidden. Can also throw 401.
facesContext.responseComplete();
}
}
Now I have to call this SecurityUtil.checkSecurity("name_of_function"); in every method.
But I want to have an annotation like this #CustomSecurity("function_name_role").
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface CustomSecurity {
// Single Element called value.
String value();
}
And when a method has this annotation the checkSecurity function automatically has to be performed. So I have to scan for this annotation at a point, or make some kind of actionlistener. JSF should have some options for this but all the forums I found on this don't really help.
Does somebody has some ideas?
EDIT:
I tried this blog it works but only on an action of a component (and components don't render when you don't have the role). So how secure is this when people try to hack into the JSF structure. And I rather have it running on every method.
public class SecurityActionListener extends ActionListenerImpl implements ActionListener {
private static final Logger LOGGER = FacesLogger.APPLICATION.getLogger();
#SuppressWarnings("unused")
#Override
public void processAction(final ActionEvent event) {
final FacesContext context = FacesContext.getCurrentInstance();
final Application application = context.getApplication();
final ConfigurableNavigationHandler navHandler = (ConfigurableNavigationHandler) application.getNavigationHandler();
// Action stuff
final UIComponent source = event.getComponent();
final ActionSource actionSource = (ActionSource) source;
MethodBinding binding;
binding = actionSource.getAction();
final String expr = binding.getExpressionString();
if (!expr.startsWith("#")) {
super.processAction(event);
return;
}
final int idx = expr.indexOf('.');
final String target = expr.substring(0, idx).substring(2);
final String t = expr.substring(idx + 1);
final String method = t.substring(0, (t.length() - 1));
final MethodExpression expression = new MethodExpressionMethodBindingAdapter(binding);
final ELContext elContext = context.getELContext();
final ExpressionFactory factory = context.getApplication().getExpressionFactory();
final ValueExpression ve = factory.createValueExpression(elContext, "#{" + target + '}', Object.class);
final Object result = ve.getValue(elContext);
// Check if the target method is a secured method
// and check security accordingly
final Method[] methods = result.getClass().getMethods();
for (final Method meth : methods) {
if (meth.getName().equals(method)) {
if (meth.isAnnotationPresent(CustomSecurity.class)) {
final CustomSecurity securityAnnotation = meth.getAnnotation(CustomSecurity.class);
System.out.println("Function to check security on: " + securityAnnotation.value()); // TODO TO LOG
SecurityUtil.checkSecurity(securityAnnotation.value());
} else {
super.processAction(event);
}
break;
}
}
}
}
And this in the faces-config.xml:
<action-listener>
com.nielsr.randompackagebecauseofnda.SecurityActionListener
</action-listener>
This blog could also be an answer, but I don't know how it will work with my JaaS Tomcat security because the security is in a separate project deployed as a standalone JAR in the tomcat lib folder.
But I actually don't know that I have to secure my Beans. Because I have configured all the functions (aka roles see above) that are on 1 page in the Web.xml as security constraints. And I render the components on the page only if you have to rights or "function_role" on that component. So is this secured enough? Or if somebody has a right to a function on a page can he render the components himself and so hack my site?
I'm not that familiar to JSF to know this, what is going on in that extra JSF abstraction layer between Controller and View? (I'm more of a Spring MVC developer, but because of requirements I have to use JSF but it's nice to broaden my knowledge.)
You can "scan for your Annotations" using
http://code.google.com/p/reflections/
Regards

Flex : LCDS Service returning null Asynctoken when executed 2nd time

I'm developing a Flex application using RobotLegs, LiveCycle DS & Java.
I'm trying to implement an update function, using LCDS, but I'm running into some strange behaviour:
This is the ActionScript code within a RobotLegs' execute command,
used to perform the update:
var token:AsyncToken = services.requestService.commit(new Array(model.currentRequestDetail));
responder = new AsyncResponder(resultHandler, faultHandler, token);
if ( token ) token.addResponder(responder);
The model.currentRequestDetail I'm trying to update is a RequestDetail Object:
[Managed]
[RemoteClass(alias="be.fgov.mobilit.td.lcds.vo.RequestDetail")]
public class RequestDetail {
public var id:Number;
public var request:Request;
public var task:Task;
/**
* Constructor
*/
public function RequestDetail() {
}
}
The first time the Actionscript code is executed, everything works fine.
The AsyncToken is nicely returned by the services.requestService.commit() function,
the resultHandler is executed as expected, and my object is updated in the GUI.
However, the second time this code is executed, my services.requestService.commit() function returns a null value, and my resultHandler is never reached.
I suspect we're not even reaching the java assembler.
This is how I declared the DataService:
var requestDetailService:DataService = new DataService("requestDetail");
requestDetailService.autoCommit = false;
Both the resultHandler & the faultHandler have the right signature:
resultHandler(result:Object, token:Object = null)
faultHandler(result:Object, token:Object = null)
We're also using a custom java assembler, this is the code:
package be.fgov.mobilit.td.lcds.assemblers;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import be.fgov.mobilit.td.lcds.vo.RequestDetail;
import flex.data.ChangeObject;
import flex.data.assemblers.AbstractAssembler;
public class RequestAssembler extends AbstractAssembler {
public RequestAssembler() {
// TODO Auto-generated constructor stub
}
public RequestDetail getRequest(Map<String, Object> identity) {
return ServiceUtility.getLcdsService().getRequestDetail(identity);
}
public List<ChangeObject> syncRequest(List<ChangeObject> changes) {
Iterator<ChangeObject> iterator = changes.iterator();
ChangeObject co;
while (iterator.hasNext()) {
co = (ChangeObject) iterator.next();
if (co.isUpdate()) {
co = doUpdate(co);
}
}
return changes;
}
private ChangeObject doUpdate(ChangeObject co) {
RequestDetail requestDetail = (RequestDetail) co.getNewVersion();
co.setNewVersion(ServiceUtility.getLcdsService().updateRequestDetail(requestDetail));
return co;
}
}
This is the assembler's configuration:
<destination id="request">
<properties>
<source>be.fgov.mobilit.td.lcds.assemblers.RequestAssembler</source>
<scope>application</scope>
<metadata>
<identity property="id" />
<identity property="task" />
</metadata>
<server>
<get-method>
<name>getRequest</name>
</get-method>
<sync-method>
<name>syncRequest</name>
</sync-method>
</server>
</properties>
</destination>
Long story short:
Does anyone have a clue/experience, why the 2nd time I execute the services.requestService.commit(); function it returns a null Asynctoken?
Thx in advance!
As requested, I added the (stripped) code from my services class.
As you can see, nothing really special going on:
package be.fgov.mobilit.services {
import mx.data.DataService;
import mx.messaging.Consumer;
import mx.messaging.events.MessageEvent;
import mx.rpc.http.HTTPService;
public class LiveCycleServices {
public var requestService:DataService;
public function LiveCycleServices() {
requestService = new DataService("request");
requestService.autoCommit = false;
}
/**
* #param MessageEvent The event object that is dispatched by the Flex framework
* #return void
*
* This message captures the server push messages that need to trigger an update
* of the task list, since this is specific for every client and cannot be
* determined on the server side, coming from LiveCycle.
*/
private function messageHandler(event:MessageEvent):void {
taskListService.refresh();
}
}
}
This is the chode where my result- & faulthandlers are added:
var token:AsyncToken = services.requestService.commit(new Array(model.currentRequestDetail));
var responder:AsyncResponder = new AsyncResponder(resultHandler, faultHandler, token);
if ( token ) token.addResponder(responder);
The aysnctoken returns null when you have no changes to commit. Hope this helps.
WWW, This isn't really an answer as such, but I need more space than a comment will give me. However, I'm not seeing how all your code is connected well enough to give you a good answer.
In general, the result and fault signatures should not look like what you describe as the "right" signature. The AsyncToken is expecting an IResponder, which whose fault and result mentods have a single parameter that is an Object. In general, this will be called with the fault or result event (as appropriate).
Now I am going into territory that is, for me, purely theoretical. It looks like to me that the DataService Class might possibly create just a single AsyncToken, since the connection is kept open. If that is the case, it is possible that the erroneous method signature damages the AsyncToken to the extent that it can't be returned for use by the method. I didn't see anything in the code that you pasted that looks like it calls your result and fault methods in a custom way.
I strongly doubt that the problem is in the Java code. AFAIK, the AsyncToken is created and set up to call the functions in the responder before the call is even made (at least that is how it seems to work with HTTPService or amf). I would expect that there's some error that is being "helpfully" suppressed, so you might benefit from stepping through the code.
I would suggest that you step back a bit and look a bit harder at the "S" part of the MVCS architecture implied by Robotlegs, and create a separate service Class that manages the whole thing, and merely kick off the process from a Command, rather than trying to pass control back and forth between your commands and services. As a side benefit, you can then swap out instances of the real service for test services when you don't need to be connected to the actual data (such as for doing design work).

How do you create a secure JEXL (scripting) sandbox?

I'm creating a sandbox for JEXL scripts to execute in so that a malicious user can't access data outside the variables we give them access to and also can't perform a DOS attack on the server. I'd like to document this for anybody else also doing this and also get other people's input into the approach.
The following is a list of the things I'm aware of that needs to be addressed:
Only allow instantiating classes using 'new' that are on a whitelist.
Do not allow accessing the getClass method on any class because then forName can be called and any class can be accessed.
Restrict access to resources such as files.
Allow an expression only a certain amount of time to execute so that we can limit the amount of resources it consumes.
This does not apply to JEXL but may apply to the scripting language you are using:
Do not allow an object to have a custom finalize method because the finalize method is called from the finalizer thread and will execute with the original AccessControlContext instead of the one being used to create the object and execute the code in it.
UPDATE: This was all done using JEXL 2.0.1. You may have to adapt this to make it work with newer versions.
Here is my approach for dealing with each of these cases. I've created unit tests to test each of these cases and I have verified that they work.
JEXL makes this pretty easy. Just create a custom ClassLoader. Override the two loadClass() methods. On JexlEngine call setClassLoader().
Again, JEXL makes this pretty easy. You must block both '.class' and '.getClass()'. Create your own Uberspect class which extends UberspectImpl. Override getPropertyGet, if identifier equals "class" return null. Override getMethod, if method equals "getClass" return null. When constructing JexlEngine pass a reference to your Uberspect implementation.
class MyUberspectImpl extends UberspectImpl {
public MyUberspectImpl(Log jexlLog) {
super(jexlLog);
}
#Override
public JexlPropertyGet getPropertyGet(Object obj, Object identifier, JexlInfo info) {
// for security we do not allow access to .class property
if ("class".equals(identifier)) throw new RuntimeException("Access to getClass() method is not allowed");
JexlPropertyGet propertyGet = super.getPropertyGet(obj, identifier, info);
return propertyGet;
}
#Override
public JexlMethod getMethod(Object obj, String method, Object[] args, JexlInfo info) {
// for security we do not allow access to .getClass() method
if ("getClass".equals(method)) throw new RuntimeException("Access to getClass() method is not allowed");
return super.getMethod(obj, method, args, info);
}
}
You do this using Java's AccessController mechanism. I'll give a quick run-down of doing this. Start java with -Djava.security.policy=policyfile. Make a file named policyfile containing this line:
grant { permission java.security.AllPermission; };
Set the default SecurityManager with this call: System.setSecurityManager(new SecurityManager()); Now you can control permissions and your app by default has all permissions. It would be better if you limit the permissions of your app to only what it requires of course. Next, create an AccessControlContext that limits the permissions to the bare minimum and call AccessController.doPrivileged() and pass the AccessControlContext, then execute the JEXL script inside doPrivileged(). Here is a small program that demonstrates this. The JEXL script calls System.exit(1) and if it isn't wrapped in doPrivileged() it would successfully terminate the JVM.
System.out.println("java.security.policy=" + System.getProperty("java.security.policy"));
System.setSecurityManager(new SecurityManager());
try {
Permissions perms = new Permissions();
perms.add(new RuntimePermission("accessDeclaredMembers"));
ProtectionDomain domain = new ProtectionDomain(new CodeSource( null, (Certificate[]) null ), perms );
AccessControlContext restrictedAccessControlContext = new AccessControlContext(new ProtectionDomain[] { domain } );
JexlEngine jexlEngine = new JexlEngine();
final Script finalExpression = jexlEngine.createScript(
"i = 0; intClazz = i.class; "
+ "clazz = intClazz.forName(\"java.lang.System\"); "
+ "m = clazz.methods; m[0].invoke(null, 1); c");
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
#Override
public Object run() throws Exception {
return finalExpression.execute(new MapContext());
}
}, restrictedAccessControlContext);
}
catch (Throwable ex) {
ex.printStackTrace();
}
The trick with this is interrupting the script before it finishes. One way I found to do this is to create a custom JexlArithmetic class. Then override each method in that class and before calling the real method in the super class check if the script should stop executing. I'm using an ExecutorService to create threads. When Future.get() is called pass the amount of time to wait. If a TimeoutException is thrown call Future.cancel() which interrupts the Thread running the script. Inside each overridden method in the new JexlArithmetic class check Thread.interrupted() and if true throw java.util.concurrent.CancellationException.
Is there a better location to put code which will get executed regularly as a script is being executed so that it can be interrupted?
Here is an excerpt of the MyJexlArithmetic class. You have to add all the other methods:
public class MyJexlArithmetic extends JexlArithmetic {
public MyJexlArithmetic(boolean lenient) {
super(lenient);
}
private void checkInterrupted() {
if (Thread.interrupted()) throw new CancellationException();
}
#Override
public boolean equals(Object left, Object right) {
checkInterrupted();
return super.equals(left, right); //To change body of generated methods, choose Tools | Templates.
}
#Override
public Object add(Object left, Object right) {
checkInterrupted();
return super.add(left, right);
}
}
Here is how I am instantiating JexlEngine:
Log jexlLog = LogFactory.getLog("JEXL");
Map <String, Object> functions = new HashMap();
jexlEngine = new JexlEngine(new MyUberspectImpl(jexlLog), new MyJexlArithmetic(false), functions, jexlLog);

Calling application.getRealPath() from within a class in JSP

I am writing a class in JSP to retrieve a bunch of config values from an XML file. My plan is to have a class "XMLConfig" that loads in the values from the file, and then uses access methods to get at the values in the config object.
My problem is that i cannot seem to call application.getRealPath() from within the class, since eclipse tells me that "application cannot be resolved". I suspect that I must change "application" to something else but I am unsure what.
My code for the class:
<%!
//Config object
public class XMLConfig {
public boolean loadConfigFile(String strName) {
String XMLfileName = application.getRealPath(strName);
try {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = null;
doc = db.parse(XMLFileName);
}catch(Exception e)
{
System.out.println(e.getMessage());
return false;
}
return true;
}
}
%>
application isn't a global var. If you want to use it in your method then you'll need to pass it as a parameter.
Not sure why you're defining the class within the jsp though instead of just creating a 'normal' java class.
That's a job for a servlet instead of JSP. Create a class which extends HttpServlet and implement the doGet() method as follows:
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String strName = getOrDefineItSomehow();
Document doc = loadConfigFile(getServletContext().getRealPath(strName));
// Do whatever you want with it and then display JSP page.
request.getRequestDispatcher("/WEB-INF/config.jsp").forward(request, response);
}
Map this servlet in web.xml on an url-pattern of for example /config and invoke it by for example http://example.com/context/config. It'll run the code in doGet().
See also:
Beginning and intermediate JSP/Servlet tutorials
How to avoid Java code in JSP?
Hidden features of JSP/Servlet

Categories

Resources