-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathHTML-Forms.lsp
130 lines (112 loc) · 8.95 KB
/
HTML-Forms.lsp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?lsp title="LSP & HTML Forms" response:include".header.lsp" ?>
<div class="rh">
<h1>LSP and HTML Forms</h1>
<p>HTML forms are used to collect user input and makes it possible for a browser to send user input to the server.
The server typically processes the received data and then dynamically produces a new HTML page,
which is sent in the response message to the browser.</p>
<div class="lspeditor" example="5.1"></div>
<p>Click the above Run button to display the HTML form.
When the user fills out the above form and clicks the submit button, the form data is sent for processing to the server.
Clicking the above run button and then the submit button in the generated page makes the browser send a
POST request to the server; however, the server side is not processing the information in the above example.
When we convert simple HTML pages into interactive applications we need to get user input to be processed at the server side.
The server side processing is done by <samp>Lua Server Pages (LSP)</samp></p>
<p>Let's add some server side Lua code to the above example. The server side code is run every time the page is accessed.</p>
<div class="lspeditor" example="5.2"></div>
<p>When the user fills out the form above and clicks the submit button, the form data is sent for processing to the URL of the page loaded in the browser.
With LSP, you can keep the server side processing in the same page or you can redirect the POST'ed
data to a separate page such as what is common when writing CGI scripts. You will find LSP much easier to use though,
since LSP makes it easy to create dynamic response data.</p>
<p>An LSP page provides a number of pre-defined variables such as the <a target="_blank" href="/ba/doc/?url=en/lua/lua.html#request">request object</a>
and the <a target="_blank" href="/ba/doc/?url=en/lua/lua.html#response">response object</a>.
The request object makes it easy to retrieve information provided by the client (the browser) and the response object is used
when sending response data back to the client. We use method <a target="_blank" href="/ba/doc/?url=en/lua/lua.html#request_data">request:data</a> on line 6
in example 5.2 to fetch the <a target="_blank" href="http://en.wikipedia.org/wiki/Percent-encoding">URL encoded data</a> sent from the browser.
This data is sent when the user clicks the Submit button. The URL encoded data is automatically converted to a Lua table by the server
and the data is presented as key/value pairs, hence the data for the HTML input element on line 14 is represented as "<code>luaTable.name</code>"
at the server side (line 7).</p>
<p><b>Note:</b> all the examples run in an HTML iframe just below the editor.
Clicking the Run button provides the same effect as clicking the browser's refresh button for the LSP code in the iframe.</p>
<p style="clear:both"></p>
<details open>
<summary>Server Side Form Validation</summary>
<p>Although form validation can be done in JavaScript code on the client side, form validation must still be done on the server side for security reasons.</p>
<p>The example below is a modified version of example 5.2, where we perform server side validation.
The example provides an introduction on how to validate code on the server.</p>
<div class="lspeditor" example="5.3"></div>
<br/>
<b>Example 5.3:</b>
<ul>
<li><b>Line 3 - 15:</b> This code is executed if the Submit button is pressed.</li>
<li><b>Line 5-7:</b> A function that uses a <a target="_blank" href="/ba/doc/luaref_index.html?url=manual.html#6.4.1">Lua regular expression</a>
to remove white space at either end of a string. The function returns <samp>nil</samp> if the argument '<samp>s</samp>' is <samp>nil</samp>.</li>
<li><b>Line 9:</b> We use the trim function to create a whitespace stripped copy of the form data '<samp>name</samp>' and '<samp>email</samp>'. </li>
<li><b>Line 10-13:</b> We validate the form data. Line 13 is using a
<a target="_blank" href="/ba/doc/luaref_index.html?url=manual.html#6.4.1">Lua regular expression</a> for email validation.
The form data '<samp>name</samp>' and '<samp>email</samp>' is guaranteed to be set if the data is sent from our HTML
form since the form includes these two named input elements;
thus you might wonder why we need to check for '<samp>nil</samp>' values on line 11.
A hacker probing the page using a command line based tool such as <a target="_blank" href="http://curl.haxx.se/">curl</a>
can send a POST request without setting these parameters.</li>
<li><b>Line 14:</b> We print out OK or Invalid Data without providing details on the invalid data.</li>
</ul>
<p>Click the above Run button and then the Submit button in the generated LSP page.
The page should print out "Invalid Data" without indicating where it failed. Enter some valid data and the page will print out 'OK'.</p>
<p>End users would find the form in example 5.3 extremely inconvenient to use since the data entered into the form ('<samp>name</samp>' and '<samp>email</samp>')
is lost when the user clicks the submit button. Enter data in the form above and notice how the two input elements are
cleared when the server sends the response data.</p>
<p>It's typical for server side generated web applications to be designed such that the application's state is preserved.
What this means for the above example is that we must find a way to save the data entered by the user.</p>
<p>The following example 5.4 is a modified version of example 5.3, which maintains the two elements '<samp>data</samp>' and '<samp>email</samp>'
if the data entered is incorrect. This enables the user to correct the data without having to retype all of it.
The page also indicates what input element that was entered incorrectly. When all data is entered correctly, the page saves the result and goes
to the next page. Note: we are not actually saving the data. You can see by the comment on line 12 where the data should be saved.
Line 14 would normally redirect to a new page. We simply redirect to a page displaying an image when the data is correct.
Notice how the value of the two input fields ('<samp>name</samp>' and '<samp>email</samp>') are maintained on line 21 and 23 below.</p>
<div class="lspeditor" example="5.4"></div>
<p>Click the above Run button and then the Submit button in the generated LSP page without entering any data.
You should see an Incorrect Data message next to the two input fields.
Next, enter Hello in both input fields. You should see an Incorrect Data message next to the <samp>email</samp> field.
The entered data is maintained (is persistent) and you can now modify the email field and correct the entered data
without having to retype the data in the name field.</p>
</details>
<details open>
<summary>Cross Site Scripting Attacks</summary>
<p>All forms above are open to <a target="_blank" href="http://en.wikipedia.org/wiki/Cross-site_scripting">cross site scripting</a> (XSS) attacks, in particular example 5.2, since this example emits the form data "as is" in the HTML response. Copy the following HTML and Javascript code, paste the data into the name field in example 5.2, and click Submit. </p>
<pre class="code" data-lang="Javascript"><script>alert("hello");</script></pre>
<p>Depending on the browser you use, you may get a JavaScript popup saying Hello. Some browsers include counter measures so you may have to try several browsers before you see the popup.</p>
<p>A common method used to prevent XSS attacks is to create a filter that translates symbols to the HTML escaped version of the symbols. The following code shows one way to create such a filter.</p>
<pre class="code">
-- Trim whitespace
local function trim(s)
return s:gsub("^%s*(.-)%s*$", "%1")
end
-- Symbols to escape
local escSyms= {
['&']="&amp;",
['<']="&lt;",
['>']="&gt;",
}
-- Escape symbols
local function escape(c) return escSyms[c] end
-- Trim and escape data from request:data()
local function xssfilter(inData)
local outData={}
for key,value in pairs(inData) do
outData[key] = trim(value):gsub("[&<>]", escape)
end
return outData
end
</pre>
<p>You can try the above filter code in example 5.2. Copy the filter code and add it to example 5.2 within the LSP tag. Then, modify the following:</p>
<pre class="code">
<b>From:</b>
local luaTable = request:data()
<b>To:</b>
local luaTable = xssfilter(request:data())
</pre>
<p>Click the run button after you have modified the script, and try to re-enter the XSS JavaScript code above. The JavaScript code should now be emitted in the HTML output and not cause the Hello popup message.</p>
<p><b>Library v.s. inline code:</b><br/>It's common to create a set of helper functions in Lua such as the above XSS filter code. Common code is typically put in a library and not directly inside an LSP page.</p>
</details>
<p id="NextBut"><a href="Ajax.lsp">Next Tutorial</a></p>
<?lsp response:include"footer.shtml" ?>