{
"cells": [
{
"attachments": {},
"cell_type": "markdown",
"metadata": {
"button": false,
"new_sheet": false,
"run_control": {
"read_only": false
},
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"# Testing Web Applications\n",
"\n",
"In this chapter, we explore how to generate tests for Graphical User Interfaces (GUIs), notably on Web interfaces. We set up a (vulnerable) Web server and demonstrate how to systematically explore its behavior – first with handwritten grammars, then with grammars automatically inferred from the user interface. We also show how to conduct systematic attacks on these servers, notably with code and SQL injection."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"execution": {
"iopub.execute_input": "2025-01-16T10:12:24.196618Z",
"iopub.status.busy": "2025-01-16T10:12:24.196521Z",
"iopub.status.idle": "2025-01-16T10:12:24.267608Z",
"shell.execute_reply": "2025-01-16T10:12:24.267345Z"
},
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
" \n",
" "
],
"text/plain": [
"
\n",
" We will send {item_name} to {name} in {city}, {zip}
\n",
" A confirmation mail will be sent to {email}.\n",
"
\n", " Want more swag? Use our order form!\n", "
\n", "\n",
" We will send One FuzzingBook Rotary Hammer to Jane Doe in Seattle, 98104
\n",
" A confirmation mail will be sent to doe@example.com.\n",
"
\n", " Want more swag? Use our order form!\n", "
\n", "\n", " The content of this project is licensed under the\n", " Creative Commons\n", " Attribution-NonCommercial-ShareAlike 4.0 International License.\n", "
\n", "\n", " To place an order, use our order form.\n", "
\n", "\n", " The content of this project is licensed under the\n", " Creative Commons\n", " Attribution-NonCommercial-ShareAlike 4.0 International License.\n", "
\n", "\n", " To place an order, use our order form.\n", "
\n", "\n", " This page does not exist. Try our order form instead.\n", "
\n", "\n", " This page does not exist. Try our order form instead.\n", "
\n", "\n", " The server has encountered an internal error. Go to our order form.\n", "
{error_message}\n",
" \n",
"\n", " The server has encountered an internal error. Go to our order form.\n", "
{error_message}\n",
" \n",
"' +\n",
" message +\n",
" \"\"))\n",
" else:\n",
" print(terminal_escape(message))"
]
},
{
"cell_type": "code",
"execution_count": 46,
"metadata": {
"execution": {
"iopub.execute_input": "2025-01-16T10:12:24.449910Z",
"iopub.status.busy": "2025-01-16T10:12:24.449833Z",
"iopub.status.idle": "2025-01-16T10:12:24.451794Z",
"shell.execute_reply": "2025-01-16T10:12:24.451589Z"
},
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"data": {
"text/html": [
"I am a httpd server message" ], "text/plain": [ "
I am another message" ], "text/plain": [ "
I am one more message" ], "text/plain": [ "
%s' % (url, url)))\n", " else:\n", " print(terminal_escape(url))" ] }, { "cell_type": "code", "execution_count": 59, "metadata": { "execution": { "iopub.execute_input": "2025-01-16T10:12:25.542650Z", "iopub.status.busy": "2025-01-16T10:12:25.542551Z", "iopub.status.idle": "2025-01-16T10:12:25.544668Z", "shell.execute_reply": "2025-01-16T10:12:25.544458Z" }, "slideshow": { "slide_type": "subslide" } }, "outputs": [ { "data": { "text/html": [ "
http://127.0.0.1:8800" ], "text/plain": [ "
127.0.0.1 - - [16/Jan/2025 11:12:25] \"GET / HTTP/1.1\" 200 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:25] INSERT INTO orders VALUES ('tshirt', 'Jane Doe', 'doe@example.com', 'Seattle', '98104')\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:25] \"GET /order?item=tshirt&name=Jane+Doe&email=doe%40example.com&city=Seattle&zip=98104 HTTP/1.1\" 200 -\n",
""
],
"text/plain": [
"\n",
" We will send One FuzzingBook T-Shirt to Jane Doe in Seattle, 98104
\n",
" A confirmation mail will be sent to doe@example.com.\n",
"
\n", " Want more swag? Use our order form!\n", "
\n", "127.0.0.1 - - [16/Jan/2025 11:12:25] \"GET /some/other/path HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"\n", " This page does not exist. Try our order form instead.\n", "
\n", "127.0.0.1 - - [16/Jan/2025 11:12:26] INSERT INTO orders VALUES ('lockset', 'Jane Doe', 'j_smith@example.com', 'Seattle', '16631')\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order?item=lockset&name=Jane+Doe&email=j_smith%40example.com&city=Seattle&zip=16631 HTTP/1.1\" 200 -\n",
""
],
"text/plain": [
"\n",
" We will send One FuzzingBook Lock Set to Jane Doe in Seattle, 16631
\n",
" A confirmation mail will be sent to j_smith@example.com.\n",
"
\n", " Want more swag? Use our order form!\n", "
\n", "127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order?item=drill&nae=Jane+Doe&email=j.doe%40example.com&city=Seattle&zip=45732 HTTP/1.1\" 500 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'name'\n",
""
],
"text/plain": [
"\n", " The server has encountered an internal error. Go to our order form.\n", "
Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'name'\n",
"\n",
" \n",
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /doe%40example.com&city=Seattle&zip=45732 HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order?item=drill&nae=Jane+Doe&email=j. HTTP/1.1\" 500 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'name'\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /ae=Jane+Doe&email=j. HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order?item=drill&n HTTP/1.1\" 500 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'name'\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /em=drill&n HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order?it HTTP/1.1\" 500 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'item'\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /er?it HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /ord HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /rder?it HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /oer?it HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /ord?it HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order HTTP/1.1\" 500 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'item'\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /rder HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /oer HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order HTTP/1.1\" 500 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'item'\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /oder HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /orer HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /ordr HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /orde HTTP/1.1\" 404 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET /order HTTP/1.1\" 500 -\n",
""
],
"text/plain": [
"127.0.0.1 - - [16/Jan/2025 11:12:26] Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'item'\n",
""
],
"text/plain": [
"\n", " The server has encountered an internal error. Go to our order form.\n", "
Traceback (most recent call last):\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/3183845167.py\", line 8, in do_GET\n",
" self.handle_order()\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1342827050.py\", line 4, in handle_order\n",
" self.store_order(values)\n",
" File \"/var/folders/n2/xd9445p97rb3xh7m1dfx8_4h0006ts/T/ipykernel_53958/1382513861.py\", line 5, in store_order\n",
" sql_command = \"INSERT INTO orders VALUES ('{item}', '{name}', '{email}', '{city}', '{zip}')\".format(**values)\n",
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
"KeyError: 'item'\n",
"\n",
" \n",
"127.0.0.1 - - [16/Jan/2025 11:12:26] \"GET / HTTP/1.1\" 200 -\n",
""
],
"text/plain": [
"