Professional Documents
Culture Documents
Suthee Kitcharoenkarnkul
Signed:
Security Analysis of University
Databases/Services
COPYRIGHT
Attention is drawn to the fact that copyright of this dissertation rests with its author. The
Intellectual Property Rights of the products produced as part of the project belong to the
author unless otherwise specified below, in accordance with the University of Bath’s policy
on intellectual property (see http://www.bath.ac.uk/ordinances/22.pdf).
This copy of the dissertation has been supplied on condition that anyone who consults it
is understood to recognise that its copyright rests with its author and that no quotation
from the dissertation and no information derived from it may be published without the
prior written consent of the author.
Declaration
This dissertation is submitted to the University of Bath in accordance with the requirements
of the degree of Bachelor of Science in the Department of Computer Science. No portion of
the work in this dissertation has been submitted in support of an application for any other
degree or qualification of this or any other university or institution of learning. Except
where specifically acknowledged, it is the work of the author.
Signed:
Abstract
SQL injection is regarded as the most dangerous and famous hacking technique against
web applications and database systems [34]. An attacker can use this technique to exploit
web application vulnerabilities in order to manipulate data in database systems, leading
to theft, modification, or destruction of sensitive information. The University of Bath
provides many online services, for example, the Moodle e-learning system. Nevertheless,
there is no SQL injection vulnerabilities assessment officially performed. This research
gives an opportunity to scan and analyze the security of the university online services and
databases, especially SQL injection vulnerabilities. In addition, it proposes a new concept
to prevent SQL injection attacks. There are many pieces of research about SQL injection
prevention, but most of them require application code modification or are deployed in the
middle between a web server and a database server. These conditions lead to an inability to
implement in some environments. Therefore, ReppSi, an SQL injection prevention system
in this research, is designed to be deployed in front of the web server as a reverse proxy and
does not need to modify the application code. An approach used to detect SQL injection
attacks based on the behavior-based detection. The operation is divided into two phases, a
learning phase and a protection phase. In the learning phase, the behaviour-based detection
system collects the characteristics of using the web application. Then, in the protection
phase, it creates profiles as security rules to detect unauthorized (anomalous) web usage,
for example, an SQL injection attack hidden inside the HTTP request. The results of the
experiments show that ReppSi could detect 100 percent of SQL injection attacks with only
one false positive, but it could block the attacks only 92 percent due to the limitation of
the program. Additionally, the average process time of the ReppSi system is less than 5
milliseconds that are very low compared to the average response time of the direct request
without the ReppSi deployment.
Contents
1 Introduction 1
1.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 Motivation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3.2.1 Tautologies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
3.2.6 Inference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
ii
CONTENTS iii
4 Literature Reviews 14
4.3.2 Using Parse Tree Validation to Prevent SQL Injection Attacks [4] . . 18
4.5 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.3 Summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
CONTENTS iv
6 Design 36
6.3.1 Listener . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
6.3.5 Logger . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6.3.6 Sender . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
7 Implementation 51
8 Experiments 74
8.4 summary . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
9.1 Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
10 Conclusion 96
C.1 The Moodle E-learning System Vulnerability Scanning by OWASP ZAP . . 113
C.2 The Moodle E-learning System Vulnerability Scanning by Subgraph Vega . 126
C.5 The SQL injection alerts of the Super Veda application Scanned by OWASP
ZAP (Before) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
C.6 The SQL injection alerts of the Super Veda application Scanned by Subgraph
Vega (Before) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
4.2 An example of the parse trees before and after the inclusion of the user-
supplied input [4] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
4.4 The deployment of the systems installed between the web server and the
database server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5.2 Comparison between the web page and its source code . . . . . . . . . . . . 30
7.1 A comparison between the modules in ReppSi and the tools for implementation 53
viii
LIST OF FIGURES ix
7.9 An example of the system event logs and the alert logs . . . . . . . . . . . . 70
8.3 An example of the profile table that digested the data from the log table . . 76
8.5 The result of bypassing the authentication system using SQL injection . . . 78
8.7 The alert from the log file (See more details of the log file in Appendix C.4) 79
8.8 A comparison between the OWASP ZAP’s log and the ReppSi’s log for
/dosearch.jsp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
8.9 A comparison between the OWASP ZAP’s log and the ReppSi’s log for
/register.jsp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
8.10 A comparison between the SQL exception and the source code . . . . . . . 82
8.12 The response time of browsing the Moodle service from London [48] . . . . 88
A.3 Java build path that the Membrane libraries have been already imported . 107
LIST OF FIGURES x
B.1 The Java console prompts the user for the operation mode . . . . . . . . . . 109
C.16 The Web Browser XSS Protection Not Enabled alert of http://moodle.
bath.ac.uk/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
C.44 The Cookie HttpOnly Flag Not Set alert of http://moodle.bath.ac.uk/ . 141
C.46 46 affected URLs of the X-Frame-Options Header Not Set alerts . . . . . . 142
C.52 An example of the log file generated by the ReppSi system . . . . . . . . . . 146
C.53 The SQL Injection - Authentication Bypass alert of Super Veda 1 . . . . . . 147
C.54 The SQL Injection - Authentication Bypass alert of Super Veda 2 . . . . . . 147
C.56 The response body of the SQL Injection - MySQL alert . . . . . . . . . . . 149
C.57 The MySQL Error Detected - Possible SQL Injection alert of Super Veda . 150
C.58 The response body of the MySQL Error Detected - Possible SQL Injection
alert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
8.1 The result of scanning Super Veda by OWASP ZAP before ReppSi deployment 79
8.2 The result of scanning Super Veda by OWASP ZAP after ReppSi deployment 80
8.3 The number of the OWASP ZAP requests, the SQL exceptions generated,
and the SQL injection attacks that pass through the ReppSi system . . . . 83
8.4 The summary result of scanning Super Veda using Subgraph Vega before
ReppSi deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
8.5 The summary result of scanning Super Veda using Subgraph Vega after
ReppSi deployment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
xiv
Acknowledgements
Many thanks to Prof. James Davenport, my supervisor, for providing great guidance
and assistance throughout the seven months of the dissertation period.
Many thanks to Asst. Prof. Krerk Piromsopa, my advisor from Chulalongkorn Uni-
versity, for inspiring me to be interested in computer security and educating me about
research method while I was studying in the University.
Many thanks to my colleague who always put pressure on me, as well as motivated
me to work on my dissertation.
Finally, . . . many thanks to my mother who always believed in me, encouraged me,
and supported me. I love you.
xv
Chapter 1
Introduction
1.1 Background
In the age of the Internet that everyone can easily connect to and communicate with
each other, information is regarded as an important thing in the world. To provide the
convenience of collecting and accessing an amount of the information, the digital format
has been increasingly used to store that information [24]. For example, the civil regis-
tration recorded by the government used to be stored in the paper-based format, but, in
the present, most governments have stored them in their database systems in the digital
format [10, 11, 16]. Likewise, patient records of many health care organizations have been
gradually converted from the paper-based format to the digital format so that the patients
could access their information using computers and the Internet [32]. In addition, business
information, financial information, or other information that was recorded in the papers
should be converted to the digital format due to a lot of benefits. The digital format pro-
vides faster access to and retrieval of the information, better service delivery from the ease
of locating the relevant information, less time spent looking for the information, simpler
backup as well as recovery, and cost saving because of less creation, storage, retrieval, and
handling of paper records [30].
1
CHAPTER 1. INTRODUCTION 2
Sybase, PostgreSQL, and so on [38]. Originally, DBMSs were used by programmers. The
stored data could be accessed via a program that the programmers wrote using a com-
plex programming language, such as COBOL. One program was responsible for a specific
purpose. If users wanted to access other data, it often required the DBMS programmers
to write new software, leading to an expensive for ad-hoc, or one-time, inquiries. Struc-
tured Query Language (SQL), invented by IBM in the 1970s, was developed as a simple
programming language that allowed non-technical users to easily contact the DBMSs in
order to access and manage data stored in the databases. The users could send requests to
the databases using simple SQL queries. Consequently, the SQL language has been widely
used in a great number of database management systems and database applications [27].
However, the SQL also required a basic skill of computer programming. Database users
need to learn some keywords and syntax to create queries sent to the databases. In some
cases, the users need to create very complex SQL queries to retrieve only specific data from
huge databases. As a result, a database application, computer software whose main purpose
is to enter and retrieve information from computerized databases, was invented to help the
users. It has an ability to create automatically SQL queries from the user’s input via the
application. Many database applications have been developed for multiple purposes. Most
organizations in the world, such as retail chain stores, government departments, financial
institutes, manufacturing enterprises, education, etc., use their database systems, including
databases, DBMSs, and database applications, to keep essential information they need to
run the businesses [38]. One of the most complex database systems is accounting system
from SAP which might contain several thousands of tables in a single module [5]. Another
famous enormous database system designed for social networking is Facebook which was
built on top of MySQL [23].
The advent of the Internet and the World Wide Web (WWW) provides more features
to the database systems. The Internet and the WWW have offered unique information
delivery mechanism which has allowed people throughout the world to communicate and
exchange information with each other. International Telecommunication Union [17] states
that there are almost 3 billion people (around 40 percents of the world population) who
use the Internet this day. Additionally, the growth rate has been increasing noticeably
year by year. Instead of designing applications specific for certain platforms, programmers
capitalized on the WWW and the Internet to create web-based applications (i.e., web ap-
plications or web services) on the top of DBMSs. The web application is cross-platform and
has become the most powerful data repository and information delivery system. Combined
with the Internet, it allows everyone to access and share information from anywhere in the
world. Most enterprises have taken advantage of the WWW and the database system to
CHAPTER 1. INTRODUCTION 3
create many kinds of web applications for multiple purposes, for example, online shopping,
online banking, online video streaming, online restaurant booking, and so on [38]. In ad-
dition to those business purposes, the web application has been widely used in education
such as library systems, registration systems, and e-learning systems. For the University of
Bath, there are many web services provided to staff, lecturers, and students, for instance,
SAMIS the University’s central database of student records, online library services that the
students can search for ebooks, online journals, or other academic articles, and Moodle a
learning platform [40].
1.2 Motivation
The undesirable thing that has followed the widespread use of web applications is a
cyber threat. People take advantage of using the web applications so that they can access
information on the Internet, communication with other people, and use online services for
the purpose of convenience. Similarly, attackers can exploit the web applications in order
to access or manipulate sensitive data in the databases without permission due to the
improper coding that leads to serious weaknesses or vulnerabilities. Many of the databases
contain valuable information, such as personal and financial details, making them a frequent
target of the attackers. The attackers exploit the web applications for several purposes,
e.g., showing their hacking skill to the world or launching political attacks. However, most
the attacks are financial motivated because the attackers could sell the information to the
organizations’ adversaries or even ask for ransom. The most popular and dangerous attack
against the database systems via the web applications is SQL injection [1].
The latest data breach investigations report from Verizon [46] points out that data
breaches in 2013 were caused by many types of threats such as point-of-sale intrusions,
insider misuse, cyber-espionage, crimeware, etc. However, the main cause was web ap-
plication attacks which took 35 percents of all types of the threats. There are a lot of
reasons why the attackers primarily targeted web applications. Firstly, web applications
must be available 24/7 to provide their services to employees, customers, and other stake-
holders. The attackers can launch attacks against web applications all the time. Secondly,
port-based firewalls and SSL cannot protect web applications from attacking since access
to the web applications have to be made public. In other words, port 80 (HTTP) and
443 (HTTPS) have to allow all traffic from both insiders and outsiders. It is difficult to
make the good/bad traffic distinction. Thirdly, web applications often connect directly to
backend databases. The attackers could exploit the web applications to access valuable
CHAPTER 1. INTRODUCTION 4
data in the databases. Finally, most web applications are custom software which involves
a lesser degree of testing than commercial off-the-shelf software. Consequently, they are
more susceptible to attack [1].
For education, the report of Verizon [46] also discovered that education experienced
data breaches caused by web application attacks which were ranked second after miscella-
neous errors. Although the loss of the educational industry cannot be comparable to that
of financial institutes, government departments, or large enterprises, it has to confront a lot
of skillful students. Some of them may study computer science and want to test their new
hacking skills. Some may attack the university systems for some purposes such as steal-
ing exam papers, modifying the scores, or delaying assessment testing. More importantly,
some IT staff in the university might think that the university has no valuable informa-
tion. Hence, they do not seriously take concern about the security systems. As a result,
the university may leave security vulnerabilities unpatched, leading to being attacked by
attackers.
For the University of Bath which provides many online services, my supervisor, Prof.
James Davenport, is in close liaison with Mark Acres, the University Computer Security
Manager. We found that there were no vulnerabilities assessment and analysis of this kind
officially performed. This research will give an opportunity to scan and analyze the security
of the university’s online services and databases, especially SQL injection vulnerabilities.
To fix the vulnerabilities, there are many pieces of research about SQL injection de-
CHAPTER 1. INTRODUCTION 5
tection and prevention in the present. Although most of them are capable of handling SQL
injection attacks, they cannot implement in the real world without disturbing the applica-
tion systems. In other words, they need to modify the application code or be deployed in
the middle between the web server and the database server. In some situations that code
modification is not allowed or the web server and the database are on the same physical
server, it is difficult to apply those pieces of research to the application systems.
• Discover and analyze the vulnerabilities of the university’s e-learning service, the
Moodle system.
• Implement and test the security system that is easy to install and does not require
application code modification.
CHAPTER 1. INTRODUCTION 6
• Implement and test the security system that can detect and prevent SQL injection
attacks.
1.5 Summary
In this paper, an analysis of the University of Bath’s online services and information
about the research of protecting web applications from being attacked by SQL injection
will be presented. It begins with the background of the university including databases/ser-
vices that the university has been using, in Chapter 2. Then, Chapter 3 shows the basic
concept of the SQL injection attack which is the primary threat this research would like to
mitigate. Moreover, this chapter will show types of SQL injection attacks and their effects
on the database system. After that, reviews of related researches in the past as well as their
strengths, weakness, and other comments will be described in Chapter 4. Chapter 5 pro-
vides security analysis of the University’s e-learning service, the Moodle system, using two
well-known web vulnerability scanner tools, OWASP ZAP and Subgraph Vega. Next two
chapters, Chapter 6 and 7, are the primary sections of this research. They present design
and implementation of the proxy “ReppSi” used to prevent the university’s databases/ser-
vices from the SQL injection attack. Then, Chapter 8 shows results and analysis of using
the ReppSi proxy to detect and prevent a web server from being attack by SQL injection.
Finally, the paper provides information about limitations, future works, and conclusion in
Chapter 9 and 10.
Chapter 2
The University of Bath provides many online services to students, lecturers, and staff
so that they can access the university resources and databases from anywhere without going
to the university. There are three important web services including Moodle, the library
system, and the registration system.
Moodle is a free, online learning management system designed for both lecturers and
students. The lecturers can create courses, upload slides and learning materials, create
assignments, and give a mark along with comments to the students. For the students, they
can check the courses they attend, view and download the learning materials, submit the
assignments, and see their scores, as well as comments from the lecturers. Moodle also
provides forums so that the lecturers and the students can have a discussion. Besides, it
has a notification system that automatically alerts the students for new assignments as well
as deadline, and forum posts [29].
The library online system is offered by the Library & Learning Centre. The main
function is to store information about books, dissertations, journals, and other educational
materials. It also stores electronic versions (i.e., ebooks, e-journals, etc.) of those materials
which students, lecturers, and staff can search and view online. The library system is
linked to other publisher databases, such as ACM, IEEE, so that the users can access
varied electronic materials around the world. Additionally, the library system provides
information about borrowing and returning books which the users can track the status
from borrowing to returning items via the library website. The users can check and renew
their loans as well as place a reservation online as well [44].
The registration system powered by Student records & Examinations Office provides
7
CHAPTER 2. THE UNIVERSITY BACKGROUND 8
online information about registration for both new students and existing students. Inside
the registration system, there is a core service called SAMIS (Student & Applicant Manage-
ment Information System), the university’s central database of student records. It stores
information about applicants and students. The users can access SAMIS via the website,
or the full database can be accessed via a PC client-server. Students can view their units,
personal details, exam timetables, and choosing their units on-line. SAMIS is connected to
other computer systems across the university network and the Library & Learning Centre.
The registered status of the student on SAMIS provides access to university resources such
as the library resources, email, gaining a Students’ Union card [40].
In addition to those three main web services, there are many websites providing on-
line information and services, for example, websites for departments and faculties, a web
application for computing services, a website about the campus life, and so on.
In this research, security analysis will begin with Moodle since it is an important
e-learning system that both students and lecturers usually access everyday. More impor-
tantly, Moodle does not use SSL encryption, in other words, it is a unencrypted HTTP
website. Therefore, it cannot prevent third parties from eavesdropping on communications
between clients and web servers, leading to more online risk exposure to cyber attacks. Fur-
thermore, the Moodle template used to be vulnerable to SQL injection attacks more than
ten times starting from version 1.4.1 in 2004 to the latest version 2.8.5 in the present. The
programmers are also required to write additional code to prevent SQL injection attacks
[9, 28].
Chapter 3
A successful SQL injection attack can read sensitive data stored in the database,
modify data (insert, update, delete), execute administration operations on the database
such as shutdown the DBMS, and, in some cases, issue commands to the operating system.
The SQL injection attack is ranked first on the top ten most critical web application security
risk conducted by OWASP [34].
9
CHAPTER 3. SQL INJECTION ATTACKS 10
3.2.1 Tautologies
SQL tokens are injected to the conditional SQL statement in order to be evaluated
always true. This type of attack is often used to bypass authentication and access to data
by exploiting non-validated input using WHERE clause.
When an SQL query is rejected, the database will return an error message including
debugging information. An attacker can use this information to find vulnerable parameters
and the type as well as structure of the database.
Example: An attacker injects the following string into the password input field:“convert(int,
(select top 1 name from sysobjects where xtype=‘u’))” in order to cause a type conversion
error which can reveal database information. The result query is:
The MsSQL Server with the metadata table called sysobjects will return an error: “Mi-
crosoft OLE DB Provider for SQL Server (0x80040E07) Error converting nvarchar value
‘CreditCards’ to a column of data type int” From the error, the attacker will know that
the database is a MsSQL Server and the string’s value that caused the type conversion to
occur.
An attack can join an injected query to the safe query using the keyword UNION in
order to obtain extra information related to other tables from the web application.
CHAPTER 3. SQL INJECTION ATTACKS 11
The null set will be returned for the original first query whereas the second query will
return data from the “creditcard” table (column “cardnumber” for account “10032”).
This attack allows an attacker to exploit a database using the query delimiter such
as “;” in order to append an extra query to the original one. A successful attack causes
the database to receive and execute both the original query and the extra query which
is usually illegitimate. As a result, the attacker can access data, modify data, or execute
remote commands.
Example: An attacker injects “’; DROP table users --” into the password field. The result
query is:
After finishing the first query, the database recognizes the query delimiter “;”, and then
executes the injected second query which would drop table users.
A stored procedure is a set of SQL statements that form a logical unit as well as
perform a particular task. It is used to encapsulate a set of queries or operations to
execute on a database server. For instance, operations on an employee database (e.g., hire,
fire, promote, lookup) could be written as stored procedures executed by the application
code. As the stored procedure could be coded by the programmer, it could be injected
by an attacker as well. Depend on the backend database, SQL injection attacks can be
built to execute stored procedures specifically provided by that database, including stored
procedures that interact with the operating system.
CHAPTER 3. SQL INJECTION ATTACKS 12
3.2.6 Inference
This type of attack is used against a high-security database. An attacker tries to get
information from the database by injecting various SQL commands into the web applica-
tion and then observes how the response/function of the application changes. The SQL
commands usually bases on true/false question about data values in the database. Con-
sequently, the attacker can deduce whether certain parameters are vulnerable and extra
information about the values in the database. There are two well-known inference attacks,
blind injection and timing attacks.
Alternate encoding is evasion technique which allows an attacker to escape from the
detection system that scans input queries for certain known “bad characters”. The attacker
can modify the injected queries using alternate encodings such as hexadecimal, ASCII, or
Unicode. This technique is usually used with other types of attacks.
Example: The following string is injected into the username field: “admin’; exec(char
(0x73687574646f776e)) --”. The result query is:
The impact and consequences of successful SQL injection attacks can be classified into
four categories.
• Integrity: Attackers can use SQL injection attacks to modify or delete critical in-
formation in the database without permission.
• Authentication: Due to poor user validation, SQL injection attacks allow attackers
to bypass authentication. The attackers can access to the database as an authenti-
cated user without knowledge of the username and password.
Literature Reviews
So far, there are many pieces of research which develop new frameworks, algorithms,
or techniques to detect and/or prevent SQL injection attacks. In this paper, those pieces
of research are classified into five categories according to their techniques including static
analysis, dynamic analysis, model-base approach, and anomaly-base approach. The com-
parison of all techniques used in each research is shown in table 4.1.
14
CHAPTER 4. LITERATURE REVIEWS 15
Wassermann and Su proposed an approach that combined static analysis and au-
tomated reasoning to verify user-supplied inputs. If the SQL queries generated by the
user-supplied inputs contain tautologies, they will be detected. They used the static anal-
ysis from Chistensen et al. [6] to generate finite state automata (FSA) for modeling a set
of valid SQL queries for each hotspot on the source code of the application that connects
to the database. Then, the context-free language (CFL) reachability algorithm was used
to analyze the structures and keywords of the valid SQL queries in the FSA so that they
CHAPTER 4. LITERATURE REVIEWS 16
could detect the presence of tautologies in WHERE clause which usually are signs of SQL
injection attacks. Moreover, the permission of using SQL commands, such as SELECT,
INSERT, UPDATE, DELETE, etc., for each user was checked. If the user did not have the
permission of using the certain command, the access control violation would be discovered.
This approach provides strong tautology-based SQL injection detection. However, this
is the primary drawback as well. This approach is limited to only detecting the tautology-
based attack which is only one of the many types of SQL injection attacks [20]. It also
cannot handle some SQL queries that contain the operator “LIKE” and “×”. Besides,
large and complex SQL queries lead to very big FSA which may cause high latency [4].
Instead of using normal SQL keywords, Boyd and Keromytis create SQL queries using
randomized instructions. That is, the SQL keywords in the source code are manipulated
by putting a random numbers (key) after the keywords. An example when the key is “123”
is shown below.
A proxy server implemented between the web server and the database server intercepts
the randomized SQL queries and de-randomizes the SQL keywords before forwarding the
normal SQL queries to the database. If the user tries to attack the web application using
SQL injection attacks, some SQL keywords must be input. However, the SQL keywords
from the user-supplied input will not be randomized. Therefore, the proxy’s parser will fail
to de-randomized the SQL keywords and reject the attacks.
The proxy server is also used to intercept an exception from the database so that
information about the database will not be revealed to the attacker. Nevertheless, the
security of using this approach depends on the key and the proxy server. If the attacker
compromises the key or the proxy server, SQLrand will not be able to prevent the attacks
[12, 20]. In addition, the source code must be modified to append a random key to SQL
keywords.
CHAPTER 4. LITERATURE REVIEWS 17
Halfond, Orso, and Manolios proposed an automated approach that detects and pre-
vents SQL injections based on the dynamic tainting mechanism which marks and tracks
certain data in an application at runtime. In other words, they identify “trusted” strings
in a program, mark them, and allow only these trusted strings to be created as certain
parts of the SQL query, such as SQL keywords or operators. The trusted strings in a
program are the whole code written by the programmer and the untrusted strings usually
are user-supplied inputs. In runtime, syntax-aware evaluation is used to distinguish the
trusted strings from the untrusted input data and make sure that all parts of an SQL query
other than string and numeric literals, i.e., SQL keywords and operators, consist only of the
trusted strings. If an SQL query contains strings not marked as trusted, it is assumed that
the application have been attacked by SQL injection, and the SQL query will be blocked.
Using positive tainting provides a lot of benefits. It is easier to marking and tracking
trusted data source than untrusted one. Missing untrusted data leads to false negatives,
that is, successful undetected attacks. In contrast, missing trusted data would lead to false
positives, i.e., legitimate SQL queries are classified as attacks, which are better. Addition-
ally, this approach can detect and prevent all kinds of SQL injection attacks [43]. On the
other hand, it has several drawbacks. For example, the application and its byte code must
be modified to mark the trusted strings, and the programmer is required to review the
marking process in order to prevent false positives.
AMNESIA can detect all kinds of SQL injection attacks except stored procedure
[22, 43]. Nonetheless, its capability depends on the precision and efficiency of the static
analysis for building the models. Incomplete building the models may lead to both false
negatives and false positives [2, 13]. Furthermore, it uses Java String Analyzer to analyze
the web application code and thereby obtain the query models. Hence, web applications
other than those developed using JSP, e.g. PHP or ASP, are not supported.
4.3.2 Using Parse Tree Validation to Prevent SQL Injection Attacks [4]
Buehrer, Weide, and Sivilotti implemented the SQLGuard using parse tree validation
to detect SQL injection attacks. Firstly, SQLGuard analyzes the application code and
create parse trees for every SQL statement before the inclusion of the user-supplied input.
At runtime, the parse tree for the SQL statement after the inclusion of the user-supplied
input will be created to compare with the original one, as illustrated in figure 4.2. If the
user- supplied input contains SQL keywords or operators, it will make the parse tree at
runtime different from the original parse tree and be suspected of an SQL injection attack.
CHAPTER 4. LITERATURE REVIEWS 19
Figure 4.2: An example of the parse trees before and after the inclusion of the user-supplied
input [4]
This approach is efficient and easy to validate the user-supplied input whether it
contains an SQL statement or a sub-statement. However, there are two major drawbacks.
The application code is needed to be modified, and a secret key is required for encapsulating
the user-supplied input. If the key is compromised, SQLGuard will fail to detect SQL
injection attacks [20].
Su and Wassermann proposed the SQLCheck that used the similar technique as the
SQLGuard introduced by Buehrer, Weide, and Sivilotti [13, 20]. But instead of using a
secret key to wrap the user-supplied input, they add the key at the beginning and the
end of every user-supplied input. At runtime, any SQL statement that is not in a valid
syntactic form is suspected as an SQL injection attack.
CHAPTER 4. LITERATURE REVIEWS 20
Both SQLCheck and SQLGuard can detect all typed of SQL injection attacks except
stored procedure [22, 43]. Like the SQLGuard, the SQLCheck has two major weaknesses.
The application code is required to be modified in order to identify and annotate user-
supplied inputs. Missing identifying the user-supplied inputs may lead to false negatives
[13]. Moreover, the detection ability depends on the strength of the secret key [20].
SQL-IDS introduced by Kemalis and Tzouramanis has the similar concept as a general
signature-based intrusion detection system. Specifications of the web application must be
defined. They collect a set of rules which describe the expected structure of all SQL queries
that are generated by the application. SQL-IDS consists of two modules. Event monitoring
module intercepts SQL queries sent to the database and forwards them to the validity
check module which compares the structures of the SQL queries with those described by
the pre-defined specifications. If the queries do not conform to the specifications, they are
considered as SQL injection attacks. Then, the event monitoring module drops the queries.
Figure 4.3 shows the architecture of SQL-IDS.
The advantages of the SQL-IDS are that the programmer does not need to modify
the application code, and it is independent of any application environment or DMBS. In
contrast, the primary drawback is that the detection ability bases on the completeness of the
specifications. The application develop need to define the specifications by himself/herself,
leading to false positives and false negatives as a result of the gaps in such a specification.
This approach was developed under the concept of behaviour-base SQL injection de-
tection. Valeur, Mutz, and Vigna proposed an IDS system based on a machine learning
technique. This approach is divided into two phases, a learning phase and a monitoring
phase. In the learning phase, profiles of the legitimate SQL queries are created from the
normal database access performed by the web application. In the monitoring phase, SQL
queries sent to the database are compared with the structures of the SQL queries in the
profiles. If the queries do not match the pre-defined structures, they are suspected of SQL
injection attacks.
The main disadvantage of this approach is that the effectiveness of detecting SQL
injection attacks depends on the profiles learned from the normal situation. If the profiles
are incomplete, it may lead to high rate of false positive [2, 12]. Besides, this approach
is not designed to detect directly SQL injection attacks. It is developed to detect the
anomalous behavior while the users from using the web application.
Bandhakavi and his team members proposed an SQL injection detection tool called
Candidate evaluation for discovering intent dynamically or CANDID. This approach tries to
create automatically the structure of the programmer-intended SQL query from every part
of code connected to the database so that it can solve the issue of manually modifying the
application code to create the prepared statements. This process can be done by recording
the legitimate SQL queries and learning their structures. At runtime, the structures of the
SQL queries sent to the database are compared with the pre-defined structures in order to
detect SQL injection attacks.
CHAPTER 4. LITERATURE REVIEWS 22
Like the IDS system proposed by Valeur, Mutz, and Vigna, the detection ability
depends on the prepared statements built from the normal database access. It might be
impossible to make a complete of legitimate SQL structures for a large web application.
4.5 Summary
In conclusion, there are a lot of pieces of past research using various techniques to
detect and prevent SQL injection attacks, for example, static analysis, dynamic analysis,
model-based, or anomaly-based methods. Each of them has its own advantages and lim-
itations. Some of them need to modify the application code to create the models used
to detect SQL injection attacks at runtime. Some of them design SQL detection systems
installed between the web server and the database server, as presented in figure 4.4, in
order to inspect SQL queries generated by the web application.
Figure 4.4: The deployment of the systems installed between the web server and the
database server
However, the application source code may be not allowed to modify in many situations,
especially in banking and financial systems. In addition, in some environments such as a
web application on a single server with a built-in database deployment or a virtual machine
running both a web server and a database server, it is difficult to install the SQL detection
systems in the middle of the web server and the database server. To eliminate these
problems, this research will design an SQL prevention system that can be easily installed
in front of the web server and does not need to alter the application code.
Chapter 5
After reviewing the pieces of research in the past, the security system is decided to
be deployed in front of a web server in order to avoid code modification and incapability
of installing in some environments. Next step is to determine an approach to detect SQL
injection attacks. To assure that the approach can fix the SQL injection vulnerabilities
and protect the University’s e-learning service, Moodle, from being attacked, vulnerabil-
ity assessment must be performed. The Moodle system will be evaluated to discover and
identify web security vulnerabilities, especially SQL injection flaws. Two well-known web
application vulnerability scanners are used to provide comprehensive patterns of SQL in-
jection attacks. After that, the results will be analyzed and applied to design the effective
approach to detect SQL injection attacks.
The objective of the assessment is to discover and identify web security vulnerabilities
of the Moodle e-Learning system, especially the vulnerability that can cause SQL injection
attacks. Two different web vulnerability scanning tools are used to search for security holes
in all directories under the domain moodle.bath.ac.uk. The procedure of the assessment is
shown below.
23
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 24
As illustrated in figure 5.1, the machine running web vulnerability scanning tools con-
nects to the internal network via the university-provided Wi-Fi “eduroam” so that traffic
from the machine is not inspected by the firewall. The Moodle website (http://moodle.bath.ac.uk)
will be logged in using a student account. Consequently, all HTTP requests from the scan-
ning tools can pass the authentication system.
Two web vulnerability scanning tools consist of OWASP ZAP and Subgraph Vega.
• ZAP or Zed Attack Proxy is an open source penetration testing tool developed by
OWASP for finding vulnerabilities in web applications. It can scan many types of
web application attacks such as SQL injection, cross-site scripting, cross-site request
forgery, etc [37].
• Vega is a free, open source vulnerability scanner and testing platform developed by
Subgraph. It is a cross-platform, GUI-based, Java application designed to help IT
administrators to find vulnerabilities in their web applications [42].
Both of them are up-to-date software at the assessment time (ZAP version 2.3.1 and
Vega version 1.0). Each scanning tool is configured to scan all web vulnerabilities in its list
as shown in the next page.
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 25
AJAX Detector, Bash Environment Variable Blind OS Injection, Blind OS Command Injec-
tion Timing, Blind SQL Injection Arithmetic Evaluation Differential, Blind SQL Injection
Timing, Blind SQL Text Injection, Differential Checks, Blind XPath Injection Checks,
Character Set Not Specified, Cleartext Password Over HTTP, Credit Card Identification,
Cookie Scope Detection, Cookie Security Module, Cross Domain Policy Auditor, Directory
Listing Detection, E-Mail Finder Module, Empty Response Body Module, Error Page De-
tection, Eval Code Injection, File Upload Detection, Form autocomplete, Format String
Injection Checks, HTTP Authentication Over Unencrypted HTTP, HTTP Header Checks,
HTTP Header Injection Checks, HTTP Trace Probes, Insecure Cross-Domain Policy, In-
secure Script Include, Integer Overflow Injection Checks, Interesting Meta Tag Detection,
Internal IP Addresses, Local File Include Checks, Oracle Application Server Fingerprint
Module, Path Disclosure, Remote File Include Checks, RSS/Atom/OPL Feed Detector,
Shell Injection Checks, Social Security/Social Insurance Number Detector, Source Code
Disclosure Module, Unsafe Or Unrecognized Character Set, URL Injection Checks, Version
Control String Detection, WSDL Detector, XML Injection Checks, XSS Injection Checks,
X-Frame-Options Header Not Set
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 26
The summary result of using OWASP ZAP to discover the Moodle’s vulnerabilities is
presented in table 5.1.
Severity: Medium
Number of Affected URLs: 37
Definition by OWASP [37]: X-Frame-Options header is not included in the HTTP
response to protect against “ClickJacking” attacks.
Solution by OWASP [37]: Most web browsers in the present support the X-Frame-
Options HTTP header. The developer should ensure that it is set on all web pages returned
by the developer’s site. If the developer expects the page to be framed only by pages on
the developer’s server (e.g. it is part of a FRAMESET) then the developer needs to set the
header as SAMEORIGIN, otherwise if the developer never expects the page to be framed,
the developer should set DENY. ALLOW-FROM allows specific websites to frame the web
page in supported web browsers.
Comment: This alert is a ClickJacking vulnerability of the Moodle. The University’s web
developer is strongly recommended to configure the X-Frame-Options header field properly
in order to prevent the system from ClickJacking attacks. For example, X-Frame-Options:
deny or X-Frame-Options: sameorigin, depending on the Moodle’s source code.
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 27
Severity: Low
Number of Affected URLs: 6
Description by OWASP [37]: A cookie has been configured without the HttpOnly flag.
That is, the cookie can be accessed by JavaScript. If an attacker runs a malicious script on
this page, the cookie will be accessible and can be transmitted to another site. Similarly,
if it is a session cookie, session hijacking might be occurred.
Solution by OWASP [37]: The developer needs to ensure that the HttpOnly flag is set
for all cookies.
Comment: This alert is a vulnerability of the cookie in the Moodle page with low severity.
It leads to the accessibility of the cookie by JavaScript inside the application code. When
this vulnerability is combined with the “Cross-Domain JavaScript Source File Inclusion”
that allowed using external JavaScript running in the web page, an attacker might forge
the script and inject it into the web page, leading to leakage of sensitive cookies or session
hijacking.
Severity: Low
Number of Affected URLs: 2
Description by OWASP [37]: The pages of the affected URLs include one or more
script files from a third-party domain.
Solution by OWASP [37]: The developer needs to ensure that JavaScript source files
are loaded from only trusted sources, and the sources cannot be controlled by end users of
the application.
Comment: The JavaScript files inside the affected URL pages are from MathJax, which
is a website providing a high-quality display of mathematics notation JavaScript files for
all web browsers [26]. It is a trusted source for downloading JavaScript files. However,
the connection between the Moodle page and the MathJax is unencrypted (http://cdn.
mathjax.org/mathjax/latest/MathJax.js). It might be attacked by a hacker using man-
in-the-middle technique. Consequently, the hacker can modify the JavaScript file and inject
it into the Moodle page. Additionally, combined with the “Cookie Set without HttpOnly
Flag” vulnerability, the hacker could steal the cookie or hijack the session.
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 28
Severity: Low
Number of Affected URLs: 37
Description by OWASP [37]: Web Browser XSS Protection is not enabled or is disabled
by the configuration of the “X-XSS-Protection” HTTP response header on the web server.
Solution by OWASP [37]: The developer needs to ensure that the web browser’s XSS
filter is enabled, by setting the X-XSS-Protection HTTP response header to “1”.
Severity: Low
Number of Affected URLs: 35
Description by OWASP [37]: The “X-Content-Type-Options”, an Anti-MIME-Sniffing
header, was not set to “nosniff”. This allows older versions of Google Chrome and Internet
Explorer to perform MIME-sniffing on the response body, potentially causing the response
body to be interpreted and displayed as a content type other than the declared content
type.
Solution by OWASP [37]: The developer needs to ensure that the web application sets
the Content-Type header appropriately. That is, sets the X-Content-Type-Options header
to “nosniff” for all web pages.
Comment: This alert is also an additional configuration to raise the security level of
using web applications. The developer should set the Content-Type-Options header field
to “nosniff” so that the web application can be prevented from MIME-sniffing.
* See a full report of the result of using OWASP ZAP in Appendix C.1
The summary result of using Subgraph Vega to discover the Moodle’s vulnerabilities
is presented in table 5.2.
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 29
Severity: High
Number of Affected URLs: 1
Description by Vega [42]: A form with a password user-supplied input is submitted
over an insecure channel (HTTP). This vulnerability could cause unauthorized disclosure
of passwords to attackers.
Solution by Vega [42]: Passwords should never be sent in the cleartext across unen-
crypted channel. The form should submit to an HTTPS target.
Figure 5.2: Comparison between the web page and its source code
Severity: High
Number of Affected URLs: 26
Description by Vega [42]: The content on a web server is including JavaScript file from
an unrelated domain. When this script code is fetched by a user browser and loaded into
the DOM, it will have complete control over the DOM, bypassing the protection offered
by the same-origin policy. Even if the source of the script code is trusted by the website
operator, malicious code could be introduced if the server is ever compromised.
Solution by Vega [42]: It is strongly recommended that web servers should host their
own JavaScript locally, especially for critical applications.
Comment: This is the same vulnerability as “Cross-Domain JavaScript Source File In-
clusion” from the OWASP ZAP’s result. The external JavaScript file is from MathJax, a
trusted source.
Integer Overflow
Severity: High
Number of Affected URLs: 1
Description by Vega [42]: Integer overflow is a kind of buffer overflow which occur when
an integer data type exceeds its maximum value. When it occurs in programs written in
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 31
Comment: After investigating, there is no sign of a bad result presenting on the Moodle
page. Moodle still operates as expected. This alert is not counted as a vulnerability of the
Moodle service.
Severity: High
Number of Affected URLs: 2
Description by Vega [42]: A different response page fingerprint in relation to a local
file include injection request was detected. This means that the response page content
returned by the web application has a different signature from that returned by an ordi-
nary request, which may indicate the existence of a local file include vulnerability. Local
file includes vulnerabilities are present when externally-supplied input is used to specify
the location of a local filesystem resource that is requested by the web application. The
differing page fingerprint may include error messages or indicate a state change in the ap-
plication in response to the local file include injection attempt made by Vega. Differing
responses may also be indicative of a file enumeration vulnerability, which would allow an
attacker to determine if specific files exist on the system. Developers should examine the
response content and underlying code to verify whether or not a vulnerability is present.
If the vulnerability exists and precautions are not taken, such a vulnerability could allow
attackers to gain unauthorized access to sensitive information contained in local files, which
may also be leveraged in further attacks on the web application.
Solution by Vega [42]: To prevent this type of vulnerability, the developer should canon-
icalize the path of any filesystem resource that has a path composed of externally-supplied
input and then perform an authorization check prior to access. For example, the real-
path() library call will return the canonical path of the resource for PHP, Perl, and Python
programming.
Comment: After testing this vulnerability by sending many requests that made the Moo-
dle page returns its error pages, two different error messages were found as shown in figure
5.3. The messages generated depended on which type of the error the user made. Never-
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 32
theless, the error messages did not provide any sensitive information about the web server.
As a result, this is a false positive alert.
• If the user enters an ID inappropriately, the error page will display “Must specify
course id, short name or idnumber” message.
• If the user does not enter an existing ID, the error page will display “Cannot find
data record in database table course” message.
Severity: Medium
Number of Affected URLs: 4
Description by Vega [42]: A possible absolute filesystem path (i.e. one that is not
relative to the web root) was detected. This information is sensitive, as it may reveal things
about the server environment to an attacker. Knowing filesystem layout can increase the
chances of success for blind attacks.
Solution by Vega [42]: Full system paths are very often found in error output. This
output should never be sent to clients on production systems. It should be redirected
to another output channel (such as an error log) for analysis by developers and system
administrators.
Comment: The web server reveals filesystem paths in error responses by itself, for exam-
ple, /lib/ajax/setuserpref.php. This vulnerability may lead to exposure of sensitive infor-
mation such as the application’s environment and directories. An attacker can collect the
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 33
information and launch other attacks with a high success rate. The developer is recom-
mended to fix this vulnerability following the method Vega suggested
Severity: Low
Number of Affected URLs: 21
Description by Vega [42]: Listing directory contents when no index file is present in
a common misconfiguration. The directory contents can provide useful information to an
attacker, especially if there are files that are not meant to be accessible, such as source code
or backups. The directory listing may also provide useful information about the habits of
the server administration and/or web developers, such as file naming convention, that could
be used to increase the probable success of brute-force or other attacks.
Solution by Vega [42]: For Apache, add “IndexIgnore *” to the directory’s .htaccess
file, or alternatively remove “Indexes” from the line “Options All Indexes FollowSymLinks
MultiViews” in the Apache configuration file. For lighttpd, change “dir-listing.activate”
parameter from “enable” to “disable” in the lighttpd configuration file.
Comment: After checking the response source code thoroughly, the listing directory con-
tents that show sensitive information such as source code or backups were not found. This
alert is suspected as a false positive.
Severity: Low
Number of Affected URLs: 26
Description by Vega [42]: Patterns that resemble email addresses in scanned content
were found. These may be user the addresses of system users, addresses inserted in user-
supplied content, or third-party addresses embedded in components of the application (such
as JavaScript libraries). Automatically scraping websites is one way that spammers and
phishers collect email addresses for their distribution lists.
Solution by Vega [42]: It is recommended that email addresses not be displayed on
exposed parts of the web application, directly or indirectly.
Comment: The email addresses found on the Moodle page is e-learning@bath.ac.uk and
lecturers’ email addresses. These email addresses are needed to be display for being a
communication channel for students and staff. It is an unavoidable risk. The spam filter
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 34
Severity: Information
Number of Affected URLs: 1
Description by Vega [42]: Vega has detected that this cookie was set without the
HttpOnly flag. When this flag is not present, it is possible to access the cookie via client-
side script code.
Solution by Vega [42]: The HttpOnly flag is a security measure that can help mitigate
the risk of cross-site scripting attacks that target session cookies of the victim. If the
HttpOnly flag is set and the browser supports this feature, attacker-supplied script code
will not be able to access the cookie.
Comment: This is the same vulnerability as “Cookie Set without HttpOnly Flag” from
the OWASP ZAP’s result.
Severity: Information
Number of Affected URLs: 46
Description by Vega [42]: Vega has detected that the resource has not set the X-Frame-
Options HTTP response header. This header allows the resource to specify its policy with
regards to whether it may be included in frames in other domains as well as which domains
are allowed. When the header has been set, this may help to mitigate clickjacking attacks
against browsers that support this feature. If the header has not been set, the affected
resource may be used in clickjacking attacks.
Solution by Vega [42]: Set the X-Frame-Options header to DENY, SAMEORIGIN, or
ALLOW-FROM according to policy.
Comment: This is the same vulnerability as “X-Frame-Options Header Not Set” from
the OWASP ZAP’s result.
* See a full report of the result of using Subgraph Vega in Appendix C.2.
CHAPTER 5. THE UNIVERSITY’S SERVICE ASSESSMENT 35
5.3 Summary
Regardless of false positive vulnerabilities, OWASP ZAP and Subgraph Vega gave
quite similar results. For instance, the risk of using external JavaScript file and suggestions
about additional header field configurations. The results of the assessment show that the
Moodle e-learning system is programmed to tolerate web attacks quite well. That is, there
are no vulnerabilities with high severity able to harm the system except sensitive data
exposure from the enrolment key. In addition, any specific SQL injection vulnerability that
can compromise the Moodle service was not found from the assessment. As a result, there
is no need to design an approach to detect the SQL injection attack specifically for the
Moodle service. Although the result states that the SQL injection vulnerability was not
found, it does not mean the Moodle service does not have an SQL injection flaw. It might
not have been discovered yet. Besides, according to the concept of defense-in-depth [31],
the system should have multi-layered security mechanisms so that if an attack causes any
security mechanism to fail, other mechanisms can still provide the necessary mechanism to
protect the system. Hence, the Moodle service should have an additional security system
to prevent SQL injection attacks.
Due to no specific vulnerability about SQL injection, the security system designed in
this research will use an approach that can detect any SQL injection attack regardless of
its pattern, as well as suspicious HTTP traffic that may contain an SQL injection attack.
Another issue to point out is that even though the script from MathJax belongs to trusted
sources, the result shows that the Moodle page is allowed to use external JavaScript. The
security system should be carefully designed by considering this issue as well.
Chapter 6
Design
From literature reviews, the security system is decided to be deployed in front of a web
server instead of deploying between a web server and a database server. Its functionality
comprises of detecting and preventing HTTP traffic that is suspected as an SQL injection
attack. Reverse proxy deployment is selected as it provides many benefits including ease of
deployment and no application code modification required. Additionally, a web application
system that has both a web server and a database server on the same physical server can
take advantage of this type of deployment. The security system designed as a reverse proxy
with SQL injection prevention system will be called “Reverse Proxy for Preventing SQL
Injection” or “ReppSi”.
36
CHAPTER 6. DESIGN 37
users accessed, patterns, and length of the user-supplied inputs. After that, it creates pro-
files as a set of security rules to detect unauthorized (anomalous) web usage. This approach
can identify attacks that enter through the user-supplied input efficiently. In addition to
SQL injection attacks which are the main targets, cross-site scripting, OS command injec-
tion, and parameter tampering are also expected to be detected by the behaviour-based
detection. Nonetheless, a successful rate of detecting the attacks and false positive rate
depend on correctness and accuracy of the profiles.
To conclude, the ReppSi system will be developed using the behaviour-based detection
as an approach to detect and prevent suspicious user-supplied inputs that may contain SQL
injection attacks.
• The security system will be implemented as a reverse proxy that can intercept HTTP
traffic from users, and inspect the traffic for an SQL injection attack before redirecting
the traffic to the protected web server.
• Create a behaviour-based detection system for detecting SQL injection attacks hidden
inside HTTP traffic.
• The security system can block HTTP requests when necessary and return an appro-
priate error page.
To support cross-platform feature, the security system will be written using Java
programming
CHAPTER 6. DESIGN 38
The security system, ReppSi, is a reverse proxy designed to prevent SQL injection
attacks. That is, HTTP request traffic from a web client, instead of being sent directly to a
web server, will be redirected to the ReppSi system. Then, the system inspects the HTTP
traffic whether it is a legitimate HTTP request without any sign of an SQL injection attack
using the behaviour-based detection. After that, the HTTP request is forwarded to the
web server if it is legitimate. Otherwise, the ReppSi system drops the request and returns
an error page to the web client. Figure 6.1 illustrates an overview of the ReppSi system.
The deployment in the reverse proxy mode provides several benefits including:
• Ease of deployment: ReppSi can be installed in front of the web server without
disturbing the application system much.
• Application transparent: Reppsi can protect the web application without manip-
ulating the web content or disrupting the protected application.
ReppSi contains six modules, Listener, Sender, Session Manager, Suspicious Input
Detection Engine, Profile Database, and Logger. Figure 6.2 shows a block diagram that
presents the relationship among modules inside the ReppSi system.
6.3.1 Listener
Listener module is responsible for handling incoming HTTP requests from the web
client and incoming HTTP responses from the web server, and then forward them to the
Session Manager module.
Session Manager module collects and manages information about HTTP sessions.
It modifies the HTTP request/response message received from the Listener module by
replacing the source/destination IP with an appropriate IP for redirecting the message to
the target destination (the web client or the web server).
CHAPTER 6. DESIGN 40
Suspicious Input Detection Engine (SIDE) is the main module of the ReppSi sys-
tem responsible for HTTP traffic inspection. It extracts necessary information from the
HTTP request message such as URL, method, header fields, and parameter values for some
purposes.
• In the learning phase, SIDE logs the information into the Profile Database module.
The information will be used to create profiles which will become security rules for
detecting suspicious user-supplied input later.
• In the protection phase, SIDE checks the information whether there is a suspicious
user-supplied input hidden inside the request by comparing to the security rules
(profiles) from the Profile Database module. If the suspicious input is detected, the
request will be suspected as an SQL injection attack. The result of the inspection is
sent to the Logger module and the Session Manager module.
Profile Database module is an SQL database that contains many database tables.
Each protected web server possesses two unique tables, a log table and a profile table.
• A log table collects legitimate HTTP request information such as URLs, methods,
and parameters from the Suspicious Input Detection Engine. This information will
be used to create/update the profile table.
• A profile table collects conditions digested from the log table for each URL and
parameter. The HTTP request that matches the conditions will be counted as a
legitimate request. Otherwise, it will be suspected as an SQL injection attack.
CHAPTER 6. DESIGN 41
6.3.5 Logger
The primary function of the Logger module is to collect information of the inspection
from the Suspicious Input Detection Engine. The information consists of a timestamp, the
original HTTP request, and the result of the inspection. A security administrator can use
the Logger module to track the history of the HTTP requests in order to analyze a trend
of SQL injection attacks or create an SQL injection report.
6.3.6 Sender
Sender module is responsible for handling the HTTP request/response including the
error page received from the Session Manager module. It creates a connection and forwards
the request/response to the destination.
1. When ReppSi starts the operation, the security administrator must enter a hostname
or an IP address of the protected web server and the operation mode (Profiling or
Protection) via the Java console.
2. If the operation mode is “Profiling”, SIDE checks whether the log table of the pro-
tected web server exists. If not, SIDE creates a log table for the protected web server.
If the operation mode is “Protection”, ignore this step.
3. SIDE creates a profile table for the protected web server if it does not exist. Then,
SIDE updates the profile table according to the information in the log table.
CHAPTER 6. DESIGN 42
4. The Logger module prepares a log file for logging the system events and the alerts
generated by SIDE.
5. SIDE sends a message which contains information about the protected web server,
the operation mode, and the database status to the Logger module.
6. The Logger module writes the information on the log file. This information is also
displayed on the console.
2. The Listener module receives the request, and then forward to the Session Manager
module.
3. The Session Manager saves the request along with the session information.
4. The Session Manager modifies the request’s headers by replacing the source IP with
the ReppSi IP and the destination IP with the web server IP before forwarding to
the Sender module.
5. The Sender module forwards the modified request to the protected web server.
6. The web server processes the request and returns an HTTP response to the ReppSi.
7. The Listener module receives the response, and then forward to the Session Manager
module.
8. The Session Manager module checks the status code. If it is success 2xx or redirection
3xx, the Session Manager finds the response’s request from its session information,
and then sends it to the SIDE for logging. Otherwise, go to step 9.
9. The SIDE extracts necessary information from the request message such as, header
fields, URL, method, parameter values, etc., and then inserts the information into
the protected web server’s log table via the Database module.
10. The Session Manager modifies the response’s headers by replacing the source IP with
the ReppSi IP and the destination IP with the web client IP before forwarding to the
Sender module.
11. The Sender module forwards the modified request to the web client.
Figure 6.4 shows the process of the learning phase for any HTTP request sent to the
protected web server.
CHAPTER 6. DESIGN 44
When the learning phase finishes, stopping and restarting the ReppSi system are
required in order to create/update the profiles (see details in 6.4.1 Database and Proxy
Preparation). The security administrator can change the operation mode to “Protection”
as well.
CHAPTER 6. DESIGN 45
2. The Listener module receives the request, and then forward to the Session Manager
module.
3. The Session Manager forwards the request to SIDE for checking the suspicious user-
supplied input.
4. SIDE extracts necessary information from the request message such as header fields,
URL, method, parameter values, etc. and then selects a profile according to the
request information from the Profile Database module.
(a) If the request information complies with the profile, SIDE informs the Session
Manager that the request is legitimate.
(b) Otherwise, SIDE informs the Session Manager that the request is suspicious and
may contain an SQL injection attack. The information about the request and
the reason why it is illegitimate is sent to the Logger module.
(a) If legitimate, the Session Manager modifies the request’s headers by replacing
the source IP with the ReppSi IP and the destination IP with the web server IP
before forwarding to the Sender module.
(b) If illegitimate, the Session Manager creates an error page, and then forwards to
the Sender module. Meanwhile, the Logger module writes the alert information
on the log file. This information is also displayed on the console.
7. The Sender module forwards the modified request to the protected web server or
returns the error page to the web client.
Figure 6.5 presents the process of the protection phase for any HTTP request sent to
the protected web server. For any HTTP response returned from the web server, ReppSi
just forwards it to the web client.
CHAPTER 6. DESIGN 46
A database system inside ReppSi is a part of the Profile Database module. HTTP
request logs and profiles of each protected web server are collected individually. That is,
one web server has its own log table and profile table. The web server is defined by a
domain name or an IP address such as example.com or 172.16.1.250.
CHAPTER 6. DESIGN 47
A log table for the protected web server is created when ReppSi start its operation if it
does not exist. The log table name will be in the format of PROTECTED WEB SERVER
NAME-log, such as example.com-log. In the learning phase (profiling mode), this table
collects traffic logs from legitimate HTTP requests including request number, URL, method,
parameter name, parameter value, parameter type, and parameter length as presented in
table 6.1.
The records in the log table will be used to create or update the protected web server’s
profile.
Similar to the log table, a profile table is updated when the ReppSi starts its operation
or created if it does not exist. The table name is in the format of PROTECTED WEB
SERVER NAME-profile, such as example.com-profile. This table collects data that is di-
gested from the data in the log table for each URL and parameter. The data consists of
CHAPTER 6. DESIGN 48
URL, method, parameter name, parameter type, maximum/minimum length of the pa-
rameter value, and special characters that are allowed for the parameter value as shown in
table 6.2. This data will be used for condition matching in the protection phase (protection
mode).
In the protection phase, when ReppSi intercepts the HTTP request from the web
client, the request information is forwarded to the Suspicious Input Detection Engine where
the condition matching is processed. If the request information complies with the conditions
(data) in the profile table, the request will be regarded as a legitimate HTTP request.
Otherwise, it will be suspected as an SQL injection attack.
ReppSi contains the Logger module responsible for collecting and displaying system
event logs and alert logs. All logs will be displayed on the console and written on the text
file so that a security administrator can use the log file to track the history of the SQL
injection attacks detected by the ReppSi system or create an SQL injection report. The
logs are collected in the pattern showing in the next page.
CHAPTER 6. DESIGN 49
As illustrated in figure 6.6, an error page is generated by the Session Manager when
a suspicious request that may contain an SQL injection attack is detected, and the Session
Manager drops the HTTP request. This feature helps the developer to conceal sensitive
server information from an error message generated by the web server. Furthermore, it
helps the security administrator to prevent Blind SQL injection attacks.
In the protection phase, all HTTP requests intercepted by ReppSi are compared to
the profiles in the database. If ReppSi cannot find appropriate profiles, it will block the
requests and return an error page to the web clients. In the case that the dropped request
is a legitimate request without any sign of an SQL injection attack, it will be a false
positive. This is mostly because of the incompleteness of the profiles. The root causes of
the incompleteness is that the number of the requests collected in the learning phase might
be not enough to cover all patterns of the legitimate requests. In order to reduce the false
positive rate, ReppSi will permit the security administrator or the developer to update
or modify the profile database. It is strongly recommended that they review the profiles
before running ReppSi in the protection mode. A log file is a useful tool for reviewing and
adapting the profile database.
On the other hand, if the requests collected in the learning phase contain illegitimate
requests or requests that have malicious code inside, they might cause false negatives.
Review and discussion of the profiles between the security administrator and the web
developer help to minimize the false negative rate. In the case that the profile record led to
the false negative cannot be modified, the security administrator is recommended to apply
other security mechanisms according to the defense-in-depth concept or takes the risk of
the vulnerability.
Chapter 7
Implementation
This chapter will begin with describing necessary equipment and tools used to imple-
ment each module in the security proxy, ReppSi. Then, it presents how each module works
and is implemented in details. Tables, diagrams, and pseudo code will be shown to make
the content easy for understanding.
There are four main tools required for implementing the ReppSi system.
Java is one of the most famous programming languages commonly used in the world
today. It is cross-platform, meaning that it can run on major operating systems such
as Windows, Mac OS X, and Linux if they have Java virtual machine (JVM) installed.
Additionally, there are many online resources and documents that support the programmer
to write Java code efficiently [18].
51
CHAPTER 7. IMPLEMENTATION 52
of messages in order to add functionality or change the behavior. The interceptor can be
built to read the content of a request/response message and its protocol information such
as HTTP header fields. It also can modify a message, for instance, changing the destination
of a message. Moreover, it can stop the message processing and create its own message to
be forwarded to the destination [39].
Therefore, implementing ReppSi using the Membrane framework will provide HTTP
traffic interception and redirection features which cover the operations of three ReppSi’s
modules including Sender, Listener, and Session Manager. The framework version used in
this research is the latest version 4.0.
ReppSi requires a database system to collect logs and profiles of the protected web
servers. MySQL database management system is selected to be implemented in the ReppSi
system as it is open source software with high performance. In this research, MAMP 3.0
is installed on the laptop running ReppSi since it is a software package containing MySQL
and phpMyAdmin, a free software tool for handling the administration of MySQL over the
web.
ReppSi is pure Java-based reverse proxy software that can run on most operating
systems. In this research, ReppSi is implemented on the MacBook Air with Mac OS X
Yosemite 10.10. Figure 7.1 shows a comparison between the modules in the ReppSi system
and the tools for implementation.
CHAPTER 7. IMPLEMENTATION 53
Figure 7.1: A comparison between the modules in ReppSi and the tools for implementation
Listener, Sender, and Session Manager are implemented using a framework of Mem-
brane Service Proxy. To intercept the HTTP traffic, the framework require an IP address/a
domain name and a port of the destination server (the protected web server), as well as a
listen port of the host (ReppSi). When web clients call the host with the listen port, all
HTTP traffic sent to the host will be intercepted. The host running the Membrane Service
Proxy can make a decision to forward or reject the traffic. If the host forwards the traffic,
it will be redirected to the destination server. An example of using the Membrane Service
Proxy is shown in figure 7.2.
All HTTP requests sent to 172.16.1.100:80 will be intercepted by the host. Then, the
host can apply some policies such as suspicious input detection to the requests. After that,
the host can decide to drop or redirect the requests to www.example.com:80.
CHAPTER 7. IMPLEMENTATION 54
In the real world implementation, the DNS configuration must be modified to make
the destination server transparent from the web clients. It must resolve the hostname
“www.example.com” to “172.16.1.100” instead of its original IP address “172.16.1.250”.
As a result, whenever the web clients call www.example.com, the HTTP requests are sent
to the proxy.
Listener, Sender, and Session Manager combine to be a reverse proxy module. The
proxy module is a core program of the ReppSi system for intercepting the HTTP request
so that ReppSi can use the Suspicious Input Detection Engine to inspect the request for
a suspicious user-supplied input that may contain an SQL injection attack. According
to 6.4.1 Database and Proxy Preparation, the Suspicious Input Detection Engine (SIDE)
is responsible for handling the database preparation. Therefore, when ReppSi starts the
operation, the proxy module requests the SIDE to prepare the database. The pseudo code
of preparing the reverse proxy is shown in the next page.
CHAPTER 7. IMPLEMENTATION 55
According to the pseudo code, the Membrane Service Proxy supports multiple inter-
ceptors at the same time. However, ReppSi requires only one interceptor for detecting SQL
injection attacks, called TrafficInterceptor. The TrafficInterceptor has two responsibilities,
HTTP request handling and HTTP response handling, which will be mentioned in the next
section. After finishing the preparation, the proxy module writes information about the
database and the proxy status on the log file.
• In the protection phase, the TrafficInterceptor will send the incoming request to the
SIDE for checking SQL injection attacks. If the SIDE replies that the request is
suspected as an SQL injection attack, the TrafficInterceptor drops the request and
returns an error page to the web client. Otherwise, it forwards the request to the
destination server.
• In the learning phase, the TrafficInterceptor always forwards the request to the des-
tination server.
Additionally, only the request targeting a dynamic web page (The page that contains
server-side code such as PHP, ASP, and JSP) will be inspected since it can compromise
the database by performing an SQL injection attack. The request targeting a static web
CHAPTER 7. IMPLEMENTATION 56
page can pass through the proxy without being inspected. This condition helps the proxy
to reduce the processing time of the static request.
• In the protection phase, the TrafficInterceptor checks the status code of the response
message. If it is an error 4xx or 5xx, the TrafficInterceptor will replace the response
message with its own error page in order to conceal the error message that might
display sensitive server information to the user.
• In the learning phase, the TrafficInterceptor will forward the response’s request to
the SIDE for logging if it is a good request. In other words, the response’s status
code is 2xx or 3xx and the request was sent to the dynamic web page.
CHAPTER 7. IMPLEMENTATION 57
Suspicious Input Detection Engine (SIDE) is a core module for detecting a suspicious
user-supplied input that might contain an SQL injection attack. It applies the behavior-
based detection to create a profile as a set of security rules for identifying anomalous input
hidden inside HTTP requests. From the design, SIDE has three main functions including
database preparation, request logging and profile updating, and suspicious input detection.
Database preparation is performed by SIDE when ReppSi starts its operation. The
main tasks are to prepare the MySQL database for logging and profile updating. From the
design in 6.4.1 Database and Proxy Preparation, the pseudo code is presented in the next
page.
CHAPTER 7. IMPLEMENTATION 58
Request logging is a process of extracting the request information from HTTP requests
and inserting it into the log table. However, not all HTTP requests will be collected in the
database. Only the requests that target dynamic web pages are selected as these requests
are usually sent to process in the web server. The processing often requires a database
connection. Consequently, an attacker can hide SQL injection attacks inside those requests
to query the database without permission. On the other hand, the requests targeting
static web pages will fetch only static content from the web server without connecting to
the database. Therefore, ReppSi does not need the profile for the HTML pages since an
attacker cannot perform SQL injection attacks on these pages. This condition will decrease
the database size and reduce the processing time of the profile updating.
Furthermore, ReppSi should filter out bad HTTP requests before inserting to the
database. The bad requests are HTTP requests that return the responses with a status
code of 4xx or 5xx. These requests do not need to collect as they generate errors. Only the
HTTP requests that return the responses with a status code of success 2xx or redirection
3xx will be appropriate for creating/updating the profiles.
The request information extracted from the HTTP request that passes all conditions
mentioned before consists of URL, method, parameter names, and parameter values. After
CHAPTER 7. IMPLEMENTATION 59
extracting, each parameter value is processed to find the parameter type which is classified
in eight types, including “Blank”, “Latin Characters”, “Numeric”, “Special Characters”,
“Latin Characters & Numeric”, “Latin & Special Characters”, “Numeric & Special Charac-
ters”, and “All”. Concurrently, the length of the parameter value is also calculated. After
that, the request information along with the parameter type and the parameter length are
inserted into the log table.
Extracted information:
URL: /login.php
Method: GET
Parameter #1 (Name, Value, Type, Length): username, suthee, Latin Characters, 6
Parameter #2 (Name, Value, Type, Length): password, pass123!, All, 8
Parameter #3 (Name, Value, Type, Length): code, 2245, Numeric, 4
Database Table:
www.example.com-log
CHAPTER 7. IMPLEMENTATION 60
After the database has collected a number of requests, profile updating can be per-
formed by restarting the ReppSi system as mentioned in 6.4.2 Learning Phase. All records
in the log table that the value in the column “isCheck” is “False” will be selected to update
the profile table. The updating process in details is shown in figure 7.3.
CHAPTER 7. IMPLEMENTATION 61
Example profile table after digesting the data in the log table:
Allowed
Other
URL GET POST Name Type Max Min Special
Methods
Characters
/login.php True False False username Latin 7 5
Characters
& Numeric
/login.php True False False password All 8 6 !@
/login.php True False False code Numeric 4 4
/main.php True False False NULL NULL NULL NULL NULL
CHAPTER 7. IMPLEMENTATION 64
After the profile of the protected web server is ready, in the protection phase, the
profile is used as a set of rules to detect a suspicious input hidden inside the HTTP request
by performing condition matching. That is, the Suspicious Input Detection Engine extracts
necessary information from the HTTP request sent by the web client and compared to the
information in the profile table. If they match, the request will be a legitimate request and
forwarded to the web server. Otherwise, the request will be suspected as an SQL injection
attack and dropped. An alert is generated as well as written on the log file. There are six
categories of the alert including:
• Unauthorized URL Access: The request is sent to the URL that is not found in
the profile.
• Unauthorized Method for Known URL: The method of the request URL does
not match that in the profile.
• Parameter Type Violation: The type of the parameter in the request is different
from that in the profile.
• Parameter Value Length Violation: The length of the parameter in the request
is greater or less than that in the profile.
• Unknown Parameter: The request contains a parameter that is not found in the
profile.
The process of the suspicious input detection in details is presented in figure 7.4 and 7.5.
CHAPTER 7. IMPLEMENTATION 65
This pseudo code will return true of false to the method handleRequest in the TrafficIn-
terceptor class. If it returns true, the TrafficInterceptor will drop the request and return
an error page to the web client. Otherwise, it forwards the request to the destination web
server.
Extracted information:
URL: /login.php
Method: GET
Parameter #1 (Name, Value, Type, Length): username, admin, Latin characters, 5
Parameter #2 (Name, Value, Type, Length): password, ’ OR ‘1’=‘1, All, 11
Parameter #3 (Name, Value, Type, Length): code, a44a, Latin Characters & Numeric,
4
Profile Table:
Allowed
Other
URL GET POST Name Type Max Min Special
Methods
Characters
/login.php True False False username Latin 7 5
Characters
& Numeric
/login.php True False False password All 8 6 !@
/login.php True False False code Numeric 4 4
/main.php True False False NULL NULL NULL NULL NULL
• Parameter Type Violation: The parameter type of “code” is different from that
in the profile.
and 7.7 . Suspicious Input Detection Engine can connect to the tables and read/write the
data using SQL commands.
For security administrators, they can use the phpMyAdmin web application to view
and manage profiles in the database directly. For example, as displayed in figure 7.8, they
could select menu “SQL” to run SQL commands for inserting, updating, or deleting profile
records if they caused false positives. In addition, menu “Export” is allowed for exporting
the profile table in CSV or PDF format so that the security administrator can show it to
the web developer and check the correctness of the profiles. This feature helps the security
administrator to reduce the false positive rate of the proxy.
CHAPTER 7. IMPLEMENTATION 70
Logger module is responsible for displaying system events and alerts on the Java con-
sole, as well as writing them on the log file. This module is implemented using the Logging
API in Java programs [33]. By importing java.util.logging package, the Logger module
is ready to use. Besides, the default log pattern displayed on the log file is customized as
mentioned in 6.6 Logging system, so that everyone can easily understand. Examples of
system event logs and an alert log written on the log file are presented in figure 7.9.
Figure 7.9: An example of the system event logs and the alert logs
CHAPTER 7. IMPLEMENTATION 71
This section will describe all classes and methods that were implemented following the
section 7.1 - 7.5. The ReppSi system consists of four main modules, Reverse Proxy (Lis-
tener, Sender, and Session Manager), Suspicious Input Detection Engine, Profile Database,
and Logger. These modules transform into five Java classes as presented in table 7.1.
Package ReppSi
Class: ReverseProxy - Implements Listener, Sender, and Session Manager using the
framework of the Membrane Service Proxy. It is a class for starting the ReppSi’s op-
eration. This class is written by following the pseudo code 1: Proxy Preparation.
There is no method for this class.
Class: TrafficeInterceptor - Implements the Session Manager module using the frame-
work of the Membrane Service Proxy. It is responsible for intercepting the HTTP traffic,
and applying some rules to forward or reject the traffic.
Method Description
Handle the incoming request, and then return
the flow of the request. If it returns “Out-
handleRequest(exchange): Outcome
come.CONTINUE”, the request is forwards to
the destination server. If it returns “Out-
* The exchange parameter
come.RETURN”, it drops the request and starts
collects the information of the
the response process. This method is written by
HTTP request/response pair.
following the pseudo code: 2 HTTP Request
Handling.
Handle the response, and then return the
flow of the response. If it returns “Out-
handleResponse(exchange): come.CONTINUE”, the response is forwards to
Outcome the web client. This method is written by fol-
lowing the pseudo code: 3 HTTP Response
Handling.
isSupportFileType(request): Return true if the request is being sent to the
Boolean dynamic web page. Otherwise, return false.
createErrorResponse(exchange): Generate an error message for returning to the
Void web client.
CHAPTER 7. IMPLEMENTATION 72
getAllRequestHeaderFields(request):
Return all header fields of the request.
HeaderField[]
Return the body message of the request. Most of
getRequestBody(request): String
them are parameters of the POST request.
getParameters(request): Return parameter pairs (Name, Value) of the re-
Map<String, String> quest.
getSpecialCharacterInValue(value): Return a list of all special characters in the pa-
String rameter value.
getRequestInformation(request): Return all information of the request. It will be
String used for logging.
Class: TxtLogger - Implements the Logger module. It is a class for displaying system
event messages and alerts on the Java console, as well as writing them on the log file.
Method Description
Display the input message with the severity on
printLog(severity, message): void
the Java console, and write it on the log file
Class: TxtLogFormatter - A part of the Logger module responsible for formatting the
log messages.
* See the installation guide and the user manual of the ReppSi program in Appendix A
and B
Chapter 8
Experiments
To prove the concept of ReppSi and its behaviour-based detection system, they are
planned to test with the Moodle, the University e-Learning system. Unfortunately, due to
the limitation of the Moodle environment, the ReppSi system could not redirect the HTTP
traffic sent to the Moodle web application without disturbing the system. In addition,
testing the ReppSi system in the real environment may cause problems to the students
and the staff. Hence, the proof of the concept will be conducted with the Super Veda web
application.
Super Veda is a demo online shopping application written by Imperva. Users can
perform online purchases of various kinds of products such as books, DVDs, electronic
goods, and so on. The application was developed using JSP and designed to run on
an Apache Tomcat 6.0.18 web service. The data is stored on a MySQL 5.1.39 database
system. This application is vulnerable to many types of web application attacks. It is used
for checking various hacking techniques and web security vulnerabilities exploitation [15].
Experiments in this chapter are divided into three tests, a protection test, a perfor-
mance test, and a false positive test.
The main objective of the protection test is to measure the ReppSi’s capability of
protecting the web server from SQL injection attacks. The test is divided into two phases,
a learning phase, and a protection phase. In the learning phase, all HTTP requests sent
to the web application will be collected to create a profile. All requests are assumed to be
74
CHAPTER 8. EXPERIMENTS 75
legitimate request without any attack hidden inside. In the protection phase, two different
web vulnerability scanning tools are used to penetrate the ReppSi system. The result will
be compared to that from the environment without the ReppSi system deployed.
The network diagram of the protection test is illustrated in figure 8.1. The ReppSi
proxy and the Super Veda web application are running on the same machine, the MacBook
Air with Mac OS X 10.10 Yosemite, under the virtual environment. Both of them are
connected with the virtual switch and connect wirelessly to the web clients. The web
clients can access the Super Veda application by calling http://172.16.1.100:8100/, which
is the hostname of the ReppSi proxy. Then, the ReppSi proxy redirects all HTTP requests
to the Super Veda application, whose hostname is 172.16.1.101.
ReppSi requires profiles for being used as security rules when inspecting HTTP re-
quests. The profiles can be built from the HTTP requests in the learning phase. The
ReppSi’s operation mode must be set to “Profiling” by selecting mode number “0” on the
ReppSi’s java console to start collecting the information from the HTTP requests. An
example of logging the requests is shown in the next page.
CHAPTER 8. EXPERIMENTS 76
Example requests:
http://172.16.1.100:8100/login.php?username=sutheekit&password=kitcha&code=8989
http://172.16.1.100:8100/login.php?username=suthee&password=nF0rc3!&code=8989
http://172.16.1.100:8100/login.php?username=suthee22&password=1q2w3e4r&code=7550
http://172.16.1.100:8100/login.php?username=thee&password=1234567&code=2222
http://172.16.1.100:8100/login.php?username=sut224&password=1q2w3e4r$R&code=1234
Figure 8.2: An example of the log table after logging HTTP requests
Figure 8.3: An example of the profile table that digested the data from the log table
In this test, 672 HTTP requests from five web clients were collected into the database.
After logging enough information, ReppSi was restarted in order to create and update the
profile table from the data in the log table. Additionally, its operation mode was changed
to “Protection” by selecting mode number “1” on the java console. Now, the ReppSi is
in the protection mode and ready to test. A full detail of the profile table is presented in
Appendix C.3.
CHAPTER 8. EXPERIMENTS 77
Two web vulnerability scanning tools, OWASP ZAP and Subgraph Vega, are used to
test the ReppSi system. Similar to scanning the Moodle system in Chapter 5, both of them
are up-to-date software at the testing time (ZAP version 2.3.1 and Vega version 1.0). Each
scanning tool is configured to scan all web vulnerabilities in its list.
Before testing with the vulnerability scanners, a few SQL injection attacks were tested
in order to check whether the ReppSi system is operating properly. One of them is a classic
SQL injection attack for unauthorized access to accounts. In the /login.jsp page, there are
two user-supplied inputs for entering the user’s username and password. As presented in
figure 8.4, bypassing the authentication was tested by inputting “mickey” as a username
and “’1 OR ‘1’=‘1” as a password.
The attack was successful. An attack could log in as “Mickey” without the knowledge
of the password. The result is shown in figure 8.5.
CHAPTER 8. EXPERIMENTS 78
Figure 8.5: The result of bypassing the authentication system using SQL injection
After deploying the ReppSi proxy, this attack was blocked due to the special character
of the password parameter did not match that in the profile. The error page was returned
to the web client as displayed in figure 8.6. Moreover, an alert was generated and written
on the log file as shown in figure 8.7.
Figure 8.7: The alert from the log file (See more details of the log file in Appendix C.4)
OWASP ZAP
The summary results of using OWASP ZAP to scan the Super Veda application before
and after implementing the ReppSi proxy are presented in table 8.1 and 8.2 respectively.
Table 8.1: The result of scanning Super Veda by OWASP ZAP before ReppSi deployment
Alert Severity Number of Affected URLs
Cross-Site Scripting (Persistent) High 2
Cross-Site Scripting (Reflected) High 4
Remote OS Command Injection High 1
SQL Injection - Authentication Bypass High 2
SQL Injection - MySQL High 23
Application Error Disclosure Medium 1
X-Frame-Options Header Not Set Medium 58
Cookie Set without HttpOnly Flag Low 14
Password Autocomplete in browser Low 2
Private IP Disclosure Low 1
Web Browser XSS Protection Not Enabled Low 58
X-Content-Type-Options Header Missing Low 58
Table 8.2: The result of scanning Super Veda by OWASP ZAP after ReppSi deployment
Alert Severity Number of Affected URLs
SQL Injection High 2
X-Frame-Options Header Not Set Medium 58
Cookie Set without HttpOnly Flag Low 14
Password Autocomplete in browser Low 2
Web Browser XSS Protection Not Enabled Low 58
X-Content-Type-Options Header Missing Low 58
The results show obviously that ReppSi could reduce the number of the SQL injection
attacks from 25 to 2, which is 92 percent blocking rate. That means the information in
the profiles were noticeably different from the patterns of the SQL injection attacks. Only
the SQL injection attacks targeting the /dosearch.jsp page and /register.jsp page could
pass through the ReppSi’s Suspicious Input Detection Engine. However, the log file shows
that the ReppSi system could detect the attacks as presented in figure 8.8 and 8.14. After
rechecking those two SQL injection attacks by penetrating the web application again, it is
found that the ReppSi system could block both attacks. Therefore, it could not summarize
that the ReppSi system was capable of detecting and blocking the SQL injection attacks
only 92 percent.
CHAPTER 8. EXPERIMENTS 81
Figure 8.8: A comparison between the OWASP ZAP’s log and the ReppSi’s log for
/dosearch.jsp
Figure 8.9: A comparison between the OWASP ZAP’s log and the ReppSi’s log for /regis-
ter.jsp
CHAPTER 8. EXPERIMENTS 82
To find the cause why the log file indicates that the ReppSi system could block the
attacks but the result of the OWASP ZAP, in contrast, shows that the attacks could pass
through the ReppSi, the program and the log file were analyzed. After an investigation,
some records in the log file were discovered that there were many SQL exceptions generated
during the test. All exceptions were created by the suspicious input detection part of the
source code as illustrated in figure 8.10.
Figure 8.10: A comparison between the SQL exception and the source code
As displayed in figure 8.10, the SQL exception states that the operation of the source
code line number 459 was not allowed because the resultSet had closed. However, it is
impossible for the resultSet to close at that line since it was just assigned the values from
selecting the profile records from the database at the line number 457. When considering
the fact that the ReppSi proxy actually could block the pass-through attacks, it is deduced
that the concept of ReppSi with the behaviour-based detection can block all types of
SQL injection attacks generated by the OWASP ZAP. Nonetheless, the incompleteness
CHAPTER 8. EXPERIMENTS 83
of the program causes the SQL exceptions, leading to the incapability of detecting or
blocking some attacks. As a result, the attacks could pass through the ReppSi system and
compromised the protected web server.
The root cause of the SQL exceptions is assumed that the SuspiciousInputDetectio-
nEngine class for detecting the SQL injection attacks does not support multi-threading.
Even though the Membrane Service Proxy supports multi-threading, the whole program
shares the same database connection pool. When the program handles the request gen-
erated more than 200 requests per second by the OWASP ZAP, it might cause errors.
According to several tests, the numbers of the SQL exceptions were varied. They were
in the range of 213 - 256 from 3723 - 3789 of all requests, while the pass-through SQL
injection attacks were around 2 - 4 as shown in table 8.3.
* The log files from these tests also show that all pass-through attacks were detected by
the ReppSi system.
Table 8.3: The number of the OWASP ZAP requests, the SQL exceptions generated, and
the SQL injection attacks that pass through the ReppSi system
Number of SQL Number of Pass-through
Test # Number of Attacks
Exceptions SQL Injection Attacks
1 3775 256 (6.78%) 3
2 3723 239 (6.42%) 2
3 3757 213 (5.67%) 2
4 3789 241 (6.36%) 4
5 3761 219 (5.82%) 2
In addition to the SQL injection attacks, the ReppSi could detect and prevent other
kinds of web vulnerabilities such as Cross-Site Scripting and Remote OS Command Injec-
tion. These vulnerabilities, like SQL injection, are required some special characters e.g.
“<”, “>”, “;” to launch the attacks. Therefore, if the user-supplied input does not support
these characters, in other words, does not match the profile, the attacks will be blocked
automatically.
Another useful feature that raises the security level of the web server is the ReppSi’s
error page. The error page will be returned to the web client if the suspicious request is de-
tected. Additionally, if the status code of the response is an error 4xx or 5xx, the response
will be replaced by the error page in order to conceal the sensitive server information. As
displayed in table 8.2, after using the ReppSi system, the Application Error Disclosure alert
CHAPTER 8. EXPERIMENTS 84
is disappeared.
Subgraph Vega
The summary results of using Subgraph Vega to scan the Super Veda application are
presented in table 8.4 and 8.5.
Table 8.4: The summary result of scanning Super Veda using Subgraph Vega before ReppSi
deployment
Alert Severity Number of Affected URLs
Cleartext Password over HTTP High 2
Session Cookie Without Secure Flag High 1
Session Cookie Without HttpOnly Flag High 1
Cross-Site Scripting High 2
MySQL Error Detected High 8
SQL Injection High 9
Page Fingerprint Differential Detected High 5
Java Debug Output Detected Medium 10
Possible XMP Injection Medium 1
Form Password Field with Autocomplete
Low 2
Enabled
Cookie HttpOnly Flag Not Set Info 1
Character Set Not Specified Info 5
Blank Body Detected Info 1
Table 8.5: The summary result of scanning Super Veda using Subgraph Vega after ReppSi
deployment
Alert Severity Number of Affected URLs
Cleartext Password over HTTP High 2
Session Cookie Without Secure Flag High 1
Session Cookie Without HttpOnly Flag High 1
Form Password Field with Autocomplete
Low 2
Enabled
Character Set Not Specified Info 5
The results present that the ReppSi system could prevent all SQL injection attacks
generate by Subgraph Vega. Different from OWASP ZAP, there was not any SQL exception
generated by the program while scanning since Subgraph Vega launched the attacks only
around 4 - 5 requests per second. Hence, the database connection pool could manage its
resources properly.
Like the OWASP ZAP’s result, ReppSi could eliminate other kinds of attacks such as
Cross-Site Scripting and Possible XML Injection, and help the protected web server from
the leakage of sensitive server information. As shown in the table 8.4.and 8.5., ReppSi
also patched the Page Fingerprint Differential Detected and Java Debug Output Detected
vulnerabilities by its error page feature.
The objective of the performance test is to check the impact on the system environment
when implementing the ReppSi proxy. The impact can be determined by the process time
of the ReppSi system including the process time of the request and the process time of the
response. Both the process times will be compared between four cases.
1. No ReppSi. HTTP traffic is directly transmitted between the web client and the web
server.
2. Only Membrane Service Proxy with default configuration running as a reverse proxy
(The ReppSi without Suspicious Input Detection Engine)
The first case is a baseline case. The second one is to check the impact of the pure
Membrane Service Proxy. The third one is to check the impact of the ReppSi system when
logging the HTTP requests into the database. And the last one is to check the impact
when inspecting the HTTP requests for suspicious inputs. Each case will collect two sets
of data, the process time of the request and the process time of the response, from more
than 500 HTTP requests/responses. Each of them will include the maximum process time,
the minimum process time, and the average process time. An average response time (start
when the HTTP request is sent from the web client and finish when the client receives the
response) is also collected to see the overall impact of the ReppSi system.
The performance test has the same setup as the protection test.
As presented in table 8.6, case #4 has the highest average process time of the request
(3.82 ms). It is because all HTTP requests in case #4 must have been compared to the
profiles selected from the database. The bigger the profile table was, the longer time the
process spent. On the other hand, case #3 has the highest average process time of the
response (1.72 ms). When ReppSi handled the HTTP responses in the learning phase, most
of the HTTP requests were inserted into the database in order to create the comprehensive
profiles. Connecting to the database led to the delay in the process. For the average process
time of the request in case #3 (1.89 ms) and the average process time of the response in case
CHAPTER 8. EXPERIMENTS 87
#4 (0.36 ms), they are not quite different from case #2 (1.67 ms and 0.2 ms respectively).
Both of them are a little bit higher since the ReppSi system needed to check some conditions
before forwarding the traffic to the destination as shown on the source code in figure 8.11.
The average process time of the request in the protection phase (3.82 ms) and the
average process time of the response in the learning phase (1.72 ms) are significantly higher
than those of the pure reverse proxy without the suspicious input detection system (1.67
ms and 0.2 ms respectively). However, when comparing all average response time of the
four cases, the maximum difference of the average response time of case #1 and case #4
is only 4.48 milliseconds that are very short. More importantly, in the real world, most
web clients connect to the web application via the Internet. The average response time
over the Internet is mostly in seconds. As displayed in figure 8.12, an example of browsing
the Moodle e-learning system from London shows that the response time is 1.279 seconds.
As a result, the 4.48-millisecond delay may not cause the user to notice the impact of the
CHAPTER 8. EXPERIMENTS 88
ReppSi system.
Figure 8.12: The response time of browsing the Moodle service from London [48]
Nevertheless, the performance test was performed with Super Veda, a tiny online
shopping application. The profile database is very small, leading to the very short process
time. In the case of enterprise-level web application, its profile database will be dramatically
larger than that of Super Veda. The delay caused by the database connection for selecting
the related profiles will be huge. Therefore, it is recommended that a system for caching
the profiles be developed, as well as the algorithm for searching the profiles be improved.
The false positive test was performed after the protection test. The test used the same
experimental setup with the same profile database as the protection test. The objective of
this test is to check whether other normal HTTP requests apart from the attacks can pass
through the ReppSi system without being blocked. More than 500 legitimate requests from
five web clients were inspected by the ReppSi system. The result is shown in table 8.7.
There was only one legitimate request blocked by the ReppSi system. After checking
the log file, two alerts related to the /register.jsp page were generated as presented in figure
8.13. The ReppSi system blocked the request because unauthorized special characters had
been found in the parameter “Password1” and “Password2”. Both of them were the user-
supplied input for entering the user’s password in the process of registration as illustrated in
figure 8.14. The alert log also shows that the allowed special characters of those parameters
only consisted of “;”, “$”, and “!” whereas the input, “T3tht@lkth@!”, contained “@”.
Consequently, the ReppSi system identified the request as an attack.
Figure 8.14: The /register.jsp page that caused the false positives
Figure 8.15: The profile records that caused the false positives
Figure 8.16: The SQL command for updating the profile records
8.4 summary
All three tests shows the results as expected. Even though there is a problem from the
SQL exception when testing with OWASP ZAP, more than 90% of the SQL injection attacks
were detected and blocked by ReppSi. While scanning the Super Veda application with
Subgraph Vega, it could prevent all SQL injection attacks. In addition to the SQL injection
attacks, ReppSi managed to detect and block many types of web attacks, such as remote
OS command injection, cross-site scripting, and the leakage of sensitive server information
through error messages, thanks to the comprehensive profiles the ReppSi system collected
from the learning phase. Nevertheless, the profiles were not perfect, leading to the false
positive found when using the web application normally. The security administrator is
CHAPTER 8. EXPERIMENTS 92
recommended to review and modify the related profile in order to solve this problem.
Super Veda is a tiny web application for online shopping. The profile is easy to collect
and does not require a large amount of time for the learning phase. In contrast, enterprise-
level websites require huge database systems and time for building the profiles. The HTTP
requests in the learning phase might contain not only the legitimate requests but also the
bad requests. Consequently, profile reviewing process would be difficult and consumed high
man-hours. Incompleteness of the profiles may lead to being incapable of blocking SQL
injection attacks and a high false positive rate. It is recommended to deploy ReppSi with
other security systems such as an intrusion prevention system or a web application firewall in
order to comprehensively detect all kinds of SQL injection attacks. This recommendation
follows the defense-in-depth concept that helps the security administrator to strengthen
the application security. Furthermore, the high false positive rate could be minimized by
using the simulation mode, another operation mode apart from the profiling mode and the
protection mode. The simulation mode is capable of detecting all suspicious HTTP traffic
in the same way as the protection mode. However, it will not block any traffic even if it is
an attack. This mode is designed for checking the results when using the ReppSi system in
the protection mode. If false positives are spotted, the security administrator can modify
the related profiles before changing to the protection mode and beginning blocking the
suspicious traffic. The simulation mode is planned to implement in the future.
Chapter 9
This chapter describes limitations of both usability and security of the ReppSi system,
as well as suggestions for future improvement.
9.1 Limitations
The essential limitation of the behaviour-based detection is the learning phase. All
HTTP requests in the learning phase must be legitimate without any malicious code or
93
CHAPTER 9. LIMITATIONS AND FUTURE WORK 94
attack hidden inside. A great number of the legitimate requests lead to comprehensive
profiles that can detect anomalous web usage effectively with the low false positive rate.
Nevertheless, there are some cases that even though the profiles are built from an abundance
of the legitimate requests, the ReppSi system cannot detect SQL injection attacks. That is,
the profiles contain characters that allow the user to input SQL commands. For instance,
the parameter “password” has the parameter type “All” and special parameters allowed
for this parameter consist of “ ‘ ” (quote), “ = ” (equal sign), and “ ” (white space).
It is a norm for the password to have these special characters. As a result, if the user
enters “’ OR ‘1’=‘1” into the user-supplied input, the ReppSi system will not detect the
request as an SQL injection attack and will forward the request to the web server. The
solution for preventing this problem is that the web developer needs to limit the special
character allowed for the parameter. In the case that the web developer cannot control
the user-supplied input and the profile record led to the false negative cannot be modified,
it is recommended that other security mechanisms be implemented to cooperate with the
ReppSi system in preventing the SQL injection attacks.
The ultimate goal of ReppSi is to be deployed in the University system so that it can
protect the online services from being attacked. Therefore, the multi-threading problem is
the first task to be solved. ReppSi should support at least 400 HTTP requests per second
so that it can be implemented in the University system and run without any problem. The
next task is that the program will be written to support multiple destination hosts in order
to protect important web services such as the library’s system and the registration system
at the same time. Moreover, GUI should be designed to help the security administrator
to easily view and manage the ReppSi’s system. After eliminating all limitations of the
ReppSi, the proxy will be tested with the Moodle e-learning system in the real environment
in order to confirm that it can protect the Moodle from SQL injection attacks.
For the performance of the ReppSi, the result of the performance test shows that the
average process time is very low (less than 5 milliseconds) compared to the response time
over the Internet. Nevertheless, due to the small size of the tested web server, the program
and the algorithm for logging and searching the data in the database might be altered to
improve the performance in the future.
For security features, the current version of the ReppSi system creates the profiles
from URLs and parameters in the HTTP request. The next version is planned to add
CHAPTER 9. LIMITATIONS AND FUTURE WORK 95
cookies to the profiles so that the ReppSi system can detect attacks that exploit the cookie
vulnerability such as cookie injection and cookie tampering. Furthermore, due to the fact
that the application source code contains the HTML forms used to collect user input (pa-
rameters), and the database structure collects the type as well as the maximum length of
the parameter, an approach for automatically creating the basic profiles from the applica-
tion source code and the database structure might be considered to reduce the time of the
learning phase. The basic profiles can use to filter some bad HTTP requests while learning
as well.
Chapter 10
Conclusion
The assessment of the Moodle system presents that although there are some SQL
injection vulnerabilities discovered in the previous versions of the Moodle template, they
have not been found in the University’s Moodle service, thanks to the developers and the
system administrators who take care of it. However, it does not mean there are no SQL
vulnerabilities existing in the Moodle system. According to the concept of defense-in-
depth, the University’s system should have multi-layered security mechanisms so that if
an attack causes any security mechanism to fail, other mechanisms can still provide the
necessary mechanism to protect the system. Hence, the University’s system should have
an additional security system to prevent SQL injection attacks. This is the main objective
of this research.
There are many pieces of research about SQL injection prevention, but most of them
require application code modification or are deployed in the middle between a web server
and a database server. These conditions lead to an inability to implement in some environ-
ments. Therefore, ReppSi, the SQL injection prevention system designed in this research,
is deployed in front of the web server as a reverse proxy and does not need to modify the
application code. An approach used to detect SQL injection attacks of the ReppSi system
is based on the behavior-based detection. The operation is divided into two phases, the
learning phase and the protection phase. In the learning phase, the behavior-based de-
96
CHAPTER 10. CONCLUSION 97
tection system collects the characteristics of using the web application such as URLs that
the users accessed, patterns, and length of the user-supplied inputs. After that, in the
protection phase, it creates profiles as security rules to detect unauthorized (anomalous)
web usage, for example, an SQL injection attack hidden inside the HTTP request.
ReppSi is a pure Java-based reverse proxy application that can run on major operating
systems such as Windows, Mac OS X, and Linux. It uses the Membrane Service Proxy
framework to implement the reverse proxy function and uses MySQL database to store the
profiles of the protected web server. The security administrator can view and manage the
profiles using phpMyAdmin. In addition, ReppSi provides a logging system that collects
system events and alerts into a text file so that the security administrator can check the
history logs and create a security report.
ReppSi was tested by being installed in front of Super Veda, a vulnerable web ap-
plication written by Imperva. All HTTP requests sent to Super Veda were redirected to
ReppSi in order to scan for SQL injection attacks before being forwarded to the destina-
tion. OWASP ZAP and Subgraph Vega, web vulnerability scanning tools, were used to
check whether ReppSi could detect and prevent SQL injection attacks targeting the web
application or not. The results show that ReppSi could detect all kinds of the SQL in-
jection attacks generated by both scanners, but it could prevent only 92 percent of the
attacks from OWASP ZAP. It is because the ReppSi’s prevention system did not support
multi-threading so it could not handle the attacks more than 200 requests per second from
OWASP ZAP at the same time. In contrast, it could prevent 100 percent of the SQL injec-
tion attacks generated by Subgraph Vega. Apart from the SQL injection attacks, ReppSi
was capable of detecting and blocking other kinds of attacks such as cross-site scripting
and remote OS command injection. These attacks, like SQL injection attacks, required re-
quest’s parameters to inject the command code. Due to the comprehensive profiles ReppSi
collected from the learning phase, it could detect the malicious code inside the parameter
value effectively. Nonetheless, the profiles were not perfect, leading to one false positive
found when performing the false positive test. The security administrator is recommended
to review and modify the related profile in order to solve this problem. In short, a successful
rate of detecting the attacks and a false positive rate depend on correctness and accuracy
of the profiles. Additionally, for the performance issue, the delay caused by the ReppSi
system is very short compared to the average response time of the HTTP request. The
user may not notice the impact of the ReppSi system.
The ReppSi’s source code will be modified to support multi-threading in the future.
GUI is also designed to make the management user-friendly. Furthermore, the security
CHAPTER 10. CONCLUSION 98
features will be improved to assure that the profiles collected in the learning phase come
from legitimate HTTP requests. After that, it will be tested with the Moodle system in
the University’s environment in order to prove that the ReppSi system can protect the
University’s online services from SQL injection attacks.
Bibliography
[1] Acunetix, (2014). Web Applications: What are They? What of Them?. [online]
Acunetix. Available at: http://www.acunetix.com/websitesecurity/web-applications/
[Accessed 9 Apr. 2015].
[3] Boyd, S. and Keromytis, A. (2004). SQLrand: Preventing SQL Injection Attacks.
Springer Berlin Heidelberg, [online] 3089, pp.292-302. Available at:
http://dx.doi.org/10.1007/978-3-540-24852-1 21 [Accessed 10 Apr. 2015].
[4] Buehrer, G., Weide, B. and Sivilotti, P. (2005). Using Parse Tree Validation to
Prevent SQL Injection Attacks. In: Proceedings of 5th International Workshop on
Software Engineering and Middleware. [online] ACM, pp.106-113. Available at:
http://doi.acm.org/10.1145/1108473.1108496 [Accessed 13 Apr. 2015].
[6] Christensen, A., Moller, A. and Schwartzbach, M. (2003). Precise Analysis of String
Expressions. In: Proceedings of the 10th International Conference on Static Analysis.
[online] Berlin, Heidelberg: Springer-Verlag, pp.1-18. Available at:
http://dl.acm.org/citation.cfm?id=1760267.1760269.
[7] Cisco, (2013). Understanding SQL Injection. [online] Cisco. Available at:
http://www.cisco.com/web/about/security/intelligence/sql injection.html [Accessed
15 Apr. 2015].
99
BIBLIOGRAPHY 100
[8] Curtis, S. (2012). Barclays: 97 percent of data breaches still due to SQL injection.
[online] Techworld. Available at: http://www.techworld.com/news/security/barclays-
97-percent-of-data-breaches-still-due-sql-injection-3331283/ [Accessed 10 Apr.
2015].
[9] CVE Details, (2015). Moodle : Security vulnerabilities. [online] CVE Details.
Available at:
http://www.cvedetails.com/vulnerability-list/vendor id-2105/opsqli-1/Moodle.html
[Accessed 9 Apr. 2015].
[10] Det Centrale Personregister, (2013). Executive Order on the Civil Registration
System Act. CPR Civil Registration System Act.
[11] EPIC, (2014). National ID and the REAL ID Act. [online] Electronic Privacy
Information Center. Available at: https://epic.org/privacy/id cards/ [Accessed 8
Apr. 2015].
[12] Halfond, W. and Orso, A. (2005). AMNESIA: Analysis and Monitoring for
NEutralizing SQL-injection Attacks. In: Proceedings of the 20th IEEE/ACM
international Conference on Automated software engineering. [online] pp.174-183.
Available at: http://doi.acm.org/10.1145/1101908.1101935 [Accessed 11 Apr. 2015].
[13] Halfond, W., Orso, A. and Manolios, P. (2006). Using Positive Tainting and
Syntax-aware Evaluation to Counter SQL Injection Attacks. In: Proceedings of the
14th ACM SIGSOFT International Symposium on Foundations of Software
Engineering. [online] New York, USA: ACM, pp.175-185. Available at:
http://doi.acm.org/10.1145/1181775.1181797 [Accessed 11 Apr. 2015].
[15] Imperva, (2004). Application Penetration Test Super Veda. [online] Imperva, pp.8-9.
Available at: http://www.cgisecurity.com/lib/VedaPenetrationTest.pdf [Accessed 10
Apr. 2015].
[16] INSEE, (n.d.). National Directory for the Identification of Natural Persons /
RNIPP. [online] National Institute of Statistics and Economic Studies. Available at:
http://www.insee.fr/en/methodes/default.asp?page=definitions/rnipp.htm [Accessed
8 Apr. 2015].
BIBLIOGRAPHY 101
[17] International Telecommunication Union, (2014). The World in 2014: ICT Facts and
Figures. [online] International Telecommunication Union, p.5. Available at:
http://www.itu.int/en/ITU-D/Statistics/Documents/facts/ICTFactsFigures2014-
e.pdf [Accessed 8 Apr.
2015].
[18] Java, (2015). Learn about Java Technology. [online] Available at:
http://www.java.com/en/about/ [Accessed 22 Aug. 2015].
[21] Kerner, S. (2013). How Was SQL Injection Discovered?. [online] eSecurity Planet.
Available at: http://www.esecurityplanet.com/network-security/how-was-sql-
injection-discovered.html [Accessed 9 Apr.
2015].
[24] Lungu, I., Velicanu, M. and Botha, I. (2009). Database Systems - Present and
Future. Informatica Economica, [online] 13(1), pp.84-99. Available at:
http://search.ebscohost.com/login.aspx?direct=true&db=bth&AN=38011631&site=ehost-
live.
BIBLIOGRAPHY 102
[25] Martin, B., Brown, M., Paller, A. and Kirby, D. (2011). CWE -2011 CWE/SANS
Top 25 Most Dangerous Software Errors. [online] Common Weakness Enumeration.
Available at: http://cwe.mitre.org/top25/index.html [Accessed 10 Apr. 2015].
[27] Microsoft, (2015). Structured Query Language (SQL). [online] MSDN - Dev Center.
Available at: https://msdn.microsoft.com/en-
gb/library/windows/desktop/ms714670(v=vs.85).aspx [Accessed 8 Apr.
2015].
[30] NAA, (2015). Benefits of digital information and records. [online] National Archives
of Australia. Available at: http://www.naa.gov.au/records-management/digital-
transition-policy/benefits-of-digital-information.aspx [Accessed 8 Apr.
2015].
[31] National Security Agency Attention, (2009). Defense in Depth. National Security
Agency Attention, pp.1-3.
[32] NHS, (2015). Your health records. [online] The NHS in England - NHS Choices.
Available at:
http://www.nhs.uk/nhsengland/thenhs/records/healthrecords/pages/overview.aspx
[Accessed 8 Apr. 2015].
[33] Oracle, (2015). Class Logger. [online] Java Platform, Standard Edition 7. Available
at: http://docs.oracle.com/javase/7/docs/api/java/util/logging/Logger.html
[Accessed 22 Aug. 2015].
[34] OWASP, (2013). The Ten Most Critical Web Application Security Risks. OWASP
Top 10 - 2013. [online] OWASP, pp.6-7. Available at:
http://owasptop10.googlecode.com/files/OWASP%20Top%2010%20-%202013.pdf
[Accessed 12 Apr. 2015].
[36] OWASP, (2015). List of useful HTTP headers. [online] OWASP. Available at:
https://www.owasp.org/index.php/List of useful HTTP headers [Accessed 20 Aug.
2015].
[37] OWASP, (2015). OWASP Zed Attack Proxy Project. [online] OWASP. Available at:
https://www.owasp.org/index.php/OWASP Zed Attack Proxy Project [Accessed 10
Apr. 2015].
[38] Ponniah, P. (2003). Database design and development. Piscataway, NJ: Wiley-IEEE
Press.
[39] Predic8, (2015). Message Interceptors. [online] Membrane Service Proxy. Available
at: http://membrane-soa.org/service-proxy-doc/4.0/interceptors.htm [Accessed 22
Aug. 2015].
[40] SREO, (2013). Frequently Asked Questions (FAQs). [online] Student Records &
Examinations Office. Available at:
http://www.bath.ac.uk/student-records/faq/index.html#s03 [Accessed 9 Apr. 2015].
[41] Su, Z. and Wassermann, G. (2006). The Essence of Command Injection Attacks in
Web Applications. In: the 33rd ACM SIGPLAN-SIGACT Symposium on Principles
of Programming Languages. [online] ACM, pp.372–82. Available at:
http://doi.acm.org/10.1145/1111037.1111070 [Accessed 11 Apr. 2015].
[42] Subgraph, (2014). Vega Vulnerability Scanner. [online] Subgraph. Available at:
https://subgraph.com/vega/index.en.html [Accessed 10 Apr. 2015].
[43] Tajpour, A. and JorJor Zade Shooshtari, M. (2010). Evaluation of SQL Injection
Detection and Prevention Techniques. In: Computational Intelligence,
Communication Systems and Networks (CICSyN), 2010 Second International
Conference on. [online] IEEE, pp.216-221. Available at:
http://ieeexplore.ieee.org/xpls/abs all.jsp?arnumber=5615711&tag=1 [Accessed 13
Apr. 2015].
[44] University of Bath, (2015). Library Services. [online] The Library & Learning Centre.
Available at: http://www.bath.ac.uk/library/services/ [Accessed 9 Apr. 2015].
[45] Valeur, F., Mutz, D. and Vigna, G. (2005). A Learning-Based Approach to the
Detection of SQL Attacks. Detection of Intrusions and Malware, and Vulnerability
Assessment, [online] pp.123-140. Available at:
http://dl.acm.org/citation.cfm?id=2144860 [Accessed 11 Apr. 2015].
BIBLIOGRAPHY 104
[46] Verizon, (2014). 2014 Data Breach Investigations Report. [online] Verizon, pp.3-4.
Available at: http://www.verizonenterprise.com/DBIR/2014/reports/rp Verizon-
DBIR-2014 en xg.pdf [Accessed 13 Apr.
2015].
[47] Wassermann, G. and Su, Z. (2004). An Analysis Framework for Security in Web
Applications. In: Specification and Verification of Component-Based Systems. [online]
pp.70-78. Available at:
http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.137.7225 [Accessed 10
Apr. 2015].
[48] Web Page Test, (2015). Web Page Performance Test for moodle.bath.ac.uk. [online]
Available at: http://www.webpagetest.org/result/150830 BN K4H/1/details/
[Accessed 30 Aug. 2015].
Appendix A
Installation Guide
2. Browse the phpMyAdmin application and create a database for collecting the logs
and the profiles data.
1. Download the Membrane Proxy Service Framework version 4.0.18 from http://
mirror.predic8.com/membrane/router/membrane-service-proxy-4.0.18.zip
2. Unzip the file, and then locate the JAR file in the library directory
%MEMBRANE HOME/lib.
105
APPENDIX A. INSTALLATION GUIDE 106
4. Create a package name “ReppSi”. Then, import the source code from Appendix D
into the package. There are five classes, ReverseProxy.java, SuspiciousInputDetec-
tionEngine.java, TrafficInterceptor.java, TxtLogFormatter.java, and TxtLogger.java.
(Or import ReppSi.jar from the attached CD into your project.)
Figure A.3: Java build path that the Membrane libraries have been already imported
• At line 19, change listenPort to the listen port of the machine (default is 8100)
• At line 23 and 24, change targetHost and targetPort to the protected web server
IP/domain name and port
• Then, compile the java file.
APPENDIX A. INSTALLATION GUIDE 108
8. Configure the location of the log file by opening TxtLogger.java. At line 31, change
the file location as desired. Then, compile the java file.
User Manual
After installation, there are some parameters needed to configure. The parameters
include the listen port of the machine running ReppSi, the protected web server IP/domain
name and port, the MySQL connection, and the location of the log file. See more details
in Appendix A.2 ReppSi Installation (Step 6 - 8).
Figure B.1: The Java console prompts the user for the operation mode
109
APPENDIX B. USER MANUAL 110
Now, the ReppSi system is running and ready to handle HTTP requests from the web
clients.
The operation can be stopped by pressing the Terminate button on the top right of
the Java console.
* It is recommended to run ReppSi in the Profiling mode at the first time so that it can
collect HTTP requests. When ReppSi collects enough the HTTP requests (the more, the
better), the ReppSi system is required to be restarted in order to update the profiles. Then,
change the operation mode to “1” Protection mode. Now, the ReppSi system is ready to
protect the web server.
The log tables and the profile tables in the MySQL database can be viewed and
managed using the phpMyAdmin web application. It is available as long as the MAMP
application is running. The default phpMyAdmin page can be accessed via this URL:
http://localhost:8888/MAMP/index.php?page=phpmyadmin&language=English.
Each protected web server possesses two tables, the log table and the profile table.
The log table is the one whose name ends with -log. The profile table is the one whose
name ends with -profile.
APPENDIX B. USER MANUAL 111
• Select “SQL” tab to input an SQL command in order to modify the data such as
update the data in the profile table.
The log file is located at the file path you configured in step 8, Appendix A.2 ReppSi
Installation. A text editor application such as Notepad or TextEdit can be used to view
the log file. An example of the log file is shown in figure B.3.
APPENDIX B. USER MANUAL 112
The result of using OWASP ZAP to scan the Moodle e-learning system is presented in
table C.1. The version of the software is 2.3.1 which is the latest version of the assessment
time. It is configured to scan all types of the web vulnerabilities.
Severity: Medium
113
APPENDIX C. RAW RESULTS OUTPUT 114
Solution by OWASP [37]: Most web browsers in the present support the X-Frame-
Options HTTP header. The developer should ensure that it is set on all web pages returned
by the developer’s site. If the developer expects the page to be framed only by pages on
the developer’s server (e.g. it is part of a FRAMESET) then the developer needs to set the
header as SAMEORIGIN, otherwise if the developer never expects the page to be framed,
the developer should set DENY. ALLOW-FROM allows specific websites to frame the web
page in supported web browsers.
Affected URLs:
1. http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML
2. http://cdn.mathjax.org/mathjax/latest/config/TeX-AMS-MML_HTMLorMML.js?rev=
2.5.3
3. http://moodle.bath.ac.uk/
4. http://moodle.bath.ac.uk/blocks/bath_oue/stats.php?username=sk914
5. http://moodle.bath.ac.uk/lib/javascript.php/-1/blocks/bath_oue/js/module.
js
6. http://moodle.bath.ac.uk/lib/javascript.php/-1/lib/javascript-static.js
7. http://moodle.bath.ac.uk/lib/javascript.php/1435681425/blocks/course_overview/
module.js
8. http://moodle.bath.ac.uk/lib/javascript.php/1435681425/lib/javascript-static.
js
9. http://moodle.bath.ac.uk/login/logout.php?sesskey=2Ip9Ixv3xj
10. http://moodle.bath.ac.uk/login/logout.php?sesskey=HlSnsofSqb
11. http://moodle.bath.ac.uk/login/logout.php?sesskey=f5jFI7mpmN
12. http://moodle.bath.ac.uk/my/
13. http://moodle.bath.ac.uk/theme/javascript.php/bath_bootstrap/1435681425/
footer
14. http://moodle.bath.ac.uk/theme/styles.php/bath_bootstrap/1435681425/all
APPENDIX C. RAW RESULTS OUTPUT 115
15. http://moodle.bath.ac.uk/theme/yui_combo.php?3.13.0/anim-base/anim-base-
min.js&3.13.0/anim-color/anim-color-min.js&3.13.0/anim-xy/anim-xy-min.
js&3.13.0/anim-curve/anim-curve-min.js&3.13.0/anim-easing/anim-easing-
min.js&3.13.0/anim-node-plugin/anim-node-plugin-min.js&3.13.0/anim-scroll/
anim-scroll-min.js
16. http://moodle.bath.ac.uk/theme/yui_combo.php?3.13.0/anim-base/anim-base-
min.js&3.13.0/anim-color/anim-color-min.js&3.13.0/anim-xy/anim-xy-min.
js&3.13.0/anim-curve/anim-curve-min.js&3.13.0/anim-easing/anim-easing-
min.js&3.13.0/anim-node-plugin/anim-node-plugin-min.js&3.13.0/anim-scroll/
anim-scroll-min.js&3.13.0/datatype-xml-parse/datatype-xml-parse-min.js&
3.13.0/io-xdr/io-xdr-min.js&3.13.0/io-form/io-form-min.js&3.13.0/io-upload-
iframe/io-upload-iframe-min.js&3.13.0/queue-promote/queue-promote-min.
js&3.13.0/io-queue/io-queue-min.js&3.13.0/matrix/matrix-min.js&3.13.0/
graphics/graphics-min.js&3.13.0/cookie/cookie-min.js&3.13.0/graphics-svg-
default/graphics-svg-default-min.js&3.13.0/graphics-svg/graphics-svg-min.
js
17. http://moodle.bath.ac.uk/theme/yui_combo.php?3.13.0/cssbutton/cssbutton-
min.css
18. http://moodle.bath.ac.uk/theme/yui_combo.php?3.13.0/plugin/plugin-min.js&
3.13.0/event-mousewheel/event-mousewheel-min.js&3.13.0/event-resize/event-
resize-min.js&3.13.0/event-hover/event-hover-min.js&3.13.0/event-touch/
event-touch-min.js&3.13.0/event-move/event-move-min.js&3.13.0/event-flick/
event-flick-min.js&3.13.0/event-valuechange/event-valuechange-min.js&3.
13.0/event-tap/event-tap-min.js
19. http://moodle.bath.ac.uk/theme/yui_combo.php?m/1435681425/block_navigation/
navigation/navigation-min.js
20. http://moodle.bath.ac.uk/theme/yui_combo.php?m/1435681425/core/lockscroll/
lockscroll-min.js&m/1435681425/core/notification/notification-alert-min.
js&m/1435681425/core/notification/notification-confirm-min.js&m/1435681425/
core/notification/notification-exception-min.js&m/1435681425/core/notification/
notification-ajaxexception-min.js&m/1435681425/core/notification/notification-
min.js&3.13.0/cache-base/cache-base-min.js&m/1435681425/core/popuphelp/
popuphelp-min.js
APPENDIX C. RAW RESULTS OUTPUT 116
21. http://moodle.bath.ac.uk/theme/yui_combo.php?m/1435681425/core/lockscroll/
lockscroll-min.js&m/1435681425/core/notification/notification-alert-min.
js&m/1435681425/filter_glossary/autolinker/autolinker-min.js
22. http://moodle.bath.ac.uk/theme/yui_combo.php?m/1435681425/core/notification/
notification-confirm-min.js&m/1435681425/core/notification/notification-
exception-min.js&m/1435681425/core/notification/notification-ajaxexception-
min.js&m/1435681425/core/notification/notification-min.js&3.13.0/cache-
base/cache-base-min.js&m/1435681425/core/popuphelp/popuphelp-min.js
23. http://moodle.bath.ac.uk/theme/yui_combo.php?m/1435681425/theme_bootstrapbase/
bootstrap/bootstrap-min.js
24. http://moodle.bath.ac.uk/theme/yui_combo.php?rollup/-1/mcore-min.js
25. http://moodle.bath.ac.uk/theme/yui_combo.php?rollup/1435681425/mcore-min.
js
26. http://moodle.bath.ac.uk/theme/yui_combo.php?rollup/3.13.0/yui-moodlesimple-
min.css
27. http://moodle.bath.ac.uk/theme/yui_combo.php?rollup/3.13.0/yui-moodlesimple-
min.js
28. http://www.bath.ac.uk/common/css/global.css?colour=internal&template=page&
columns=2
29. http://www.bath.ac.uk/common/css/print.css?columns=2
30. http://www.bath.ac.uk/common/js/editpage.php
31. http://www.bath.ac.uk/common/js/exploreBar.js
32. http://www.bath.ac.uk/common/js/jquery-1.8.2.min.js
33. http://www.bath.ac.uk/common/js/pdftracking.js
34. http://www.bath.ac.uk/web/guides/sso/
35. http://www.bath.ac.uk/web/tools/sso/
36. http://www.google-analytics.com/analytics.js
37. http://www.google-analytics.com/ga.js
APPENDIX C. RAW RESULTS OUTPUT 117
Severity: Low
Description by OWASP [37]: A cookie has been configured without the HttpOnly flag.
That is, the cookie can be accessed by JavaScript. If an attacker runs a malicious script on
this page, the cookie will be accessible and can be transmitted to another site. Similarly,
if it is a session cookie, session hijacking might be occurred.
Solution by OWASP [37]: The developer needs to ensure that the HttpOnly flag is set
for all cookies.
Affected URLs:
1. http://moodle.bath.ac.uk/
Figure C.4: The Cookie Set without HttpOnly Flag alert of http://moodle.bath.ac.uk/
2. http://moodle.bath.ac.uk/login/logout.php?sesskey=2Ip9Ixv3xj
Figure C.5: The Cookie Set without HttpOnly Flag alert of http://moodle.bath.ac.uk/
login/logout.php?sesskey=2Ip9Ixv3xj
APPENDIX C. RAW RESULTS OUTPUT 119
3. http://moodle.bath.ac.uk/login/logout.php?sesskey=HlSnsofSqb
Figure C.6: The Cookie Set without HttpOnly Flag alert of http://moodle.bath.ac.uk/
login/logout.php?sesskey=HlSnsofSqb
4. http://moodle.bath.ac.uk/login/logout.php?sesskey=f5jFI7mpmN
Figure C.7: The Cookie Set without HttpOnly Flag alert of http://moodle.bath.ac.uk/
login/logout.php?sesskey=f5jFI7mpmN
APPENDIX C. RAW RESULTS OUTPUT 120
5. http://www.bath.ac.uk/common/css/print.css?columns=2
Figure C.8: The Cookie Set without HttpOnly Flag alert of http://www.bath.ac.uk/
common/css/print.css?columns=2
6. http://www.bath.ac.uk/web/tools/sso/
Figure C.9: The Cookie Set without HttpOnly Flag alert of http://www.bath.ac.uk/
web/tools/sso/
APPENDIX C. RAW RESULTS OUTPUT 121
Severity: Low
Description by OWASP [37]: The pages of the affected URLs include one or more
script files from a third-party domain.
Solution by OWASP [37]: The developer needs to ensure that JavaScript source files
are loaded from only trusted sources, and the sources cannot be controlled by end users of
the application.
Affected URLs:
APPENDIX C. RAW RESULTS OUTPUT 122
1. http://moodle.bath.ac.uk/
Figure C.12: The Cross-Domain JavaScript Source File Inclusion alert of http://moodle.
bath.ac.uk/
2. http://moodle.bath.ac.uk/my/
Figure C.14: The Cross-Domain JavaScript Source File Inclusion alert of http://moodle.
bath.ac.uk/my/
Severity: Low
Description by OWASP [37]: Web Browser XSS Protection is not enabled or is disabled
by the configuration of the “X-XSS-Protection” HTTP response header on the web server.
Solution by OWASP [37]: The developer needs to ensure that the web browser’s XSS
filter is enabled, by setting the X-XSS-Protection HTTP response header to “1”.
Affected URLs: The same URLs as C.1 X-Frame-Options Header Not Set.
APPENDIX C. RAW RESULTS OUTPUT 124
Figure C.16: The Web Browser XSS Protection Not Enabled alert of http://moodle.
bath.ac.uk/
Severity: Low
Solution by OWASP [37]: The developer needs to ensure that the web application sets
the Content-Type header appropriately. That is, sets the X-Content-Type-Options header
to “nosniff” for all web pages.
Affected URLs: The same URLs as C.1 X-Frame-Options Header Not Set. Except http:
//www.bath.ac.uk/web/guides/sso/ and http://www.bath.ac.uk/web/tools/sso/
The result of using Subgraph Vega to scan the Moodle e-learning system is presented
in table C.2. The version of the software is 1.0 which is the latest version of the assessment
time. It is configured to scan all types of the web vulnerabilities.
Severity: High
Solution by Vega [42]: Passwords should never be sent in the cleartext across unen-
crypted channel. The form should submit to an HTTPS target.
Severity: High
Description by Vega [42]: The content on a web server is including JavaScript file from
an unrelated domain. When this script code is fetched by a user browser and loaded into
the DOM, it will have complete control over the DOM, bypassing the protection offered
by the same-origin policy. Even if the source of the script code is trusted by the website
APPENDIX C. RAW RESULTS OUTPUT 128
Solution by Vega [42]: It is strongly recommended that web servers should host their
own JavaScript locally, especially for critical applications.
Affected URLs:
Integer Overflow
Severity: High
Description by Vega [42]: Integer overflow is a kind of buffer overflow which occur when
an integer data type exceeds its maximum value. When it occurs in programs written in
languages such as C, it contributes to security implications. For instance, unsigned integers
will be reduced, result in wrapping back to a lower numeric value. The consequence on
security depends on how the integer value is used. If it is used as the size of a data buffer,
it may lead to bypassing of size checks.
APPENDIX C. RAW RESULTS OUTPUT 130
Solution by Vega [42]: The developer should investigate the error and determine if a
vulnerability is present.
Severity: High
Description by Vega [42]: A different response page fingerprint in relation to a local file
include injection request was detected. This means that the response page content returned
by the web application has a different signature from that returned by an ordinary request,
which may indicate the existence of a local file include vulnerability. Local file includes
vulnerabilities are present when externally-supplied input is used to specify the location
APPENDIX C. RAW RESULTS OUTPUT 131
of a local filesystem resource that is requested by the web application. The differing page
fingerprint may include error messages or indicate a state change in the application in
response to the local file include injection attempt made by Vega. Differing responses may
also be indicative of a file enumeration vulnerability, which would allow an attacker to
determine if specific files exist on the system. Developers should examine the response
content and underlying code to verify whether or not a vulnerability is present. If the
vulnerability exists and precautions are not taken, such a vulnerability could allow attackers
to gain unauthorized access to sensitive information contained in local files, which may also
be leveraged in further attacks on the web application.
Solution by Vega [42]: To prevent this type of vulnerability, the developer should canon-
icalize the path of any filesystem resource that has a path composed of externally-supplied
input and then perform an authorization check prior to access. For example, the real-
path() library call will return the canonical path of the resource for PHP, Perl, and Python
programming.
Affected URLs:
1. http://moodle.bath.ac.uk/course/search.php
2. http://moodle.bath.ac.uk/course/view.php
Severity: Medium
Description by Vega [42]: A possible absolute filesystem path (i.e. one that is not
relative to the web root) was detected. This information is sensitive, as it may reveal things
about the server environment to an attacker. Knowing filesystem layout can increase the
chances of success for blind attacks.
Solution by Vega [42]: Full system paths are very often found in error output. This
output should never be sent to clients on production systems. It should be redirected
to another output channel (such as an error log) for analysis by developers and system
administrators.
APPENDIX C. RAW RESULTS OUTPUT 133
Affected URLs:
1. http://moodle.bath.ac.uk/
2. http://moodle.bath.ac.uk/lib/javascript.php/-1/lib/javascript-static.js
3. http://moodle.bath.ac.uk/my/
4. http://moodle.bath.ac.uk//theme/yui_combo.php
Severity: Low
Description by Vega [42]: Listing directory contents when no index file is present in
a common misconfiguration. The directory contents can provide useful information to an
attacker, especially if there are files that are not meant to be accessible, such as source code
or backups. The directory listing may also provide useful information about the habits of
APPENDIX C. RAW RESULTS OUTPUT 137
the server administration and/or web developers, such as file naming convention, that could
be used to increase the probable success of brute-force or other attacks.
Solution by Vega [42]: For Apache, add “IndexIgnore *” to the directory’s .htaccess
file, or alternatively remove “Indexes” from the line “Options All Indexes FollowSymLinks
MultiViews” in the Apache configuration file. For lighttpd, change “dir-listing.activate”
parameter from “enable” to “disable” in the lighttpd configuration file.
Affected URLs:
Severity: Low
Description by Vega [42]: Patterns that resemble email addresses in scanned content
were found. These may be user the addresses of system users, addresses inserted in user-
supplied content, or third-party addresses embedded in components of the application (such
as JavaScript libraries). Automatically scraping websites is one way that spammers and
phishers collect email addresses for their distribution lists.
Affected URLs:
Severity: Information
Description by Vega [42]: Vega has detected that this cookie was set without the
HttpOnly flag. When this flag is not present, it is possible to access the cookie via client-
side script code.
Solution by Vega [42]: The HttpOnly flag is a security measure that can help mitigate
the risk of cross-site scripting attacks that target session cookies of the victim. If the
HttpOnly flag is set and the browser supports this feature, attacker-supplied script code
will not be able to access the cookie.
APPENDIX C. RAW RESULTS OUTPUT 141
Figure C.44: The Cookie HttpOnly Flag Not Set alert of http://moodle.bath.ac.uk/
Severity: Information
Description by Vega [42]: Vega has detected that the resource has not set the X-Frame-
Options HTTP response header. This header allows the resource to specify its policy with
regards to whether it may be included in frames in other domains as well as which domains
are allowed. When the header has been set, this may help to mitigate clickjacking attacks
APPENDIX C. RAW RESULTS OUTPUT 142
against browsers that support this feature. If the header has not been set, the affected
resource may be used in clickjacking attacks.
Affected URLs:
Figure C.46: 46 affected URLs of the X-Frame-Options Header Not Set alerts
APPENDIX C. RAW RESULTS OUTPUT 143
As shown in figure C.50 and C.51, the complete profile table was built from 672 HTTP
requests in the learning phase.
Figure C.52 presents an example of the log file generated by the ReppSi system.
APPENDIX C. RAW RESULTS OUTPUT 146
Figure C.52: An example of the log file generated by the ReppSi system
APPENDIX C. RAW RESULTS OUTPUT 147
Before implementing ReppSi, there are two kinds of SQL injection vulnerabilities found
on the Super Veda application, SQL Injection - Authentication Bypass and SQL Injection
- MySQL. While scanning, the IP address of Super Veda was 172.16.1.101.
Figure C.53: The SQL Injection - Authentication Bypass alert of Super Veda 1
Figure C.54: The SQL Injection - Authentication Bypass alert of Super Veda 2
APPENDIX C. RAW RESULTS OUTPUT 148
Affected URLs:
1. http://172.16.1.101/add2cart.jsp
2. http://172.16.1.101/addcomment.jsp
3. http://172.16.1.101/dosearch.jsp
4. http://172.16.1.101/login.jsp
5. http://172.16.1.101/proddetails.jsp
6. http://172.16.1.101/showproducts.jsp
7. http://172.16.1.101/postcomment.jsp
8. http://172.16.1.101/register.jsp
Figure C.56: The response body of the SQL Injection - MySQL alert
There are also two kinds of SQL injection vulnerabilities found on the Super Veda
application by Subgraph Vega before ReppSi deployment including MySQL Error Detected
- Possible SQL Injection and SQL Injection.
Description by Vega [42]: Vega has detected a SQL error string known to be output by
MySQL. This can indicate a possible SQL injection vulnerability. These vulnerabilities are
present when externally-supplied input is used to construct a SQL query. If precautions are
not taken, the externally-supplied input (usually a GET or POST parameter) can modify
the query string such that it performs unintented actions. These actions include gaining
unauthorized read or write access to the data stored in the database, as well as modifying
the logic of the application.
Affected URLs:
1. http://172.16.1.101/addcomment.jsp
2. http://172.16.1.101/dosearch.jsp
3. http://172.16.1.101/login.jsp
APPENDIX C. RAW RESULTS OUTPUT 150
4. http://172.16.1.101/postcomment.jsp
5. http://172.16.1.101/proddetails.jsp
6. http://172.16.1.101/recoverpasswordsend.jsp
7. http://172.16.1.101/showproducts.jsp
Figure C.57: The MySQL Error Detected - Possible SQL Injection alert of Super Veda
Figure C.58: The response body of the MySQL Error Detected - Possible SQL Injection
alert
APPENDIX C. RAW RESULTS OUTPUT 151
Description by Vega [42]: Vega has detected a possible SQL injection vulnerability.
These vulnerabilities are present when externally-supplied input is used to construct a
SQL query. If precautions are not taken, the externally-supplied input (usually a GET or
POST parameter) can modify the query string such that it performs unintented actions.
These actions include gaining unauthorized read or write access to the data stored in the
database, as well as modifying the logic of the application.
Affected URLs:
1. http://172.16.1.101/addcomment.jsp
2. http://172.16.1.101/dosearch.jsp
3. http://172.16.1.101/login.jsp
4. http://172.16.1.101/postcomment.jsp
5. http://172.16.1.101/proddetails.jsp
6. http://172.16.1.101/recoverpasswordsend.jsp
7. http://172.16.1.101/showproducts.jsp
Source Code
This section presents Java source code of the ReppSi system that consists of five classes
including:
• ReverseProxy.java
• TrafficInterceptor.java
• SuspiciousInputDetectionEngine.java
• TxtLogger.java
• TxtLogFormatter.java
156
APPENDIX D. SOURCE CODE
D.1 ReverseProxy.java System . out . p r i n t ( ” O p e r a t i o n Mode ( P r o f i l i n g = 0 ,
Protection = 1) : ” ) ;
try {
package ReppSi ; S t r i n g i n p u t = br . r e a d L i n e ( ) ;
while ( ! i n p u t . e q u a l s ( ” 0 ” ) && ! i n p u t . e q u a l s ( ” 1 ” ) ) {
import j a v a . i o . B u f f e r e d R e a d e r ; System . out . p r i n t ( ”Wrong i n p u t . P l e a s e e n t e r t h e
import j a v a . i o . IOException ; o p e r a t i o n mode a g a i n : ” ) ;
import j a v a . i o . InputStreamReader ; i n p u t = br . r e a d L i n e ( ) ;
}
import com . p r e d i c 8 . membrane . c o r e . HttpRouter ; mode = I n t e g e r . p a r s e I n t ( i n p u t ) ;
import com . p r e d i c 8 . membrane . c o r e . r u l e s . S e r v i c e P r o x y ; } catch ( NumberFormatException e1 ) {
import com . p r e d i c 8 . membrane . c o r e . r u l e s . S e r v i c e P r o x y K e y ; e1 . p r i n t S t a c k T r a c e ( ) ;
} catch ( IOException e1 ) {
public c l a s s ReverseProxy { e1 . p r i n t S t a c k T r a c e ( ) ;
}
public f i n a l s t a t i c TxtLogger LOGGER = new TxtLogger ( ) ; i f ( mode == 0 ) LOGGER. p r i n t L o g ( TxtLogger . INFO ,
” O p e r a t i o n Mode : P r o f i l i n g ” ) ;
public s t a t i c void main ( S t r i n g [ ] a r g s ) { e l s e LOGGER. p r i n t L o g ( TxtLogger . INFO , ” O p e r a t i o n
Mode : P r o t e c t i o n ” ) ;
// l i s t e n i n g p o r t o f t h e p r o x y
int l i s t e n P o r t = 8100; // i n i t i a l c o n f i g u r a t i o n o f t h e p r o x y
S e r v i c e P r o x y K e y key = new S e r v i c e P r o x y sp = new S e r v i c e P r o x y ( key , t a r g e t H o s t ,
ServiceProxyKey ( l i s t e n P o r t ) ; targetPort ) ;
sp . g e t I n t e r c e p t o r s ( ) . add (new
// t a r g e t h o s t t h a t t h e p r o x y w i l l f o r w a r d t r a f f i c t o T r a f f i c I n t e r c e p t o r ( mode , t a r g e t H o s t , s i d e ) ) ;
String targetHost = ” 172.16.1.101 ” ;
int t a r g e t P o r t = 8 0 ; HttpRouter r o u t e r = new HttpRouter ( ) ;
LOGGER. p r i n t L o g ( TxtLogger . INFO , ” P r o t e c t e d Web try {
Server : ” + targetHost + ” : ” + targetPort ) ; r o u t e r . add ( sp ) ;
router . i n i t () ;
S u s p i c i o u s I n p u t D e t e c t i o n E n g i n e s i d e = new } catch ( E x c e p t i o n e ) {
SuspiciousInputDetectionEngine ( targetHost ) ; e . printStackTrace () ;
side . init () ; }
}
// c h o o s e mode : P r o f i l i n g = 0 , P r o t e c t i o n = 1
i n t mode = 0 ; }
B u f f e r e d R e a d e r br = new B u f f e r e d R e a d e r (new
157
InputStreamReader ( System . i n ) ) ;
APPENDIX D. SOURCE CODE
D.2 TrafficInterceptor.java i f ( mode == 1 ) {
// i n s p e c t o n l y t h e s e r v e r −s i d e programming r e q u e s t
i f ( i s S u p p o r t F i l e T y p e ( exchange . g e t R e q u e s t ( ) ) ) {
package ReppSi ; // i f t h e r e q u e s t i s s u s p i c i o u s , b l o c k t h e
r e q u e s t and r e t u r n an e r r o r page
import com . p r e d i c 8 . membrane . c o r e . exchange . Exchange ; i f ( s i d e . i s S u s p i c i o u s R e q u e s t ( exchange . g e t R e q u e s t ( ) ,
import com . p r e d i c 8 . membrane . c o r e . h t t p . Header ; exchange . getRemoteAddrIp ( ) ) ) {
import com . p r e d i c 8 . membrane . c o r e . h t t p . Request ; c r e a t e E r r o r R e s p o n s e ( exchange ) ;
import com . p r e d i c 8 . membrane . c o r e . h t t p . Response ; return Outcome .RETURN;
import }
com . p r e d i c 8 . membrane . c o r e . h t t p . Response . R e s p o n s e B u i l d e r ; }
import }
com . p r e d i c 8 . membrane . c o r e . i n t e r c e p t o r . A b s t r a c t I n t e r c e p t o r ; return Outcome .CONTINUE;
import com . p r e d i c 8 . membrane . c o r e . i n t e r c e p t o r . Outcome ; }
public c l a s s T r a f f i c I n t e r c e p t o r extends // h a n d l e t h e h t t p r e s p o n s e
AbstractInterceptor { @Override
public Outcome h a n d l e R e s p o n s e ( Exchange exchange ) {
// o p e r a t i o n mode ( P r o f i l i n g = 0 , P r o t e c t i o n = 1) // l e a r n i n g p h a s e − l o g r e q u e s t s
private i n t mode ; i f ( mode == 0 ) {
// i f t h e r e q u e s t g e t 200 or 300 r e s p o n s e code and
private S u s p i c i o u s I n p u t D e t e c t i o n E n g i n e s i d e ; u s e s s e r v e r −s i d e programming , l o g t h e r e q u e s t
for creating a profile
public T r a f f i c I n t e r c e p t o r ( i n t mode , S t r i n g // i g n o r e s t a t i c page such as html , j p g , png , mp3 ,
protectedServer , SuspiciousInputDetectionEngine mp4 , e t c .
side ) { i f ( exchange . g e t R e s p o n s e ( ) . g e t S t a t u s C o d e ( ) < 400 &&
super ( ) ; i s S u p p o r t F i l e T y p e ( exchange . g e t R e q u e s t ( ) ) ) {
t h i s . mode = mode ; // l o g r e q u e s t s t o t h e d a t a b a s e and u p d a t e
this . s i d e = s i d e ; profiles
s i d e . l o g R e q u e s t ( exchange . g e t R e q u e s t ( ) ) ;
i f ( mode == 0 ) s i d e . i n i t P r o f i l i n g ( ) ; }
else side . i n i t P r o t e c t i o n () ; }
} // p r o t e c t i o n p h a s e − r e t u r n an e r r o r page i f s t a t u s
code = 4 xx or 5 xx
// h a n d l e t h e h t t p r e q u e s t else {
@Override i f ( exchange . g e t R e s p o n s e ( ) . g e t S t a t u s C o d e ( ) >= 4 0 0 ) {
public Outcome h a n d l e R e q u e s t ( Exchange exchange ) {
158
c r e a t e E r r o r R e s p o n s e ( exchange ) ;
// p r o t e c t i o n p h a s e
APPENDIX D. SOURCE CODE
} margin−top : 10 px ; } ”
} + ”p { c o l o r : #505761; f o n t −s i z e : 12 px ;
return Outcome .CONTINUE; f o n t −f a m i l y : \” Lucida Grande \ ” , A r i a l ,
} sans − s e r i f ; f o n t −w e i g h t : normal ; margin−top :
1 0 ; l i n e −h e i g h t : 20 px ; } ”
// c h e c k w h e t h e r t h e r e q u e s t u s e s s e r v e r −s i d e + ” h1 { c o l o r : #505761; f o n t −s i z e : 30 px ;
programming f o n t −f a m i l y : \” Lucida Grande \ ” , A r i a l ,
// t h i s p r o x y s u p p o r t s asp , aspx , j s p , php , and j s sans − s e r i f ; f o n t −w e i g h t : b o l d ; l e t t e r −s p a c i n g :
private boolean i s S u p p o r t F i l e T y p e ( Request r e q u e s t ) { 0px ; width : auto ; } ”
String url = getUrl ( request ) ; + ” h2 { c o l o r : #505761; f o n t −s i z e : 16 px ;
i f ( u r l . matches ( ” ( ˆ / . + \ \ . ( asp | aspx | j s p | php | j s ) $ ) | ( ˆ / [ ˆ \ \ . ] ∗ ) ” ) ) f o n t −f a m i l y : \” Lucida Grande \ ” , A r i a l ,
return true ; sans − s e r i f ; f o n t −w e i g h t : b o l d ; margin : 0 . 8 3 em
e l s e return f a l s e ; 0 0 ; }”
} + ”−−></s t y l e >”
+ ”</head>”
// c r e a t e an e r r o r page + ”<body>”
private void c r e a t e E r r o r R e s p o n s e ( Exchange exchange ) { + ”<d i v i d =\” o u t l i n e \”>”
R e s p o n s e B u i l d e r e r r o r = Response . ok ( ) ; + ”<img
e r r o r . contentType ( ” t e x t / html ” ) ; s r c =\” h t t p : / /www. bath . ac . uk/ m a r k e t i n g / images / v i s u a l i d / l o g o s l a t e . j p g \”
e r r o r . body ( ” <!DOCTYPE html PUBLIC \”−//W3C//DTD a l t =\”\” h e i g h t =\”85\” width =\”180\”
XHTML 1 . 0 T r a n s i t i o n a l //EN\” b o r d e r =\”0\” />”
\” h t t p : / /www. w3 . o r g /TR/ xhtml1 /DTD/ xhtml1−t r a n s i t i o n a l . dtd\”>” + ”<d i v i d =\” t i t l e \”>”
+ ”<html xmlns=\” h t t p : / /www. w3 . o r g /1999/ xhtml\”>” + ”<h1>Error </h1>”
+ ”<head>” + ”</div>”
+ ”<meta http−e q u i v =\” c o n t e n t −t y p e \” + ”<d i v i d =\” t e x t \”>”
c o n t e n t =\” t e x t / html ; c h a r s e t=u t f −8\” />” + ”<h2>S u s p i c i o u s Request D e t e c t e d ! ! < / h2>”
+ ”<meta name=\” g e n e r a t o r \” c o n t e n t =\”Adobe + ”<p>This page can ’ t be d i s p l a y e d . Contact IT
GoLive \” />” s u p p o r t f o r a d d i t i o n a l i n f o r m a t i o n . </p>”
+ ”< t i t l e >Error </ t i t l e >” + ”</div>”
+ ”< s t y l e t y p e =\” t e x t / c s s \” media=\” s c r e e n \”><!−−” + ”</div>”
+ ”#o u t l i n e { p o s i t i o n : r e l a t i v e ; h e i g h t : 250 px ; + ”</body>”
width : 300 px ; margin : 18 px auto 0 ; b o r d e r : + ”</html>” ) ;
s o l i d 2px #505761; } ” S tr in g contentEncoding =
+ ”#t i t l e { l e f t : 10 px ; width : 300 px ; top : 70 px ; exchange . g e t R e q u e s t ( ) . g e t H e a d e r ( ) . g e t C o n t e n t E n c o d i n g ( ) ;
p o s i t i o n : a b s o l u t e ; v i s i b i l i t y : v i s i b l e ; }” i f ( c o n t e n t E n c o d i n g != n u l l )
+ ”#t e x t { l e f t : 10 px ; top : 120 px ; p o s i t i o n : e r r o r . h e a d e r ( Header .CONTENT ENCODING,
159
a b s o l u t e ; width : 300 px ; v i s i b i l i t y : v i s i b l e ; contentEncoding ) ;
APPENDIX D. SOURCE CODE
exchange . s e t R e s p o n s e ( e r r o r . b u i l d ( ) ) ;
}
// r e t u r n r e q u e s t URL e . g . / l o g i n . php
private S t r i n g g e t U r l ( Request r e q u e s t ) {
i n t qmark = r e q u e s t . g e t U r i ( ) . i n d e x Of ( ” ? ” ) ;
i f ( qmark < 0 ) return r e q u e s t . g e t U r i ( ) ;
e l s e return r e q u e s t . g e t U r i ( ) . s u b s t r i n g ( 0 , qmark ) ;
}
160
APPENDIX D. SOURCE CODE
D.3 SuspiciousInputDetectionEngine.java public void i n i t ( ) {
p r e I n s e r t L o g = null ;
p r e S e l e c t P r o f i l e 1 = null ;
package ReppSi ; p r e S e l e c t P r o f i l e 2 = null ;
r e s u l t S e t = null ;
import j a v a . i o . U nsupp ortedEnc odi ngExc ept ion ;
import j a v a . n e t . URLDecoder ; requestNumber = 1 ;
import java . s q l . Connection ;
import j a v a . s q l . DatabaseMetaData ; try {
import j a v a . s q l . DriverManager ; // c r e a t e c o n n e c t i o n t o t h e d a t a b a s e
import java . s q l . PreparedStatement ; C l a s s . forName ( ”com . mysql . j d b c . D r i v e r ” ) ;
import java . s q l . ResultSet ; connection =
import j a v a . s q l . SQLException ; DriverManager . g e t C o n n e c t i o n ( ” j d b c : mysql : / / l o c a l h o s t : 8 8 8 9 / r e s e a r c h ” ,
import j a v a . s q l . Statement ; ” r o o t ” , ” password ” ) ;
import j a v a . s q l . Types ; } catch ( SQLException ex ) {
import j a v a . u t i l . HashMap ; ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
import j a v a . u t i l . Map ; ” SQLException : ” + ex . g e t M e s s a g e ( ) ) ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
import com . p r e d i c 8 . membrane . c o r e . h t t p . H e a d e r F i e l d ; ” SQLState : ” + ex . getSQLState ( ) ) ;
import com . p r e d i c 8 . membrane . c o r e . h t t p . Request ; } catch ( E x c e p t i o n e ) {
e . printStackTrace () ;
public c l a s s S u s p i c i o u s I n p u t D e t e c t i o n E n g i n e { }
private S t r i n g p r o t e c t e d S e r v e r ; // c r e a t e a l o g g i n g d a t a b a s e and/ or a p r o f i l i n g
d a t a b a s e i f n o t e x i s t e d / a l s o perform p r o f i l e
private C o n n e c t i o n c o n n e c t i o n ; updating
private P r e p a r e d S t a t e m e n t p r e I n s e r t L o g ; prepareDatabase ( ) ;
private P r e p a r e d S t a t e m e n t p r e S e l e c t P r o f i l e 1 ,
preSelectProfile2 ; }
private R e s u l t S e t r e s u l t S e t ;
public void i n i t P r o f i l i n g ( ) {
private i n t requestNumber ; Statement s t a t e m e n t = n u l l ;
ResultSet r e s u l t S e t = null ;
public S u s p i c i o u s I n p u t D e t e c t i o n E n g i n e ( S t r i n g try {
protectedServer ) { // a s s i g n a r e q u e s t number t o t h e h t t p r e q u e s t
this . protectedServer = protectedServer ; statement = connection . createStatement ( ) ;
}
161
APPENDIX D. SOURCE CODE
r e s u l t S e t = s t a t e m e n t . e x e c u t e Q u e r y ( ”SELECT S t r i n g s e l e c t P r o f i l e = ”SELECT
MAX( Req ) FROM ‘ ” + p r o t e c t e d S e r v e r + ”−l o g ‘ ” ) ; GET, POST, OtherMethods , Name , Type , Max , Min , A l l o w e d S p e c i a l C h a r a c t e r s
i f ( r e s u l t S e t . n e x t ( ) ) requestNumber = FROM ‘ ” + p r o t e c t e d S e r v e r + ”− p r o f i l e ‘ ”
resultSet . getInt (1) + 1; + ”WHERE URL=? OR (URL=? AND Name=?)” ;
preSelectProfile1 =
//SQL s t a t e m e n t f o r i n s e r t i n g t h e h t t p r e q u e s t t o connection . prepareStatement ( s e l e c t P r o f i l e ) ;
the database preSelectProfile2 =
S t r i n g i n s e r t L o g = ”INSERT INTO ‘ ” + connection . prepareStatement ( s e l e c t P r o f i l e ) ;
p r o t e c t e d S e r v e r + ”−l o g ‘ ( Req , URL, Method , } catch ( SQLException ex ) {
Name , Value , Type , Length , i s C h e c k ) ” + ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
”VALUES ( ? , ? , ? , ? , ? , ? , ? , ’ 0 ’ ) ” ; ” SQLException : ” + ex . g e t M e s s a g e ( ) ) ;
preInsertLog = ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
connection . prepareStatement ( insertLog ) ; ” SQLState : ” + ex . getSQLState ( ) ) ;
} catch ( E x c e p t i o n e ) {
} catch ( SQLException ex ) { e . printStackTrace () ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, }
” SQLException : ” + ex . g e t M e s s a g e ( ) ) ; }
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
” SQLState : ” + ex . getSQLState ( ) ) ; // p r e p a r e a d a t a b a s e f o r l o g g i n g and p r o f i l i n g
} catch ( E x c e p t i o n e ) { private void p r e p a r e D a t a b a s e ( ) {
e . printStackTrace () ; Statement c r e a t e L o g = n u l l ;
} finally { Statement c r e a t e P r o f i l e = n u l l ;
try { ResultSet l o g S e t = null ;
i f ( r e s u l t S e t != n u l l ) r e s u l t S e t . c l o s e ( ) ; ResultSet p r o f i l e S e t = null ;
i f ( s t a t e m e n t != n u l l ) s t a t e m e n t . c l o s e ( ) ;
} catch ( SQLException ex ) { PreparedStatement p r e I n s e r t P r o f i l e = null ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, PreparedStatement p r e U p d a t e P r o f i l e 1 = null ;
” SQLException : ” + ex . g e t M e s s a g e ( ) ) ; PreparedStatement p r e U p d a t e P r o f i l e 2 = null ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, PreparedStatement p r e S e l e c t P r o f i l e = null ;
” SQLState : ” + ex . getSQLState ( ) ) ;
} i n t numberOfRecordsUpdated = 0 ;
}
} try {
// c h e c k w h e t h e r t h e d a t a b a s e f o r l o g g i n g e x i s t s
public void i n i t P r o t e c t i o n ( ) { DatabaseMetaData md = c o n n e c t i o n . getMetaData ( ) ;
try { l o g S e t = md . g e t T a b l e s ( null , null , ” ‘ ” +
162
//SQL s t a t e m e n t f o r s e l e c t i n g profiles p r o t e c t e d S e r v e r + ”−l o g ‘ ” , n u l l ) ;
APPENDIX D. SOURCE CODE
+ ”URL v a r c h a r ( 2 5 5 ) , ”
// c r e a t e a d a t a b a s e f o r l o g g i n g i f n o t e x i s t e d + ”GET b o o l e a n , ”
i f ( ! l o g S e t . next ( ) ) { + ”POST b o o l e a n , ”
createLog = connection . createStatement () ; + ” OtherMethods b o o l e a n , ”
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . INFO , + ”Name v a r c h a r ( 2 5 5 ) , ”
” Creating a table ‘ ” + protectedServer + + ”Type v a r c h a r ( 2 5 5 ) , ”
”−l o g ‘ f o r l o g g i n g HTTP r e q u e s t s . ” ) ; // ∗∗∗∗∗ + ”Max i n t , ”
S t r i n g c r e a t e = ”CREATE TABLE ‘ ” + + ”Min i n t , ”
p r o t e c t e d S e r v e r + ”−l o g ‘ ( ” + ” AllowedSpecialCharacters varchar (255) ) ” ;
+ ”Req i n t , ” c r e a t e P r o f i l e . executeUpdate ( c r e a t e ) ;
+ ”URL v a r c h a r ( 2 5 5 ) , ” ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . INFO ,
+ ”Method v a r c h a r ( 2 5 5 ) , ” ” Table ‘ ” + p r o t e c t e d S e r v e r + ”− p r o f i l e ‘
+ ”Name v a r c h a r ( 2 5 5 ) , ” i s r e a d y . ” ) ; // ∗∗∗∗∗
+ ” Value v a r c h a r ( 2 5 5 ) , ” }
+ ”Type v a r c h a r ( 2 5 5 ) , ” profileSet . close () ;
+ ” Length i n t , ”
+ ” isCheck boolean ) ” ; // s t a r t p r o f i l e u p d a t i n g
createLog . executeUpdate ( c r e a t e ) ; long s t a r t T i m e = System . c u r r e n t T i m e M i l l i s ( ) ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . INFO , ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . INFO ,
” Table ‘ ” + p r o t e c t e d S e r v e r + ”−l o g ‘ i s ” S t a r t p r o f i l e s u p d a t i n g . . . ” ) ; // ∗∗∗∗∗
r e a d y . ” ) ; // ∗∗∗∗∗
} //SQL s t a t e m e n t f o r i n s e r t i n g a new p r o f i l e t o
// i f e x i s t e d , u p d a t e p r o f i l e the database
else { S t r i n g i n s e r t P r o f i l e = ”INSERT INTO ‘ ” +
c r e a t e P r o f i l e = connection . createStatement () ; p r o t e c t e d S e r v e r + ”− p r o f i l e ‘ (URL, GET,
POST, OtherMethods , Name , Type , Max , Min ,
// c h e c k w h e t h e r t h e p r o f i l e d a t a b a s e e x i s t s AllowedSpecialCharacters ) ” +
p r o f i l e S e t = md . g e t T a b l e s ( null , null , ” ‘ ” + ”VALUES ( ? , ? , ? , ? , ? , ? , ? , ? , ? ) ” ;
p r o t e c t e d S e r v e r + ”− p r o f i l e ‘ ” , n u l l ) ; preInsertProfile =
connection . prepareStatement ( i n s e r t P r o f i l e ) ;
// c r e a t e t h e p r o f i l e d a t a b a s e i f n o t e x i s t e d
i f ( ! p r o f i l e S e t . next ( ) ) { //SQL s t a t e m e n t f o r u p d a t i n g an e x i s t i n g p r o f i l e
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . INFO , in the database
” Creating a table ‘ ” + protectedServer + S t r i n g u p d a t e P r o f i l e 1 = ”UPDATE ‘ ” +
”− p r o f i l e ‘ f o r p r o f i l i n g ” ) ; // ∗∗∗∗∗ p r o t e c t e d S e r v e r + ”− p r o f i l e ‘ SET GET=? ,
S t r i n g c r e a t e = ”CREATE TABLE ‘ ” + POST=? , OtherMethods =? , Name=? , Type=? ,
163
p r o t e c t e d S e r v e r + ”− p r o f i l e ‘ ( ” Max=? , Min=? , A l l o w e d S p e c i a l C h a r a c t e r s =? ”
APPENDIX D. SOURCE CODE
+ ”WHERE URL=? AND (Name=? OR (Name I S NULL // u p d a t e p r o f i l e f o r t h e h t t p r e q u e s t w i t h o u t
AND ? I S NULL) ) ” ; any parameter
preUpdateProfile1 = i f ( p r o f i l e S e t . wasNull ( ) ) {
connection . prepareStatement ( updateProfile1 ) ; // p r o f i l e has a l r e a d y e x i s t e d
i f ( tempSet . n e x t ( ) ) {
S t r i n g u p d a t e P r o f i l e 2 = ”UPDATE ‘ ” + // s e t GET
p r o t e c t e d S e r v e r + ”− p r o f i l e ‘ SET GET=? , i f ( p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”GET” )
POST=? , OtherMethods=? ” && tempSet . g e t I n t ( ”GET” ) == 0 ) {
+ ”WHERE URL=? AND (Name=? OR (Name I S NULL preUpdateProfile2 . s e t I n t (1 , 1) ;
AND ? I S NULL) ) ” ; preUpdateProfile2 . s e t I n t (2 , 0) ;
preUpdateProfile2 = preUpdateProfile2 . s e t I n t (3 , 0) ;
connection . prepareStatement ( updateProfile2 ) ; preUpdateProfile2 . setString (4 ,
p r o f i l e S e t . g e t S t r i n g ( ”URL” ) ) ;
//SQL s t a t e m e n t f o r s e l e c t i n g p r o f i l e s preUpdateProfile2 . setString (5 ,
S t r i n g s e l e c t P r o f i l e = ”SELECT p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ;
GET, POST, OtherMethods , Name , Type , Max , Min , A l l o w e d S p e c i a l C h a r a c t e r sp r e U p d a t e P r o f i l e 2 . s e t S t r i n g ( 6 ,
FROM ‘ ” + p r o t e c t e d S e r v e r + ”− p r o f i l e ‘ ” p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ;
+ ”WHERE URL=? AND (Name=? OR (Name I S NULL pr eUp dat ePro fil e2 . executeUpdate ( ) ;
AND ? I S NULL) ) ” ; numberOfRecordsUpdated++;
preSelectProfile = }
connection . prepareStatement ( s e l e c t P r o f i l e ) ; // s e t POST
i f ( p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”POST” )
// f i n d t h e h t t p l o g s t h a t haven ’ t u p d a t e d t h e && tempSet . g e t I n t ( ”POST” ) == 0 ) {
p r o f i l e yet preUpdateProfile2 . s e t I n t (1 , 0) ;
p r o f i l e S e t = c r e a t e P r o f i l e . e x e c u t e Q u e r y ( ”SELECT preUpdateProfile2 . s e t I n t (2 , 1) ;
URL, Method , Name , Value , Type , Length FROM ‘ ” + preUpdateProfile2 . s e t I n t (3 , 0) ;
p r o t e c t e d S e r v e r + ”−l o g ‘ WHERE i s C h e c k = ’0 ’ ” ) ; preUpdateProfile2 . setString (4 ,
R e s u l t S e t tempSet = n u l l ; p r o f i l e S e t . g e t S t r i n g ( ”URL” ) ) ;
while ( p r o f i l e S e t . n e x t ( ) ) { preUpdateProfile2 . setString (5 ,
preSelectProfile . setString (1 , p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ;
p r o f i l e S e t . g e t S t r i n g ( ”URL” ) ) ; preUpdateProfile2 . setString (6 ,
preSelectProfile . setString (2 , p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ;
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ; pr eUp dat ePro fil e2 . executeUpdate ( ) ;
preSelectProfile . setString (3 , numberOfRecordsUpdated++;
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ; }
tempSet = p r e S e l e c t P r o f i l e . e x e c u t e Q u e r y ( ) ; // s e t OtherMethods
164
APPENDIX D. SOURCE CODE
i f ( ! p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”GET” ) }
&& }
! p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”POST” ) p r e I n s e r t P r o f i l e . s e t N u l l ( 5 , Types .NULL) ;
&& tempSet . g e t I n t ( ” OtherMethods ” ) == p r e I n s e r t P r o f i l e . s e t N u l l ( 6 , Types .NULL) ;
0) { p r e I n s e r t P r o f i l e . s e t N u l l ( 7 , Types .NULL) ;
preUpdateProfile2 . s e t I n t (1 , 0) ; p r e I n s e r t P r o f i l e . s e t N u l l ( 8 , Types .NULL) ;
preUpdateProfile2 . s e t I n t (2 , 0) ; p r e I n s e r t P r o f i l e . s e t N u l l ( 9 , Types .NULL) ;
preUpdateProfile2 . s e t I n t (3 , 1) ; p r e I n s e r t P r o f i l e . executeUpdate ( ) ;
preUpdateProfile2 . setString (4 , numberOfRecordsUpdated++;
p r o f i l e S e t . g e t S t r i n g ( ”URL” ) ) ; }
preUpdateProfile2 . setString (5 , }
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ;
preUpdateProfile2 . setString (6 , // u p d a t e p r o f i l e f o r t h e h t t p r e q u e s t t h a t has
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ; a t l e a s t one parameter
pr eUp date Pro fil e2 . executeUpdate ( ) ; else {
numberOfRecordsUpdated++; // p r o f i l e has a l r e a d y e x i s t e d
} i f ( tempSet . n e x t ( ) ) {
} // s e t GET
// p r o f i l e hasn ’ t been c r e a t e d y e t i f ( p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”GET” ) )
else { preUpdateProfile1 . s e t I n t (1 , 1) ;
p r e I n s e r t P r o f i l e . setString (1 , else preUpdateProfile1 . s e t I n t (1 ,
p r o f i l e S e t . g e t S t r i n g ( ”URL” ) ) ; tempSet . g e t I n t ( ”GET” ) ) ;
i f ( p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”GET” ) )
{ // s e t POST
p r e I n s e r t P r o f i l e . s e t I n t (2 , 1) ; i f ( p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”POST” ) )
p r e I n s e r t P r o f i l e . s e t I n t (3 , 0) ; preUpdateProfile1 . s e t I n t (2 , 1) ;
p r e I n s e r t P r o f i l e . s e t I n t (4 , 0) ; else preUpdateProfile1 . s e t I n t (2 ,
} else { tempSet . g e t I n t ( ”POST” ) ) ;
i f ( p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”POST” ) )
{ // s e t OtherMethods
p r e I n s e r t P r o f i l e . s e t I n t (2 , 0) ; i f ( ! p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”GET” )
p r e I n s e r t P r o f i l e . s e t I n t (3 , 1) ; &&
p r e I n s e r t P r o f i l e . s e t I n t (4 , 0) ; ! p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”POST” ) )
} else { preUpdateProfile1 . s e t I n t (3 , 1) ;
p r e I n s e r t P r o f i l e . s e t I n t (2 , 0) ; else preUpdateProfile1 . s e t I n t (3 ,
p r e I n s e r t P r o f i l e . s e t I n t (3 , 0) ; tempSet . g e t I n t ( ” OtherMethods ” ) ) ;
165
p r e I n s e r t P r o f i l e . s e t I n t (4 , 1) ;
APPENDIX D. SOURCE CODE
// s e t Name and o t h e r s }
tempSet . g e t S t r i n g ( ”Name” ) ; // p r o f i l e hasn ’ t been c r e a t e d y e t
i f ( tempSet . wasNull ( ) ) { else {
preUpdateProfile1 . setString (4 , p r e I n s e r t P r o f i l e . setString (1 ,
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ; p r o f i l e S e t . g e t S t r i n g ( ”URL” ) ) ;
preUpdateProfile1 . setString (5 , i f ( p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”GET” ) )
p r o f i l e S e t . g e t S t r i n g ( ”Type” ) ) ; {
preUpdateProfile1 . setInt (6 , p r e I n s e r t P r o f i l e . s e t I n t (2 , 1) ;
p r o f i l e S e t . g e t I n t ( ” Length ” ) ) ; p r e I n s e r t P r o f i l e . s e t I n t (3 , 0) ;
preUpdateProfile1 . setInt (7 , p r e I n s e r t P r o f i l e . s e t I n t (4 , 0) ;
p r o f i l e S e t . g e t I n t ( ” Length ” ) ) ; }
preUpdateProfile1 . setString (8 , else {
g e t S p e c i a l C h a r a c t e r I n V a l u e ( p r o f i l e S e t . g e t S t r i n g ( ” Value ” )i)f)(;p r o f i l e S e t . g e t S t r i n g ( ”Method” ) . e q u a l s ( ”POST” ) )
} else { {
preUpdateProfile1 . setString (4 , p r e I n s e r t P r o f i l e . s e t I n t (2 , 0) ;
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ; p r e I n s e r t P r o f i l e . s e t I n t (3 , 1) ;
preUpdateProfile1 . setString (5 , p r e I n s e r t P r o f i l e . s e t I n t (4 , 0) ;
getNewType ( tempSet . g e t S t r i n g ( ”Type” ) , } else {
p r o f i l e S e t . g e t S t r i n g ( ”Type” ) ) ) ; p r e I n s e r t P r o f i l e . s e t I n t (2 , 0) ;
preUpdateProfile1 . setInt (6 , p r e I n s e r t P r o f i l e . s e t I n t (3 , 0) ;
Math . max( tempSet . g e t I n t ( ”Max” ) , p r e I n s e r t P r o f i l e . s e t I n t (4 , 1) ;
p r o f i l e S e t . g e t I n t ( ” Length ” ) ) ) ; }
preUpdateProfile1 . setInt (7 , }
Math . min ( tempSet . g e t I n t ( ”Min” ) , p r e I n s e r t P r o f i l e . setString (5 ,
p r o f i l e S e t . g e t I n t ( ” Length ” ) ) ) ; p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ;
preUpdateProfile1 . setString (8 , p r e I n s e r t P r o f i l e . setString (6 ,
g e t S p e c i a l C h a r a c t e r I n V a l u e ( tempSet . g e t S t r i n g ( ” A l l o w e d S p e c p i arloCfhi laerSa ec t e. rgse”t)S.tcroi n cga(t”Type”
( p r o f i)l)e ;S e t . g e t S t r i n g ( ” Value ” ) ) ) ) ;
} preI nsertProfi le . setInt (7 ,
p r o f i l e S e t . g e t I n t ( ” Length ” ) ) ;
preUpdateProfile1 . setString (9 , preI nsertProfi le . setInt (8 ,
p r o f i l e S e t . g e t S t r i n g ( ”URL” ) ) ; p r o f i l e S e t . g e t I n t ( ” Length ” ) ) ;
preUpdateProfile1 . setString (10 , p r e I n s e r t P r o f i l e . setString (9 ,
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ; g e t S p e c i a l C h a r a c t e r I n V a l u e ( p r o f i l e S e t . g e t S t r i n g ( ” Value ” ) ) ) ;
preUpdateProfile1 . setString (11 , p r e I n s e r t P r o f i l e . executeUpdate ( ) ;
p r o f i l e S e t . g e t S t r i n g ( ”Name” ) ) ; numberOfRecordsUpdated++;
pr eUp date Pro fil e1 . executeUpdate ( ) ; }
166
numberOfRecordsUpdated++; }
APPENDIX D. SOURCE CODE
} } catch ( SQLException ex ) {
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
//SQL s t a t e m e n t f o r c h a n g i n g parameter ’ i s C h e c k ’ ” SQLException : ” + ex . g e t M e s s a g e ( ) ) ;
to ’1 ’ a f t e r updating p r o f i l e s ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
c r e a t e P r o f i l e . e x e c u t e U p d a t e ( ”UPDATE ‘ ” + ” SQLState : ” + ex . getSQLState ( ) ) ;
p r o t e c t e d S e r v e r + ”−l o g ‘ SET i s C h e c k = ’1 ’ }
WHERE i s C h e c k = ’0 ’ ” ) ; }
long f i n i s h T i m e = System . c u r r e n t T i m e M i l l i s ( ) ; }
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . INFO ,
” P r o f i l e s u p d a t i n g i s done . ” + // l o g t h e incoming h t t p r e q u e s t
numberOfRecordsUpdated + ” p r o f i l e r e c o r d s public void l o g R e q u e s t ( Request r e q u e s t ) {
a r e updated . P r o c e s s i n g time i s ” + try {
( f i n i s h T i m e − s t a r t T i m e ) + ”ms” ) ; // ∗∗∗∗∗ Map<S t r i n g , S t r i n g > params =
getParameters ( request ) ;
} i f ( params . isEmpty ( ) ) {
} catch ( SQLException ex ) { p r e I n s e r t L o g . s e t I n t ( 1 , requestNumber ) ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, preInsertLog . setString (2 , getUrl ( request ) ) ;
” SQLException : ” + ex . g e t M e s s a g e ( ) ) ; preInsertLog . setString (3 , r e q u e s t . getMethod ( ) ) ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, p r e I n s e r t L o g . s e t N u l l ( 4 , Types .NULL) ;
” SQLState : ” + ex . getSQLState ( ) ) ; p r e I n s e r t L o g . s e t N u l l ( 5 , Types .NULL) ;
} catch ( E x c e p t i o n e ) { p r e I n s e r t L o g . s e t N u l l ( 6 , Types .NULL) ;
e . printStackTrace () ; p r e I n s e r t L o g . s e t N u l l ( 7 , Types .NULL) ;
} finally { p r e I n s e r t L o g . executeUpdate ( ) ;
try { } else {
i f ( l o g S e t != n u l l ) l o g S e t . c l o s e ( ) ; S t r i n g name ;
i f ( p r o f i l e S e t != n u l l ) p r o f i l e S e t . c l o s e ( ) ; String value ;
i f ( c r e a t e L o g != n u l l ) c r e a t e L o g . c l o s e ( ) ; f o r (Map . Entry<S t r i n g , S t r i n g > e n t r y :
i f ( c r e a t e P r o f i l e != n u l l ) c r e a t e P r o f i l e . c l o s e ( ) ; params . e n t r y S e t ( ) ) {
i f ( p r e S e l e c t P r o f i l e != n u l l ) name = e n t r y . getKey ( ) . t o S t r i n g ( ) ;
preSelectProfile . close () ; value = entry . getValue ( ) . t o S t r i n g ( ) ;
i f ( p r e I n s e r t P r o f i l e != n u l l )
preInsertProfile . close () ; p r e I n s e r t L o g . s e t I n t ( 1 , requestNumber ) ;
i f ( p r e U p d a t e P r o f i l e 1 != n u l l ) preInsertLog . setString (2 , getUrl ( request ) ) ;
preUpdateProfile1 . close () ; preInsertLog . setString (3 ,
i f ( p r e U p d a t e P r o f i l e 2 != n u l l ) r e q u e s t . getMethod ( ) ) ;
167
preUpdateProfile2 . close () ; p r e I n s e r t L o g . s e t S t r i n g ( 4 , name ) ;
APPENDIX D. SOURCE CODE
preInsertLog . setString (5 , value ) ; // c h e c k Method
preInsertLog . setString (6 , i f ( ( requestMethod . e q u a l s ( ”GET” ) &&
getValueType ( v a l u e ) ) ; r e s u l t S e t . g e t I n t ( ”GET” ) == 0 ) | |
preInsertLog . setInt (7 , value . length () ) ; ( requestMethod . e q u a l s ( ”POST” ) &&
p r e I n s e r t L o g . executeUpdate ( ) ; r e s u l t S e t . g e t I n t ( ”POST” ) == 0 ) | |
} ( ! requestMethod . e q u a l s ( ”GET” ) &&
} ! requestMethod . e q u a l s ( ”POST” ) &&
requestNumber++; r e s u l t S e t . g e t I n t ( ” OtherMethods ” ) == 0 ) ) {
} catch ( SQLException ex ) { ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . SEVERE,
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, ” U n a u t h o r i z e d Method f o r Known URL: ” +
” SQLException : ” + ex . g e t M e s s a g e ( ) ) ; requestMethod + ” \n IP : ” + i p +
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, getRequestInformation ( request ) ) ;
” SQLState : ” + ex . getSQLState ( ) ) ; i s S u s p i c i o u s ++;
} catch ( E x c e p t i o n e ) { }
e . printStackTrace () ; }
} // no p r o f i l e matched
} else {
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . SEVERE,
// r e t u r n t r u e i f t h e incomming HTTP r e q u e s t i s ” U n a u t h o r i z e d URL A c c e s s : ” + requestURL +
s u s p i c i o u s ( doesn ’ t match t h e p r o f i l e i n t h e ” \n IP : ” + i p +
database ) getRequestInformation ( request ) ) ;
public boolean i s S u s p i c i o u s R e q u e s t ( Request r e q u e s t , return true ;
String ip ) { }
int i s S u s p i c i o u s = 0 ; }
S t r i n g requestURL = g e t U r l ( r e q u e s t ) ; // i n s p e c t t h e h t t p r e q u e s t t h a t has a t l e a s t one
S t r i n g requestMethod = r e q u e s t . getMethod ( ) ; parameter
else {
Map<S t r i n g , S t r i n g > params = g e t P a r a m e t e r s ( r e q u e s t ) ; f o r (Map . Entry<S t r i n g , S t r i n g > e n t r y :
try { params . e n t r y S e t ( ) ) {
// i n s p e c t t h e h t t p r e q u e s t w i t h o u t any parameter p r e S e l e c t P r o f i l e 1 . s e t S t r i n g ( 1 , ”NULL” ) ;
i f ( params . isEmpty ( ) ) { p r e S e l e c t P r o f i l e 1 . s e t S t r i n g ( 2 , requestURL ) ;
p r e S e l e c t P r o f i l e 1 . s e t S t r i n g ( 1 , requestURL ) ; p r e S e l e c t P r o f i l e 1 . s e t S t r i n g ( 3 , e n t r y . getKey ( ) ) ;
p r e S e l e c t P r o f i l e 1 . s e t S t r i n g ( 2 , ”NULL” ) ; r e s u l t S e t = p r e S e l e c t P r o f i l e 1 . executeQuery ( ) ;
p r e S e l e c t P r o f i l e 1 . s e t S t r i n g ( 3 , ”NULL” ) ; // t h e r e q u e s t URL f u l l y matches t h e p r o f i l e
r e s u l t S e t = p r e S e l e c t P r o f i l e 1 . executeQuery ( ) ; (URL + Name)
// t h e r e q u e s t URL matches t h e p r o f i l e i f ( r e s u l t S e t . next ( ) ) {
168
i f ( r e s u l t S e t . next ( ) ) { // c h e c k Method
APPENDIX D. SOURCE CODE
i f ( ( requestMethod . e q u a l s ( ”GET” ) && > 0) {
r e s u l t S e t . g e t I n t ( ”GET” ) == 0 ) | | String spListFromProfile =
( requestMethod . e q u a l s ( ”POST” ) && resultSet . getString (” AllowedSpecialCharacters ”) ;
r e s u l t S e t . g e t I n t ( ”POST” ) == 0 ) | | String replacedValue = entry . getValue ( ) ;
( ! requestMethod . e q u a l s ( ”GET” ) && for ( int i = 0 ; i <
! requestMethod . e q u a l s ( ”POST” ) && s p L i s t F r o m P r o f i l e . l e n g t h ( ) ; i ++) {
r e s u l t S e t . g e t I n t ( ” OtherMethods ” ) == i f ( s p L i s t F r o m P r o f i l e . charAt ( i ) == ’ s ’ )
0) ) { {
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . SEVERE, replacedValue =
” U n a u t h o r i z e d Method f o r Known URL: ” r e p l a c e d V a l u e . r e p l a c e A l l ( ” \\ s ” ,
+ requestMethod + ” \n IP : ” + i p + ”0” ) ;
getRequestInformation ( request ) ) ; } else {
i s S u s p i c i o u s ++; replacedValue =
} r e p l a c e d V a l u e . r e p l a c e ( s p L i s t F r o m P r o f i l e . charAt ( i ) ,
’0 ’ ) ;
// c h e c k Type & A l l o w e d S p e c i a l C h a r a c t e r s }
S t r i n g requestValueType = }
getValueType ( e n t r y . g e t V a l u e ( ) ) ; replacedValue =
i f ( ! i s S u b s e t O f ( requestValueType , r e p l a c e d V a l u e . c o n c a t ( ”A0” ) ;
r e s u l t S e t . g e t S t r i n g ( ”Type” ) ) ) { i f ( getValueType ( r e p l a c e d V a l u e ) . e q u a l s ( ” A l l ” ) )
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . SEVERE, {
” Parameter Type V i o l a t i o n : ” + ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . SEVERE,
e n t r y . getKey ( ) + ”=” + ” Unauthorized S p e c i a l Character
entry . getValue ( ) + ” ( ” + f o r Parameter : ” + e n t r y . getKey ( )
r e s u l t S e t . g e t S t r i n g ( ”Type” ) + ” ) \n + ”=” + e n t r y . g e t V a l u e ( ) + ” ( ” +
IP : ” + i p + resultSet . getString (” AllowedSpecialCharacters ”)
getRequestInformation ( request ) ) ; + ” ) \n IP : ” + i p +
i s S u s p i c i o u s ++; getRequestInformation ( request ) ) ;
} else { i s S u s p i c i o u s ++;
i f ( ( requestValueType . e q u a l s ( ” S p e c i a l }
Characters ” ) | | }
requestValueType . e q u a l s ( ” Latin & }
Special Characters ” ) | |
r e q u e s t V a l u e T y p e . e q u a l s ( ” Numeric & // c h e c k Max & Min
Special Characters ” ) | | i f ( entry . getValue ( ) . length ( ) >
r e q u e s t V a l u e T y p e . e q u a l s ( ” A l l ” ) ) && r e s u l t S e t . g e t I n t ( ”Max” ) | |
169
r e s u l t S e t . g e t S t r i n g ( ” AllowedSpecialCharacters ” ) . length ( ) entry . getValue ( ) . length ( ) <
APPENDIX D. SOURCE CODE
r e s u l t S e t . g e t I n t ( ”Min” ) ) { }
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . SEVERE, }
” Parameter Value Length V i o l a t i o n : ” + }
e n t r y . getKey ( ) + ”=” + } catch ( SQLException ex ) {
entry . getValue ( ) + ” ( ” + ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
r e s u l t S e t . g e t S t r i n g ( ”Max” ) + ” , ” + ” SQLException : ” + ex . g e t M e s s a g e ( ) ) ;
r e s u l t S e t . g e t S t r i n g ( ”Min” ) + ” ) \n IP : ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING,
” + ip + ” SQLState : ” + ex . getSQLState ( ) ) ;
getRequestInformation ( request ) ) ; } catch ( E x c e p t i o n e ) {
i s S u s p i c i o u s ++; e . printStackTrace () ;
} }
}
// no p r o f i l e matched i f ( i s S u s p i c i o u s > 0 ) return true ;
else { e l s e return f a l s e ;
p r e S e l e c t P r o f i l e 2 . s e t S t r i n g ( 1 , requestURL ) ;
p r e S e l e c t P r o f i l e 2 . s e t S t r i n g ( 2 , ”NULL” ) ; }
p r e S e l e c t P r o f i l e 2 . s e t S t r i n g ( 3 , ”NULL” ) ;
R e s u l t S e t tempSet = // r e t u r n a t y p e o f t h e parameter v a l u e
p r e S e l e c t P r o f i l e 2 . executeQuery ( ) ; private S t r i n g getValueType ( S t r i n g v a l u e ) {
// t h e r e q u e s t URL p a r t i a l l y matches t h e int type = 0 ;
p r o f i l e (URL) i f ( v a l u e . l e n g t h ( ) == 0 ) return ” Blank ” ;
i f ( tempSet . n e x t ( ) ) { else {
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger .WARNING, i f ( v a l u e . matches ( ” . ∗ [ a−zA−Z ] . ∗ ” ) ) t y p e +=1;
”Unknown Parameter : ” + e n t r y . getKey ( ) i f ( v a l u e . matches ( ” . ∗ [ 0 − 9 ] . ∗ ” ) ) t y p e +=2;
+ ” \n IP : ” + i p + i f ( v a l u e . matches ( ” . ∗ [ \ \ s ; & \ \ + \ ” \ ’ \ \ ( \ \ )%<>\\\\/\\−#\\$ :@\\ˆ \ \ | \ \ . \ \ ∗ ! , ˜ \ \ [ \ \
getRequestInformation ( request ) ) ; t y p e +=4;
i s S u s p i c i o u s ++; switch ( t y p e ) {
} case 1 : return ” L a t i n C h a r a c t e r s ” ;
// t h e r e q u e s t URL doesn ’ t match even t h e URL case 2 : return ” Numeric ” ;
else { case 3 : return ” L a t i n C h a r a c t e r s & Numeric ” ;
ReverseProxy .LOGGER. p r i n t L o g ( TxtLogger . SEVERE, case 4 : return ” S p e c i a l C h a r a c t e r s ” ;
” U n a u t h o r i z e d URL A c c e s s : ” + case 5 : return ” L a t i n & S p e c i a l C h a r a c t e r s ” ;
requestURL + ” \n IP : ” + i p + case 6 : return ” Numeric & S p e c i a l C h a r a c t e r s ” ;
getRequestInformation ( request ) ) ; case 7 : return ” A l l ” ;
return true ; default : return ” L a t i n C h a r a c t e r s ” ;
} }
170
i f ( tempSet != n u l l ) tempSet . c l o s e ( ) ; }
APPENDIX D. SOURCE CODE
} i f ( typeOfProfile . equals (” All ”) | |
ty peOfRe quest . e q u a l s ( ” Blank ” ) ) return true ;
// combine 2 parameter t y p e s t o g e t h e r else {
private S t r i n g getNewType ( S t r i n g type1 , S t r i n g t y p e 2 ) { i f ( t ype OfR equ est . e q u a l s ( ” L a t i n C h a r a c t e r s ” ) &&
i f ( type1 . e q u a l s ( ” All ” ) | | type2 . e q u a l s ( ” All ” ) ) ( typeOfProfile . equals ( ” Latin Characters ” ) | |
return ” A l l ” ; typeOfProfile . equals ( ” Latin Characters &
else { Numeric ” ) | | t y p e O f P r o f i l e . e q u a l s ( ” L a t i n &
S t r i n g value1 = ”” ; S p e c i a l C h a r a c t e r s ” ) ) ) return true ;
i f ( t y p e 1 . e q u a l s ( ” L a t i n C h a r a c t e r s ” ) ) v a l u e 1 = ”A” ; i f ( t ype OfR equ es t . e q u a l s ( ” Numeric ” ) &&
i f ( t y p e 1 . e q u a l s ( ” Numeric ” ) ) v a l u e 1 = ” 0 ” ; ( t y p e O f P r o f i l e . e q u a l s ( ” Numeric ” ) | |
i f ( type1 . e q u a l s ( ” S p e c i a l Characters ” ) ) value1 = typeOfProfile . equals ( ” Latin Characters &
”!”; Numeric ” ) | | t y p e O f P r o f i l e . e q u a l s ( ” Numeric &
i f ( t y p e 1 . e q u a l s ( ” L a t i n C h a r a c t e r s & Numeric ” ) ) S p e c i a l C h a r a c t e r s ” ) ) ) return true ;
v a l u e 1 = ”A0” ; i f ( t ype OfR equ es t . e q u a l s ( ” S p e c i a l C h a r a c t e r s ” ) &&
i f ( type1 . e q u a l s ( ” Latin & S p e c i a l Characters ” ) ) ( typeOfProfile . equals ( ” Special Characters ” ) | |
v a l u e 1 = ”A! ” ; typeOfProfile . equals ( ” Latin & S p e c i a l
i f ( t y p e 1 . e q u a l s ( ” Numeric & S p e c i a l C h a r a c t e r s ” ) ) C h a r a c t e r s ” ) | | t y p e O f P r o f i l e . e q u a l s ( ” Numeric
value1 = ” 0! ” ; & S p e c i a l C h a r a c t e r s ” ) ) ) return true ;
S t r i n g value2 = ”” ; i f ( t ype OfR equ est . e q u a l s ( ” L a t i n C h a r a c t e r s &
i f ( t y p e 2 . e q u a l s ( ” L a t i n C h a r a c t e r s ” ) ) v a l u e 2 = ”A” ; Numeric ” ) && t y p e O f P r o f i l e . e q u a l s ( ” L a t i n
i f ( t y p e 2 . e q u a l s ( ” Numeric ” ) ) v a l u e 2 = ” 0 ” ; C h a r a c t e r s & Numeric ” ) ) return true ;
i f ( type2 . e q u a l s ( ” S p e c i a l Characters ” ) ) value2 = i f ( t ype OfR equ est . e q u a l s ( ” L a t i n & S p e c i a l
”!”; C h a r a c t e r s ” ) && t y p e O f P r o f i l e . e q u a l s ( ” L a t i n &
i f ( t y p e 2 . e q u a l s ( ” L a t i n C h a r a c t e r s & Numeric ” ) ) S p e c i a l C h a r a c t e r s ” ) ) return true ;
v a l u e 2 = ”A0” ; i f ( t ype OfR equ est . e q u a l s ( ” Numeric & S p e c i a l
i f ( type2 . e q u a l s ( ” Latin & S p e c i a l Characters ” ) ) C h a r a c t e r s ” ) && t y p e O f P r o f i l e . e q u a l s ( ” Numeric
v a l u e 2 = ”A! ” ; & S p e c i a l C h a r a c t e r s ” ) ) return true ;
i f ( t y p e 2 . e q u a l s ( ” Numeric & S p e c i a l C h a r a c t e r s ” ) ) return f a l s e ;
value2 = ” 0! ” ; }
return getValueType ( v a l u e 1 . c o n c a t ( v a l u e 2 ) ) ; }
}
} // r e t u r n a l i s t o f t h e s p e c i a l c h a r a c t e r s i n t h e v a l u e
private S t r i n g g e t S p e c i a l C h a r a c t e r I n V a l u e ( S t r i n g
// r e t u r n t r u e i f t y p e o f t h e r e q u e s t i s s u b s e t o f t y p e value ) {
of i t s p r o f i l e S t r i n g s p L i s t = ”” ;
private s t a t i c boolean i s S u b s e t O f ( S t r i n g i f ( v a l u e . matches ( ” . ∗ [ \ \ s ] . ∗ ” ) ) s p L i s t =
171
typeOfRequest , S t r i n g t y p e O f P r o f i l e ) { spList . concat ( ” s ” ) ;
APPENDIX D. SOURCE CODE
i f ( v a l u e . matches ( ” . ∗ [ ; ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ ] . ∗ ” ) ) s p L i s t =
spList . concat ( ” ; ” ) ; spList . concat ( ” ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ & ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ | ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ”&” ) ; spList . concat ( ” | ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ \ \ + ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ . ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ”+” ) ; spList . concat ( ” . ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ \ ” ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ ∗ ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ” \” ” ) ; s p L i s t . concat ( ”∗” ) ;
i f ( v a l u e . matches ( ” . ∗ [ \ ’ ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ ! ] . ∗ ” ) ) s p L i s t =
spList . concat ( ” \ ’ ” ) ; spList . concat ( ” ! ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ ( ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ ‘ ] . ∗ ” ) ) s p L i s t =
spList . concat ( ” ( ” ) ; spList . concat ( ” ‘ ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ ) ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ ˜ ] . ∗ ” ) ) s p L i s t =
spList . concat ( ” ) ” ) ; s p L i s t . concat ( ”˜” ) ;
i f ( v a l u e . matches ( ” . ∗ [ % ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ , ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ”%” ) ; spList . concat ( ” , ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ < ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ [ ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ”<” ) ; spList . concat ( ” [ ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ > ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ ] ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ”>” ) ; spList . concat ( ” ] ” ) ;
i f ( v a l u e . matches ( ” . ∗ [ \ \ \ \ ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ { ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ” \\ ” ) ; s p L i s t . concat ( ”{” ) ;
i f ( v a l u e . matches ( ” . ∗ [ / ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ } ] . ∗ ” ) ) s p L i s t =
s p L i s t . concat ( ”/” ) ; s p L i s t . concat ( ”}” ) ;
i f ( v a l u e . matches ( ” . ∗ [ \ \ − ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ = ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ”−” ) ; s p L i s t . c o n c a t ( ”=” ) ;
i f ( v a l u e . matches ( ” . ∗ [ # ] . ∗ ” ) ) s p L i s t = i f ( v a l u e . matches ( ” . ∗ [ \ \ ? ] . ∗ ” ) ) s p L i s t =
s p L i s t . c o n c a t ( ”#” ) ; spList . concat ( ”?” ) ;
i f ( v a l u e . matches ( ” . ∗ [ \ \ $ ] . ∗ ” ) ) s p L i s t = return s p L i s t ;
s p L i s t . concat ( ”$” ) ; }
i f ( v a l u e . matches ( ” . ∗ [ : ] . ∗ ” ) ) s p L i s t =
spList . concat ( ” : ” ) ; // r e t u r n parameter p a i r s ( name , v a l u e )
i f ( v a l u e . matches ( ” . ∗ [ @ ] . ∗ ” ) ) s p L i s t = private Map<S t r i n g , S t r i n g > g e t P a r a m e t e r s ( Request
s p L i s t . c o n c a t ( ”@” ) ; request ) {
i f ( v a l u e . matches ( ” . ∗ [ \ \ ˆ ] . ∗ ” ) ) s p L i s t = Map<S t r i n g , S t r i n g > p a r a m e t e r = new HashMap<S t r i n g ,
s p L i s t . concat ( ”ˆ” ) ; S t r i n g >() ;
172
S t r i n g method = r e q u e s t . getMethod ( ) ;
APPENDIX D. SOURCE CODE
S t r i n g [ ] p a i r s = null ; }
i f ( method . e q u a l s ( ”GET” ) ) {
i f ( r e q u e s t . g e t U r i ( ) . i n d e x Of ( ” ? ” ) < 0 | | // r e t u r n a l l h e a d e r f i e l d s o f t h e r e q u e s t ( name , v a l u e )
r e q u e s t . g e t U r i ( ) . i n d e x Of ( ”=” ) < 0 ) return private H e a d e r F i e l d [ ]
parameter ; g e t A l l R e q u e s t H e a d e r F i e l d s ( Request r e q u e s t ) {
else pairs = H e a d e r F i e l d f i e l d [ ] = new
r e q u e s t . getUri ( ) . s u b s t r i n g ( r e q u e s t . getUri ( ) . indexOf ( ”?” ) HeaderField [ r e q u e s t . getHeader ( ) . g e t A l l H e a d e r F i e l d s ( ) . l e n g t h ] ;
+ 1 ) . s p l i t ( ”&” ) ; System . a r r a y c o p y ( r e q u e s t . g e t H e a d e r ( ) . g e t A l l H e a d e r F i e l d s ( ) ,
} e l s e i f ( method . e q u a l s ( ”POST” ) ) { 0 , f i e ld , 0 , f i e l d . length ) ;
i f ( getRequestBody ( r e q u e s t ) . i n d e x Of ( ”=” ) < 0 ) return f i e l d ;
return p a r a m e t e r ; }
e l s e p a i r s = getRequestBody ( r e q u e s t ) . s p l i t ( ”&” ) ;
} // r e t u r n a l l i n f o r m a t i o n i n t h e HTTP r e q u e s t f o r
for ( S t r i n g p a i r : p a i r s ) { logging
i n t i n d e x = p a i r . in d e x Of ( ”=” ) ; private S t r i n g g e t R e q u e s t I n f o r m a t i o n ( Request r e q u e s t ) {
try { // p r i n t s t a t u s code , d e s t i n a t i o n , URL, method
p a r a m e t e r . put ( URLDecoder . d ec od e ( p a i r . s u b s t r i n g ( 0 , S t r i n g i n f o = ”\ t D e s t i n a t i o n : ” + p r o t e c t e d S e r v e r +
i n d e x ) , ”UTF−8” ) , ” \tURL : ” + g e t U r l ( r e q u e s t ) + ” \ tMethod : ” +
URLDecoder . d ec od e ( p a i r . s u b s t r i n g ( i n d e x + 1 ) , r e q u e s t . getMethod ( ) ;
”UTF−8” ) ) ;
} catch ( Unsupp orted Enc odi ng Exc ept io n e ) { // p r i n t h e a d e r f i e l d s
e . printStackTrace () ; HeaderField f i e l d [ ] =
} getAllRequestHeaderFields ( request ) ;
} f o r ( i n t i = 0 ; i < f i e l d . l e n g t h ; i ++) i n f o = i n f o +
return p a r a m e t e r ; ” \n ” + f i e l d [ i ] . getHeaderName ( ) + ” : ” +
} f i e l d [ i ] . getValue ( ) ;
173
return r e q u e s t . getBodyAsStringDecoded ( ) ; entry . getValue ( ) + ” , ” ;
APPENDIX D. SOURCE CODE
}
}
i n f o = i n f o + ” \n
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−” ;
return i n f o ;
}
174
APPENDIX D. SOURCE CODE
D.4 TxtLogger.java } catch ( S e c u r i t y E x c e p t i o n e ) {
e . printStackTrace () ;
} catch ( IOException e ) {
package ReppSi ; e . printStackTrace () ;
}
import java . i o . IOException ; }
import java . u t i l . l o g g i n g . ConsoleHandler ;
import java . u t i l . logging . FileHandler ; public void p r i n t L o g ( S t r i n g l e v e l , S t r i n g msg ) {
import java . u t i l . l o g g i n g . Logger ; i f ( l e v e l . e q u a l s ( ” warning ” ) ) {
l o g g e r . warning ( msg ) ;
public c l a s s TxtLogger { } else {
i f ( l e v e l . e q u a l s ( ” s e v e r e ” ) ) l o g g e r . s e v e r e ( msg ) ;
private Logger l o g g e r ; e l s e l o g g e r . i n f o ( msg ) ;
private TxtLogFormatter f o r m a t t e r ; }
private ConsoleHandler cHandler ; }
private FileHandler fHandler ;
}
public f i n a l s t a t i c S t r i n g INFO = ” i n f o ” ;
public f i n a l s t a t i c S t r i n g WARNING = ” warning ” ;
public f i n a l s t a t i c S t r i n g SEVERE = ” s e v e r e ” ;
public TxtLogger ( ) {
l o g g e r = Logger . g e t L o g g e r ( TxtLogger . c l a s s . getName ( ) ) ;
logger . setUseParentHandlers ( false ) ;
f o r m a t t e r = new TxtLogFormatter ( ) ;
c H a n d l e r = new C o n s o l e H a n d l e r ( ) ;
cHandler . setFormatter ( formatter ) ;
l o g g e r . addHandler ( c H a n d l e r ) ;
try {
// l o c a t i o n o f t h e l o g f i l e
f H a n d l e r = new
F i l e H a n d l e r ( ” / U s e r s / Thee / Desktop / t x t l o g g e r . t x t ” ,
true ) ;
fHandler . setFormatter ( formatter ) ;
175
l o g g e r . addHandler ( f H a n d l e r ) ;
APPENDIX D. SOURCE CODE
D.5 TxtLogFormatter.java S t r i n g B u i l d e r b u i l d e r = new S t r i n g B u i l d e r ( 1 0 0 0 ) ;
b u i l d e r . append ( d f . f o r m a t (new Date ( ) ) ) . append ( ” ” ) ;
b u i l d e r . append ( ” [ ” ) . append ( r e c o r d . g e t L e v e l ( ) ) . append ( ” ]
package ReppSi ; ”) ;
b u i l d e r . append ( formatMessage ( r e c o r d ) ) ;
import java . util . Date ; b u i l d e r . append ( ” \n” ) ;
import java . util . l o g g i n g . Formatter ; return b u i l d e r . t o S t r i n g ( ) ;
import java . util . l o g g i n g . Handler ; }
import java . util . l o g g i n g . LogRecord ;
import java . text . DateFormat ; public S t r i n g getHead ( Handler h ) {
import java . text . SimpleDateFormat ; return super . getHead ( h ) ;
}
public c l a s s TxtLogFormatter extends Formatter {
public S t r i n g g e t T a i l ( Handler h ) {
private s t a t i c f i n a l DateFormat d f = new return super . g e t T a i l ( h ) ;
SimpleDateFormat ( ”dd−MM−yyyy HH:mm: s s ” ) ; }
public S t r i n g f o r m a t ( LogRecord r e c o r d ) { }
176