Hi - I have a possible security issue:
My scenario is the following:
- User posts CGI variables into my service
- IS determines service to call dynamically
- IS calls this service and passes pipeline as input to that service
- Dynamically chosen service customizes variables posted by user
Imagine two similarly named variable existed in the pipeline – say, both named “AllowAccess”. Now if the Flow subsequently “wired” the AllowAccess variable to a service input, which of the two AllowAccess variables will bind to the service input at runtime?
A clearPipeline call is of no use here. Since I don’t know which variables the user posts in at runtime, I may be clearing variables required by the dynamically chosen service invoked later on.
This gives rise to a security issue. If the user knew which variables I used in my services, he could rather cleverly posts in a CGI variable called AllowAccess, and set it to “true”.
To work around this, as the first in the pipeline, I will manually drop AllowAccess (as well as other variables used later in the internal control flow of my services).
- How does WM decide which of two or more similarly-named variables to use, to say bind to a service input?
- Is the above precaution adequate? (“dropping” control flow variables)
…solution is a Java service I’ve written called “filterPipeline” … filterPipeline service removes all instances of only those variables whose names are specified in its “filter” input. …
I just realized one potential problem with my filterPipeline service - the “filter” input to the service MUST be hardcoded (i.e. the “filter” CANNOT be mapped from a variable.) In Developer you can do this by “setting” the service inputs so the little blue curved arrow appears next to “filter”. Make sure while doing this that the “Overwrite Pipeline Value” checkbox is ticked.
Otherwise, a malicious user can simply pass in another variable named “filter” and filter out what he wants, rather than what you want.
You can map the values from the pipeline to internal variables you defined and drop the original variables.
Would this work? I thought I would join this monotonous conversation.
Thanks for the company Vinod.
Mapping customer-defined variables to an internal data structure won’t work since my frontend service does not know what these variables are. The frontend service passes the entire pipeline to arbitrary services at runtime – these custom services know what the customer’s variables are.
So I came up with this dual plan:
- Carefully name my internal control variables with unlikely names:
- At the start of the frontend service, run filterPipeline
to “filter out” any these unlikely named internal variables
that the customer has sent.
Once I know any customer-generated variables with the same name as my internal control variables have been removed, I can use my internal control variables fearlessly later on in the frontend service.
The only simple alternative to these acrobatics seems to be the deepClone() method in IS Java API’s IDataUtil package. However, it carries the following warning:
public static IData deepClone(IData src) – Returns an independent copy (a deep clone) of the specified IData and its children.
Important:Be aware that using this method is extremely expensive in terms of processing time and memory. Use it only when absolutely necessary
deepClone is a no-no go for me since performance is an issue in this service.
To quote somebody famous: This discussion has a “bad smell”. There should be no reason to have 2 variables with the exact name at the same time. The 2 smells are:
- You need 2 variables with the same name at the same time
- You are using a pipeline variable to determine security permissions.
A few questions for you: Can you have the CGI script call different IS services? Then you know which variables to expect for each service within your flow.
If not, could you turn on ‘Enforce Execute ACL’ Always so that you subsequent flow services will check the username/password instead of you using a variable in your flow to determine this.
So if we assume you don’t have the ‘2 similar variables’ issue then your dynamically invoked flow should know what variables are coming in.
> “bad smell”.
I assure you it isn’t half as bad as you think
> 1) You need 2 variables with the same name at the same time
I don’t need duplicate variables with the same name - WM allows for this situation. All I’m doing is stopping any malicious user-injected duplicate variables affecting my service by stripping them out beforehand with the “filterPipeline” service.
> 2) You are using a pipeline variable to determine security
Again, no - the “AllowAccess” example above was cooked-up. However, pipeline variables are used to control a flow (eg: an SWITCH statement) and I was just illustrating how dastardly things can get.
> A few questions for you: Can you have the CGI script call different
> IS services? Then you know which variables to expect for each
> service within your flow.
Yes, each customized user could hit his own script - then I’d know which variables to expect and could put in the appropriate clearPipeline calls. However, this would give me a multiplicity of entry points with the usual problems with permissions, manageability, code maintenance, etc.
> If not, could you turn on ‘Enforce Execute ACL’ Always so that you
> subsequent flow services will check the username/password instead of
> you using a variable in your flow to determine this.
I’m not sure what you mean by “Enforce Execute ACL”. However, the authentication is being done later on in my service – once the flow has become “generic enough” to do a clearPipeline call on it.
I guess I don’t fully understand your problem - I’m trying to figure what the real problem is versus what is ‘fictitional’…however what I’m suggesting is that you can have one entry point and use the parameter to determine which service to invoke, but don’t use the pipeline variables to check security - instead if you enforce ACLs on internal invokes (those after the entry point service) even though you dynamically invoke the service, IS will still check the logged in user for subsequent flow steps.
I still don’t see why you would need 2 variables with the same name even though webMethods allows it. Also if you set ‘overwrite pipeline values’ no previous value can overwrite the ‘allowAccess’ variable as you described. Anyways, it sounds like you know enough about webMethods to come up with a feasible solution!
Hi Will - Thank for spending time and giving your inputs. I appreciate it. The solution does look secure - I thought I’d just fill in what it is for.
The service is the entry handler for the SAP OCI Shopping Cart standard. The OCI standard requires the user initiating the shopping session to POST special OCI variables – eg: ~Caller, HOOK_URL, Target – to the entry handler. The problem is the OCI standard also allows the user to POST any additional CGI variables “as required by the remote application”. For example, the OCI user could POST variables named: USERNAME, Password, CostCenter, etc - really, anything at all.
The aim was to build a secure OCI entry service without having to clear the pipeline (so as to ease future customization). I don’t need two pipeline variables to have the same name - infact the Java service above (“filterPipeline”) was written precisely to avoid this situation. Think of it as clearPipeline, but in reverse - with a “remove list”, rather than a “retain list”.