0

I have an application build on top of Mojarra 2.1.20 (package com.sun.faces, RI for JSF 2.2 specification). I have a context param javax.faces.STATE_SAVING_METHOD with value as server specified in my application deployment descriptor file web.xml

JSF is injecting the following ViewState hidden element on my post login page

<input type="hidden" name="javax.faces.ViewState" id="javax.faces.ViewState" value="random_number1:random_number2" autocomplete="off" />

The hidden element has value in some random number format and separated by a colon. Since STATE_SAVING_METHOD is server, the actual ViewState in my case is getting stored on the server. But the client is just getting the unique ViewState identifier or random numbers from the server. My understanding is that when user submits a form with this hidden element, the server extracts these random numbers, identifies the actual ViewState from these numbers and then processes the request and sends back the response to the client/user.

Based on the above understandings, I have following queries on the ViewState and its vulnerabilities-

  • Why two colon separated random numbers instead of one? What these two colon separated random numbers represents? What autocomplete="off" means?

  • Does these server generated random number map to actual ViewState stored on the server? Is this understanding correct?

  • Are these server generated random numbers already in encrypted format? Is encryption required on these random numbers to potentially avoid data leak and other vulnerabilities in the application?

  • How to encrypt these random numbers in my case when ViewState is saved on server?

  • Could we somehow avoid injection of the element in sources without getting displayed as hidden element?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
vinsinraw
  • 2,003
  • 1
  • 16
  • 18

1 Answers1

1

Why two colon separated random numbers instead of one? What these two colon separated random numbers represents?

The view state is basically stored in a nested map like as Map<FirstId, Map<SecondId, ViewState>>. This map is in turn stored in the HttpSession. The first ID is the 'logical' view ID (basically representing XHTML page itself) and the second ID is the 'actual' view state ID.

What autocomplete="off" means?

It prevents web browsers from autofilling the value of the input element with previously submitted value from the browser cache. It should not be needed because the value is already prepopulated and the input element is a hidden type, but older Firefox versions were known to incorrectly overwrite this. Using autocomplete="off" is basically a work around against them.

Does these server generated random number map to actual ViewState stored on the server? Is this understanding correct?

Yes.

Are these server generated random numbers already in encrypted format? Is encryption required on these random numbers to potentially avoid data leak and other vulnerabilities in the application?

No.

How to encrypt these random numbers in my case when ViewState is saved on server?

Not needed.

Could we somehow avoid injection of the element in sources without getting displayed as hidden element?

Not needed. You would in first place still need the JSESSIONID cookie in order to be able to successfully perform view state injection. But when one already has the JSESSIONID cookie at hands then you've anyway much bigger problems than only ViewState tampering, such as potentially a gaping XSS hole. Moreover, in case of server side state saving the "injected" view state can only be user's own view state obtained from another page in the same HTTP session and absolutely not a random one from a completely different user/session.

Your security concern would only apply if the view state was stored in the ServletContext (the application scope) instead of in the HttpSession (the session scope). But this is clearly not the case.

See also:

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • @BaluC What the inner map object's value ViewState represents in the nested Map>? Also any reason why server requires the 'logical' view ID of the page? Does the framework passes the actual structure of the page without any data in nested Map object in VIewState? – vinsinraw Jan 24 '23 at 15:29
  • The value represents the view state itself. The logical view id is used so it's much easier manageable on a per-logical-view-id basis. Your last question makes no sense. I guess you have no clear idea what exactly a "view state" is. In that case, head here: https://stackoverflow.com/a/5475564 – BalusC Jan 24 '23 at 15:54
  • Thanks for the link. Per the actual structure of the page in my last query, I meant with the original JSF component tree. Could we say that the component tree structure makes up ViewState object on the client and forwarded to server along with firstId and secondId. Is this correct understanding? I am trying to understand the complete Life Cycle of JSF ViewState. Any pictorial rep of ViewState lifecycle would be extremely helpful. – vinsinraw Jan 24 '23 at 17:12
  • Absolutely not the component tree. It's basically rebuilt from scratch during view build time and then any attributes modified in previous request are restored from the view state during postback. Drill down into the "See also" links and the "See also" links thereof, if any, to learn more and more. One of them is https://stackoverflow.com/q/31890433 – BalusC Jan 24 '23 at 17:14
  • ok got it, will go over the links. My vulnerability team has insisted for encryption of ViewState. But as you mentioned that Encryption is Not Needed, is there any reasons that these numbers should not be encrypted in order to better convince them? – vinsinraw Jan 25 '23 at 16:00
  • As answered, it will require hijacking the session cookie in order to be able to change the view state. But when you already have the session cookie in first place then you have much bigger problems than merely a "injected" view state from another page of exactly the same user (impossibly of a different user). – BalusC Jan 25 '23 at 16:14