Open spring-operator opened 6 years ago
Rossen Stoyanchev commented
an external request, by default, causes a new execution key to be created, so only higher-scoped information (e.g. Session) would even be available, correct?
The number of executions per user is configurable. By default it is set to 1, so the answer is yes, but it is configurable.
Sorry, I obviously don't know for certain, so I'm looking for a clear explanation of what is possible and why or why not.
An attacker cannot just jump in the middle of a flow execution without a flow execution id and I don't see a way for them to have one. Flow execution state is invalidated (cleared) when the flow completes, or otherwise it expires and is relatively short-lived.
Doug Breaux commented
Thanks, but it seems like even if more executions are allowed, an external/direct link to the flow - even if it explicitly specifies an existing execution key - still starts a new one? Thus, anything stored in that prior execution's flow wouldn't be available? Only anything that would be stored up in the Session itself?
Again, apologize if I'm being thick.
Rossen Stoyanchev commented
It's easy to have a lost in translation moment without concrete details. The execution key does change on each step. If it starts a new flow execution it probably can't find a snapshot stored for that key in that user session. And it is correct that two flow executions for the same user session cannot share anything unless they store data explicitly in the Servlet session.
Doug Breaux commented
Let me try to make it more concrete.
I have /app/flowX that an attacker wants to exploit through CSRF.
Victim has accessed /app/flowX and is currently in a potentially-exploitable state, "exploitState", through the nominal path to get there in a straight sequence, let's say with execution=e1s5.
Attacker constructs a request and gets victim to submit it, that submits eventId and request parameters that would be valid for "exploitState", that would do something the victim doesn't want.
Attacker makes the request be to /app/flowX?execution=e1s5 (or 6?). The question is, can that work? If not, what exactly prevents it?
In my trying to cause this, any attempts to load /app/flowX, with or without an execution key, regardless of what I've put as the execution key value, I get redirected to start a new "e2s1".
But... it just occurred to me that I might have only tried HTTP GET so far, which I expect has different handling than POST would.
Anyway, does that help? I just can't tell whether a flow by nature is not vulnerable to CSRF, or whether it is, and I need to come up with an effective prevention.
Rossen Stoyanchev commented
If you know of an execution key that maps to a snapshot stored in the flow execution repository for the current flow execution, in the same Servlet session, then yes it should work. Those keys are pretty short-lived however as either the flow completes, or the user navigates enough times for older snapshots to be removed, or the session expires and all flow executions are removed.
Doug Breaux commented
That would make sense, but I haven't been able to make it work. Would it only work with a POST?
Rossen Stoyanchev commented
I'm not really sure, I would use the same as what's expected for that state. You can step through with a debugger, it shouldn't be hard to find out exactly why it starts a new flow execution.
Doug Breaux opened SWF-1729 and commented
I'm trying to persuade myself to what extent a Web Flow application would automatically not be vulnerable to CSRF. CSRF depends on an existing user "session", and, I think, either a stateless request that can be handled, or knowing exactly what state the user is in, so that you can cause an appropriate request to be sent for that state?
WebFlow is clearly not stateless. And, in fact, an external request, by default, causes a new execution key to be created, so only higher-scoped information (e.g. Session) would even be available, correct?
I guess an attacker familiar with the app could guess at e1 and sX, where X is some default path to the step they want to attack, but the victim would have to be there already? And even then, my testing seems to indicate that still a new execution will be started instead?
Sorry, I obviously don't know for certain, so I'm looking for a clear explanation of what is possible and why or why not.
I'd be happy to take this question elsewhere, but it seems like StackOverflow is the next-most-official support channel, and best I can tell it doesn't get much "official" attention. So I'm hoping this is an appropriate path.
Reference URL: https://stackoverflow.com/questions/2760701/prevent-cross-site-request-forgery-in-a-spring-webflow-application