Forum OpenACS Development: Re: What's wrong with forms
When I refer to forms, I mean HTML forms in general, nothing in particular with OpenACS. I was trying to be somewhat non-specific as far as a solution because I will not be doing the work to include these ideas into ad_form or the cr's new tcl api.
The bottom line, as pointed out by a few others here is that forms in general are insecure if they rely on a single request to both validate what is on the form and accept form input. Also due to the transparency of the form source it is easy to use a predetermined attack against all users.
Maybe if I step through the process of form creation, validation and submission things might be more clear.
- Create a form: a tcl procedure or an ATS templating tag will initiate the form creation process. In the local context the form could have an easy to use name, but the form would be given an external name which would be difficult to guess. The easy to use name would be used later to add form elements, but the web user would never see this name and it wouldn't have any meaning outside the form creation process. This step would contain enough information to construct the form tag and would include a hidden field with the external form name. This external name would be a session level variable, and would serve as the key to finding the form later. The form data itself would be represented as an array of lists, in the simple case, an nsv array, although persistence in the database might be the goal.
- Add form elements: form elements would be added in a similar way using a tcl procedure or ATS tag. The procedure would reference the local form name. It would create a list of information. At the very least the list would contain the actual variable name to be used once the form is submitted, but could contain other information which would make form processing more efficient. For one, the initial value of the data could be included in the list. If the value didn't change, it would not need to be checked as heavily as new data, or for updates, it could be omitted from the update statement. Once the list is constructed, it would be added to the session level form array. The list might in the form of what
array get
would return, so list order would not be a problem, and so different form element types could have different types of information in the list. If an element to be added is a hidden type, it would not even need to be included on the external form, it would just be added to the form array.The element creation process would generate an external name for the input element, something of the form 'i12345...'. These don't need to be secure as much as unique. Even identically named inputs would generate unique external names. It might be helpful it the form structure maintained a var name to external name mapping (list), so you could quickly find all variables with a given name.
- Validation: assuming the first stop in form submission is validation, each element of the form would go through validation after the initial form is submitted. The hidden form name would be used to look up the form, make sure it is tied to the current session and validate the data. The validated data would be added to the session level form array. Invalid data could be presented in a scaled down form showing only the problems in an editable format, other data could be shown either editable or not. Uploaded files would be saved in a temporary location for the next step, or if there was a file error, allow fixing this problem during this step. This step would repeat until all form data was valid, and then a simple form with a 'commit changes' button or something similar, and the hidden form name field.
- Form Commit: The form commit would use only the values in the stored session level form array. Obviously if the form didn't exist, the session was invalid, or valid data was never submitted beforehand this step would fail.