In recent years, SQL injection attacks pose a common and serious security threat to web
applications: they allow attackers to obtain unrestricted access to the database underlying the applications and to the potentially sensitive information these database contain, and it is becoming
significantly more popular amongst hackers. According to recent research, there has been an
increased attempt of this attack type. As one can imagine, attacker gaining administrator access
to server means e ectively loss of all of the data on that server to the invader. Worse yet there is
now a beachhead behind your firewall from which attacks on other server and services can now
be made. In this way SQL injection can provide access to all company or personal data. In the
web environment, end -user privacy is one of the most controversial legal issues, therefore, all
types of SQL injections which are dangerous for the components of the web application must be
prevented. In this project, we have presented a review of di erent types of SQL injections and
illustrated how to use them to perform attacks. we also surveyed existing techniques against SQL
injection attacks and analyzed their advantages and disadvantages. Thus our aim is to provide
increased security by developing a light weighted technique which prevents illegal access to the
database and overcome disadvantages of previously existing techniques.
Introduction to SQL Injection Attacks
SQL injection is one of the major issues that belongs to the category of code injection
problems. According to the report by the White Hat on web security vulnerabilities 2011,
it shows that nearly 15 out of 100 web application attacks account for SQL Injection .
An SQL injection is a kind of injection vulnerability in which the attacker tries to inject
arbitrary pieces of malicious data into the input fields of an application, which, when
processed by the application, causes that data to be executed as a piece of code by the back
end SQL server, thereby giving undesired results which the developer of the application
did not anticipate. SQL injection vulnerabilities are caused by software applications
that accept data from an untrusted source (internet users), fail to properly validate and
sanitize the data, and subsequently use that data to dynamically construct an SQL query
to the database backing that application. Query is constructed by concatenating an
input string directly from the User, the query behaves correctly only if input contains
no malicious string. Using this attack, the attacker can create, up-date, retrieve or delete
any data, depending upon the access specification allowed through the application
code. In addition, the attack can have severe consequences like executing administration
operations on the database  or recovering the content present on the DBMS.
For example, suppose a database contains user names and passwords, and the un-3
derlying application contains the following code:
query = ' SELECT FROM emp WHERE username =
request: getParameter('username') + '
AND password =
request: getParameter('password') + '
This query is used to authenticate the user who tries to login to the web site, by checking
username and password against data stored in the database. However, if a malicious
user enters '
' into the username field, the query string submitted to
the database would be:
SELECT FROM emp WHERE
AND password =
Since the atomic formula
is a tautology, the user will bypass the check, and
authentication will be successful.
Definition 1 (Web Application) We can abstract a web application P : h
a mapping from user inputs (over an alphabet ) to query strings (over ). In particular, P is
given by fh f1; :::; f
1; :::; s
is an input filter,
is a constant string.
The argument to P is an n-tuple of input strings hi1; :::; i
i and P returns a query q = q
1 + ::: + q
where, for 1 j l,
s wheres 2 fs
1; :::; s
f (i) where f 2 f f1; :::; f
ng ^ i 2 fi1; :::; i
That is, each q j
is either a static string or a
Definition 2 (SQL Command Injection Attack) Given a web application P and an input
vector hi1; :::; i
i, the following SQL query:
q = P(i1; :::; i
constructed by P is an SQL injection attack (SQLIA) if the following conditions hold:
The query string q has a valid parse tree Tq ,
There exists k such that 1 k n and f
k ) is a substring in q and is not a valid syntactic
form in Tq .
In this thesis, we have proposed an encoding-based technique to prevent SQL injection attacks. In particular, the proposal works in following phases:
1. We will design an encoding function which respects the homomorphic property
w:r :t: SQL basic operations.
2. We will transform the original version of queries into semantically equivalent form
applying encoding functions before appending inputs to the queries.
3. Finally conversion of result to unicode domain if required.
The structure of the thesis is organized as follows: Chapter 2 describes various type
of attack chapter 3 describes available related works in the literature. Chapter 4 and
subsequent chapters describes Proposed Approach ....
SQL Injections Attacks and their types
SQL injection belongs to the category of code injection attacks. This attack can be
classified into dierent types based on the manner in which the malicious content is
added to the original query.
An atomic formula that always holds true is called tautology. This type of attack can be
performed by injecting an input such that condition in where clause becomes tautology
in the resultant query. The attacker can use the SQL keyword OR to perform this type
of attack. Consider a Log in application that accepts username and password from the
user for authentication . Generic Log in query for authentication can be written as :
$query='Select * from members where username=' '+$userName+'' AND password=' ' +$password+''';
If the attacker enters '
' as username and enters some random
value for password , the resulting query would be:
Select * from members where userName='
AND $password=' ';
The condition check in resulting query will always be true since ' ' will comment
out the password check condition in where clause transforming the where clause into a
tautology . On executing this query, the database will return all data entries of members table. Since the query returns a non-null value, the attacker will be authenticated
to log in .
2.0.2 Union-based Attack
In this type of attack, the attacker injects a malicious input such that resultant query becomes Union of two SQL queries suppose the attacker enters the input '
from members where userName =
' in the userName field and enters some
random value in the password field .At run time final query will look some like this.
Select * from members where username=' ' UNION Select * from USER
where userName='bharat' AND password=' ';
The resulting query will reveal all the private data of the user with username as
bharat if bharat is valid username .
2.0.3 Logically Incorrect Queries
This is a most useful SQL injection attack which may not alter the database but can be
very useful to get information about the database.The attacker enters malicious string
in such a manner such that query string becomes incorrect according to SQL Grammer
resulting origin of some error messages, when executed on database server.These error messages can be useful enough for attacker to gain valuable information about the
database such as table name , column name or their data types . Single quotes can be very
helpful to perform these type of attacks. The attacker can enter an input like 'o'rian' in
the username field and some random value for password . Resultant query at run time
will look something like this.
Select * from members where username=' O'rian 'AND password='random';
We can see that resultant query is incorrect .So when input is appended and query is
sent to the database layer database will throw some error which can reveal information
such as table,their columns ,their datatypes , some part of code involved in this operation.
This might be useful for the attacker to get information about the type of database in use
and its tables, and can help him to easily perform the more attacks described here. thus
programmers are advised to handle all errors and exceptions in application itself so that
attacker can not get any error or exception message.
2.0.4 Alternate Encoding
A defensive Approach to prevent SQLIA will be to filter single quote but attacker can still
attack by using alternate mechanisms to encode and add malicious input to the query.
He can user various availbale encoding schemes like ASCII, hexadecimal instead of
directly using single quote or other malicious input . For example, char(39) represents
the ASCII character for single quote, which is a intelligent way to inject semicolon in the
query instead of directly putting the single quote character.
This type of attack are useful to gain knowledge about the database state . The attacker
can inject Select-Case style statements to per-form timing based delay attacks, these
timing based delay attacks can help him to get some information about current state of
2.0.6 Piggy-backed Queries
An interesting idea would be to insert a completely new query by piggybacking it over
the intended query, rather than appending it with the intended query.Here Attacker is
not modifying the query rather than he is inserting his own query to alter the database.
operator to separate two queries in SQL is semicolon. If the attacker inputs any random
value in the username , and enters ' ; Drop table members;' . At Runtime query will be
Select * from members where username=' ' AND password=' '; Drop table members;
The other query is inserted with the intended query, and both queries are sent to
database for execution . After execution of these queries , the member table is deleted
from the database.Some databases don't allow two queries to execute simultaneously
like oracle.thus these type of attacks depends on database platform.
2.0.7 Stored Procedure Attacks
Programmers have common belief that stored procedures are a useful mechanism to
prevent SQLIA. However, these store procedures are also vulnerable . Attacker can get
information about the code and other data with the help of logically incorrect queries
execution . This code-data can be used along with a combination of tautology and piggybacked query to perform an attack on Application. Using this attack, Attacker can insert
his own code to execute in application thus attacker can be successful in crashing the
application by putting some junk code he can crash the database or he can shutdown
the database by the help of this type of attacks.
Several approaches are proposed in the past to countermeasure SQL injection attacks.some
approaches are based on static code analysis some are completely dynamic others use
combination of both. Let us look at each with there advantages and disadvantages.
3.0.8 Dynamic Query Matching
The dynamic query matching approach  generates a SQL master file, which contains
all valid queries that are intended to be generated by the application. An XML is created
at run time which contains all the queries generated during run time and this XML
is matched with already existing master file. This approach can prevent SQLIA since
modified query will not be present in the master file and the XML Matching module
would detect possible attack.
3.0.9 Analysis Framework for Web Application Security
The approach presented by the paper  creates a finite state automaton based on
dynamic time query generated by the application. Idea is to define expected value of
input for any intended query by this finite state automaton . So basically this method
is based on input validation and depends on how application filters user input . Some
drawbacks also demonstrated such as this approach validates the query based on its
syntax, and but does not takes semantic validation in account . Also, the solution
does not supports all SQL operators such as this does not supports the 'like' operator.
The technique is completely theoretical, and requires some experimental evaluation for
3.0.10 Instruction Set Randomization
It  proposes that the SQL keywords should be appended with the some random
numbers generated by the randomization algorithm. Attempt For SQLIA fails because
constructed keywords are completely random and attacker has no idea about it so he
can not successfully alter the query structure(query modification required keywords).
This algorithm requires a proxy server to validate query based on new Grammar and
de-randomise keywords to send actual query to database layer.if query structure is valid
according to new grammar keyword are de-randomised and sent to database layer else
attempt to SQLIA is prevented . However, introducing proxy server for randomization
and de-randomization adds significant performance overhead.
3.0.11 Frameworks for SQL Retrieval on Web Application Security
This approach  basically works in two modules - Pattern Creation Module (PCM)
and Attack Detection Module (ADM). Pattern Creation Module (PCM) creates a model
of attacks based on the attack patterns from previous attacks.Then Attack Detection
Module (ADM) checks if the query constructed by the application at run time matches
created pattern by PCM Module. It is some kind of signature based Approach if the
attacker performs a new type of attack that does not match an existing available pattern,
the attack will be successful, and this mechanism will fail.
CANDID  stands for Candidate Evaluation for Discovering Intent Dynamically. This
approach dynamically checks the intended query structure with run time generated
query .It proposes to run the web application on candidate inputs that are benign.
However, thus not a practical approach because the problem of finding candidate inputs
This approach  a hybrid approach uses combination of static code analysis and dynamic monitoring . In the static phase, a model is created based on all the queries that
are intended to be generated by the application. Model creation requires source code
which may not be present if application is developed by some third party. In the second
phase which is dynamic phase, the query built during run-time is validated against the
model built during the static phase.
3.0.14 Automated Fix Generation to secure SQL Statements
This approach identifies known vulnerable SQL statements generates a eective solution
to fix and then replaces this vulnerability with the new fix code. This method, however
is based on an assumption that the language of development, database connector and
database system support prepared statements. Primary assumption of this approach is
equivalency of data type of vulnerable code and data types of corresponding columns
in the database. In case of mismatching data types assumption is run-time module will
handle all type conversions whenever required .
SQL injection can be prevented by proper validation of the user input. Some web
frameworks handle this issue by distinguishing user input from the SQL query. For
example, Microsoft's .NET framework provides a mechanism called parametrized query,
which accepts the user inputs as parameters. This helps in separation of the user input
from developer-intended query and allows the database engine to identify malicious
inputs, thus preventing SQL injection.
Proposed Approach: An Encoding-based
In this section we will provide a generic approach on encoding based technique to
prevent SQL injection attacks.
In database-enabled web-applications, SQL Queries are, in general, constructed by
concatenating an input string directly from the User. Through input string attacker
somehow manages to modify query structure. This query structure modification is
possible because both the query languages and input strings use same alphabet and
input strings are directly appended. Therefore one can put SQL keywords in input
strings and manages to modify query structure. What if we change the alphabet of input
string dierent from SQL. This way one can not change query structure if input string
has completely dierent alphabet than query language .
As we know that now-a-days many database systems are using unicode in order to
unifying the character set of dierent languages in an universal way . Let U be the set
of unicode and be a new alphabet. We can define the following function F which maps
any unicode value into a string of
F : U !
The component-wise distributive property of F is defined as
2 : : : x
) = F(x
2) : : : F(x
As an example let us consider = f0; 1g. Given a string 'abc', the unicode of it is
U(abc) = U(a)U(b)U(c). Therefore, the encoded representation of it in = f0; 1g is obtained
Enc(abc) = F(U(abc))
Now let's see how this helps in preventing injection attack. Consider the following
string Q=`` SELECT * FROM members WHERE username = ' '' +
$username + `` ' AND password = ` '' + $password + ``''';
Suppose the username and password entered are ' OR 1=1 and password respectively. The encoded version of inputs are:
Enc(' OR 1=1 ) = 010101010101010101010011001010001
Enc(password) = 100101110101010010100010100101010
Instead of appending the original inputs to the original query Q, we will append the
encoded representation in the language dierent from the SQL constructs as depicted
string query=``SELECT * FROM members
WHERE username =`010101010101010101010011001010001' AND
password = `010101010101010101010011001010001';
Observe that the semantics of Q after appending inputs in encoded form is not changed,
leading to a mitigation of the injection attacks. However, the issue arises here is that the
WHERE condition produces false positives as values are in a new language rather than
4.1 Extending encoding-based approach to database-applications
As we have seen how encoding helps in preventing SQL injection attacks. We now
discuss two major issues in case of database-applications:
1. Data storage and string comparison.
2. Transformation of traditional String Operations into semantically equivalent operations in the new language.
4.1.1 Data storage and string comparison
Consider the database showin in table 4.1. Suppose administrator wants to login by
providing $username= Admin and $password = Admin. Appending inputs in the encoded
form results into the following query:
String query=``SELECT * FROM members
WHERE username =` 011000010111010101011011001010001' AND
password = `011000010111010101011011001010001'
where Enc(Admin)=011000010111010101011011001010001. As an enhancement to the
existing database systems when matching operation is performed over database data,
we can adopt one of the followings:
1. Rather than storing normal string Store its encoded value.
2. While comparing the database entries with input string convert database entries
into encoded value on a fly and then match with input string.
To enable the matching operation, we can store encoded values of strings in the databases
rather than actual strings and and will decode it to its original form after performing all
operations at encoded-level. The encoded version of the database (table 4.2) as shown
It is to be observed that encoded version of database may occupy more storage space
than the original version, and therefore, may take more time on performing database
operations. Therefore, this might be suitable for small database systems only.
Conversion on Fly
Storing database in raw binary format doesnt seem convincing and can take too much
overhead in decoding. We can define similar encoding procedure at database side and
then can compare encoded Value of database entries with encoded input string .What
we are doing is we are comparing encoded value of database entries with encoded value
of input string becuase of there one to one mapping relationship .For encoded value
comparison we can convert unicode data values into encoded value on a fly rather than
storing it permanently.
Let us consider an example how this works. A generic login query would look something like this
string query = 'SELECT * FROM members WHERE databaseEncode(username) =
' ' ' + ApplicationEncode($username) + '' AND databaseEncode (password) = ' ' +
ApplicationEncode( $password) + ''';
Here databaseEncode is encoding function implemented at database layer while ApplicationEncode is same encoding function implemented at application layer. When
normal users tries to login he will be successful in logging in because there is one to
one correspondence between data entries and encoded values. Same can be said for
Unsuccessful trial of attack from attacker side due to oneone mapping.
4.1.2 Transformation of traditional String Operations into the semantically
We want our encoding function to such that all the string operation should provide same
results in encoded domain as in normal domain. Before discussing further we should
look at concept called homomorphism. homomorphic encodingis a form of encoding
which allows specific types of computations to be carried out on encoded text and
generate result which matches the result of operations performed on the normal text.
so basically we want our encoding to follow homomorphism property so that we
should get same results in encoded domain which were intended in normal domain.
Some of the traditional substring matching operations do not behave similarly in new
domain lets consider an example. Suppose we have to search name having a substring
BH. Lets say Encoding for BH is 0011001111001011 suppose we have a name CDE in
database say encoding for CDE is 110000110011110010110000.
So we found a match which is incorrect .Problem is because match is not on byte
boundary. To solve this problem we can take any one of two steps described subsequently.
1) Use Delimiter
2)Use already defined data base string procedures for encoding at database layer.
4.1.3 Delimiter based encoding
We should redefine encoding function to introduce delimiter at byte Boundary. Because
delimiter is at byte boundary, string matching will require delimiter matching also
ensuring every match at byte boundary.
Now our alphabet has 3 symbols (0,1,;) But we Cant represent it with single bit so we
should again define mapping such that we can represent 0 1 and ; by combination of bit
0 and 1
Represent 0 by 00
Represent 1 by 11
Represent ; By 010
4.1.4 Use already defined procedures at database layer
We are using encoding function at database layer also. We can use already defined
procedure in database library such as Binary, Hex (if use hexadecimal encoding instead
of binary ) etc. these types of conversion automatically ensures that matching is done on
Ex- A generic login query can be written something like this
string query = 'SELECT * FROM members WHERE BINARY(username) = '' ' +
Application Binary Encode($username) + '' AND BINARY (password) = ' ' + Application Binary Encode( $password) + ''';
string query = 'SELECT * FROM members WHERE HEX(username) = '' ' + Application HexaDecimal Encode($username) + '' AND HEX (password) = ' ' + Application
Hexadecimal Encode( $password) + ''';
Where HEX and binary are already define function in database library. Hex converts
string to hexadecimal string and BINARY convert string to binary string. Application
Hexadecimal Encode and Application Binary Encode are application layer function for
A Working Example
In this chapter, we will illustrate our proposed technique step-by-step with a working
5.1 Complete technique with worked example
i) Define encoding function at Application layer
ii) Define encoding function at database layer or chose already defined function in
iii) Encode user input before appending to query.
iv) Augment query such that it compares encoded user input with encoded database
ex- string query = 'SELECT * FROM members WHERE username = '' ' + $username + '' AND password = ' ' + $ password + ''';
step i) -Define Encoding function at application layer
HEXAD(String)- user defined string function converts string to Its hexadecimal .
Step ii) encoding function at database layer HEX(already defined in library)
Step iii) and iv)
string query = 'SELECT * FROM members WHERE HEX(username) = ' ' ' +HEXAD(
$username) + '' AND HEX(password) = ' ' + HEXAD($ password) + ' ' ';
A set of Benchmark JSP web applications with MySQL as the backend database were
chosen for experimental Analysis. Analysis was performed to estimate the eectiveness
of our Approach.
Table (6.1) Describes the setup used such as the applications (on which technique was
applied), their size (Lines of Code), no of hotspots, no of vulnerable parameters. Line
of Code was measured using open source tool CLOC . The web applications chosen
were benchmark problems online book store, employee directory, event manager, bug
tracker, online forum, online engineering portal, information portal.
6.1 Result Analysis
For injection and result monitoring tool called SQL Inject Me  was used.Table 3.2
describes the results.
6.2 Hypothesis Evaluation
The results demonstrated in this section 6.2 supplement the hypothesis that our approach
is ecient to prevent SQL injection attacks. It was able to prevent dierent variations of
Description LOC No. of No. of
hotspots injectible parameters
Application for online 6982 13 44
Application to maintain 2317 4 15
profile of employees
Application to manage 2883 8 26
and organise events
Online portal 6502 16 93
Application to notify 2981 7 18
bugs of system
information 3269 7 29
Discussion 1690 3 7
No. of Attacks Rate of No. of Rate of
vulnerable Detected/ false Good inputs flase
inputs injected prevented Negative injected positive
bookstore 51 51 0 53 0
Empldir 50 50 0 52 0
profile of employees
Events 50 50 0 50 0
and organise events
Portal 50 50 0 50 0
Bugtrack 50 50 0 50 0
bugs of system
YellowPages 50 50 0 50 0
the attack, like tautology attack, piggy-backed at-tack, union-based attack and attack performed by injecting logically incorrect queries in the application. Also, the performance
overhead introduced by this approach was negligible. However, the tests performed
were restricted to an application which had only a few queries. It would have been very
interesting to observe the behavior of this approach in case of complicated queries or
queries which contained lots of tokens in the form of joins and select-list attributes. And
comparison of results with other available techniques.
Many Approached have been proposed while highly eective, these approaches have
several limitations that aect their ability to deploy them in practical applications for
preventing SQL injection attacks. There are several limitation eecting deployment of
these techniques like Static analysis techniques address only a subset of the problem , do
not achieve the same levels of precision as dynamic techniques but reduces high runtime
overhead of Dynamic techniques. Other solutions require developers to learn and use
new APIs, modify their source code,some has limitations of completeness Defensive
coding techniques oering eective solution to injection attacks is dicult to apply
eectively in practical applications because of selection of proper validation function .
Our approach is very much light weighted since it just encodes user input before
appending to query .Run time time includes encoding and query execution time thus
has little overhead of encoding which is very minimal (linear run time ).So this approach
can be deployed in practical application with ease.
In this thesis, we have proposed a new encoding-based technique to prevent SQL injection attacks. Currently, our approach is able to prevent all first order injection such
as union-based attack, piggy-backed query based attack, tautology based attack and
logically incorrect queries based attack. The attack simulation for testing the eectiveness and eciency of the approach was performed using already available tool
SQLInjectMe which is written to test application with already available test data set
having both malicious inputs and benign inputs. However the tests performed were
restricted to benchmark applications which had only a few queries. It would have been
very interesting to observe the behavior of this approach in case of practical on-net
applications with large databases having complicated queries in the form of joins and
select-list attributes to get actual idea of complexity and overhead involved.
 Sruthi Bandhakavi, Prithvi Bisht, P. Madhusudan, and V. N. Venkatakrishnan.
CAN-DID : Preventing SQL Injection Attacks using Dynamic Candidate
Evaluations. In Proceedings of the 14th ACM conference on Computer and
communications security, CCS '07, pages 12'24, New York, NY, USA, 2007. ACM.
 Stephen W. Boyd and Angelos D. Keromytis. SQLRand : Preventing SQL Injection
Attacks. In In Proceedings of the 2nd Applied Cryptography and Network
Security (ACNS) Conference, pages 292'302, 2004.
 Gregory T. Buehrer, Bruce W. Weide, and Paolo A. G. Sivilotti. Using parse tree
validation to prevent sql injection attacks. In In Proceedings of the International
Workshop on Software Engineering and Middleware (SEM) at Joint FSE and
ESEC, pages 106'113, 2005.
 Justin Clarke. SQL Injection Attacks and Defense. Syngress Publishing, 1st edition,
 Debasish Das, Utpal Sharma, and D.K. Bhattacharyya. An Approach to Detection
of SQL Injection Attack Based on Dynamic Query Matching. International Journal
of Computer Applications, 1(25):28'34, February 2010. Published By
Foundation of Computer Science.
 OWASP Foundation. Top 10 2013-a1-injection, June 2013.
 William G. J. Halfond, Jeremy Viegas, and Ro Orso. Classification of SQL Injection
Attacks and Countermeasures.
 William G.J. Halfond and Alessandro Orso. Preventing SQL Injection Attacks
 Haeng Kon Kim. Frameworks for SQL retrieval on Web Application Security. In
Pro- ceedings of the International Multiconference of Engineers and Computer
Scientists, volume 1, page 5, Hong Kong, 2010. IMECS, International Association
 Diallo Abdoulaye Kindy and Al-Sakib Khan Pathan. A Detailed Survey on
Various Aspects of SQL Injection: Vulnerabilities, Innovative Attacks, and
Remedies. CoRR, abs/1203.3324, 2012.
 Microsoft. Microsoft code analysis tool .net (cat.net) v1 ctp - 32 bit.
http://www. microsoft.com/en-us/download/details.aspx?id=19968, 2013.
 Microsoft. Rngcryptoserviceprovider class. http://msdn.microsoft. com/enus/library/system.security.cryptography. rngcryptoserviceprovider.aspx, 2013.
 Open Web Application Security Project (OWASP). Projects/OWASP Secure
Web Application Framework Manifesto/Releases/Current/Manifesto, November
 Ashok Singh Sairam Sangita Roy, Avinash Kumar Singh. Analyzing SQL Meta
char- acters and preventing SQL Injection attacks using meta filter. In
International Con- ference on Information and Electronics Engineering, ICIEE
2011, IACSIT Press, vol- ume 6, page 4, Singapore, 2011. Indian Institute of
Technology, Kalinga Institute of Industrial Technology, IACSIT Press.
 IBM GlobalTechnology Services.Ibm Internet Security Systems X- xforce-2008-annual-report.pdf.
 Stephen Thomas and Laurie Williams. Using Automated Fix Generation to
Secure SQL Statements. In Proceedings of the Third International Workshop on
Software Engineering for Secure Systems, SESS '07, pages 9'15, Washington, DC,
USA, 2007. IEEE Computer Society.
 Gary Wassermann and Zhendong Su. An Analysis Framework for Security in
Web Applications. In In Proceedings of the FSE Workshop on Specification and
Verifica- tion of Component-Based Systems (SAVCBS) 2004, pages 70'78, 2004.