We all know that vulnerabilities in web pages are quite common these
days. They range from SQL injections, XSS vulnerabilities, CSRF, etc. In
this article we'll provide basic examples of the most common
vulnerabilities you'll find in web pages—including and especially
WordPress. We'll describe them in detail below.

1. DoS (Denial of Service)

The denial of service happens for various reasons, but we won't describe
anything like attackers trying to DoS a specific web site with a botnet
of compromised computers, but we'll rather describe how a DoS
vulnerability can happen when writing a code.

Usually we have to make a logical mistake to create a DoS scenario in
our web application. Let's present such a scenario with a little PHP
code. The code below is a PHP sample code that contains a logical error
that can be exploited to cause a denial of service.

In the above code, we're first checking whether the file parameter
exists. If yes, we're reading the value stored in the file parameter,
otherwise we're closing the application with an error message that says
that we didn't enter the file parameter. Thus, we have to provide the
file parameter in order to continue execution of the application.
After that, we're reading the value stored in the file parameter and
checking whether the file exists. If it doesn't, we're again closing the
application with an error message about a non-existent file. But if a
file does exist, we're including it into the current application
execution. From the above code it's not instantly evident that the code
contains a vulnerability that can result in a denial of service.

Let's say that we saved the above code as index.php and we're supplying
a value of "testing.php" in a file parameter. In such a scenario
everything works fine as long as the testing.php file exists and does
some work. But what happens if we provide index.php as a value for
the file parameter. In such a case, the index.php file is including
itself into the current execution, and this happens infinitely,
resulting in a denial of service. By default, the operating system
allocates just so much memory to each application, and if that
application wants more memory, it is usually forcibly closed by the
operating system. This is exactly what happens in this case. When the
index.php allocates as much memory as permitted, the operating system
forcibly closes it.

Let's also present a request that we would have to send to the above
application to force a DoS. Such a request is presented below:

GET /index.php?file=index.php HTTP/1.0

2. SQL Injection

SQL injection vulnerability is still quite common these days even though
it's been present for over ten years. SQL injection vulnerability
happens when the application isn't checking the input values for special
characters and encapsulating them, and uses the inputted value in the
SQL query. An example of such an application can be seen below:

We can see that we're checking whether the parameters username and
password exist and have a correspondent value. If they have, we're
reading the values into the $user and $pass variables. Afterwards we're
connecting to the SQL database on localhost:3306 with a username
admin and password admin and selecting the database db.
Then we're constructing an SQL query sentence in which we're including
the exact values from the username and password inputted values
without checking it for special characters.

But we should do that, because the above code is vulnerable to SQL
injections, because we're not encapsulating the username and
password inputted values. Imagine that we enter a value ' OR
1=1--' into both the username and password field. After that
the constructed SQL query will be as follows:

SELECT * FROM users WHERE username='' OR 1=1--'' AND password='' OR
1=1--''

This effectively selects all users from the table users because of
the OR directive we've passed to the vulnerable application. The above
SQL query is always evaluated to true and we don't need to enter the
right username and password, which would log us into the application.
Instead we can enter special input values to break the logic behind the
application and login nevertheless.

3. CSRF (Cross-Site Request Forgery)

The cross-site request forgery vulnerability is present when we can
plant a request to the user, which is then sent to the targeted web site
in his/her name. The request then executes certain action on the target
web site in the user's name. There are two questions we need to ask
ourselves:

How can we plant a request to the user?

What kind of action can we execute on the target web site?

The answer to the first question is simple. We can plant a request to
the user in various ways through which the end goal is the same: the
user's browser has to send the request to the target web site on one way
or another. We can plant the request to the user in one of the following
ways:

In case the target web site is vulnerable and we can temporarily
inject some code into it, we need to construct the right URI that we
sent to the user, who must click on it. Upon clicking on the URI, the
initial request will be sent, but because of the vulnerability a
second request will be made to request the action that we specified.

In case the target web site is vulnerable and we can permanently
inject some code into it, we can simply insert another request into
the source code of the web page. When the user visits that specific
web page sometime in the future, our custom request will be executed
in the user's name. This approach doesn't even need social
engineering to work, because all the user has to do is visit the
vulnerable web page.

We can also construct our own web page, which we have total control
over. This is why we can include the code that will do the malicious
request in the source code of the web page alone. But in the end the
user must still visit that web page, which is why we must send
him/her a link to our own web page. When the user visits the web
page, the requests embedded into the web page alone will be executed
in the user's name.

We can see that there are various ways to plant a request to the user's
browser, which must execute the request. But this is only half of the
story; we still need to talk about what kind of request we can embed
into the web page. The requested action can really be anything we like,
but the targeted web page must support that action and execute
accordingly.

When the user visits this web page, a new request will be made
requesting the index.php resource on the web page
"http://www.anything.com" with parameters id=1000 and action=up. Now, if
that web page doesn't have the resource index.php the request will fail.
But if the index.php is present but doesn't use the parameters
id and action, the request will again fail. This means that we
need to know about the files present on the targeted web page as well as
the parameters that the web page uses to do some action. This way we
could alter the results of the survey, where we would make a request
that would vote for the first candidate of the survey instead of the
other (which might be more popular). After that we would need to attract
users to our page, so the voting requests will be sent to the survey as
well.

But this is just a tip of the ice berg; imagine what we could do if we
could send requests that would add another administrator user to some
database, delete all the usernames, or even send arbitrary emails to
contacts in users' mailbox signed by that user, etc.

Now we're going to explore other web vulnerabilities, which are also
both prominent and common.

XSS (Cross-Site Scripting)

This attack is arguably as common as the original three. The cross-site
scripting attack allows us to inject arbitrary code into the vulnerable
web page, which we can use to obtain sensitive information like
usernames, passwords, cookies, etc. With the XSS attack we can
circumvent the same-origin policy, which is present in all scripting
languages executing at the client-side in a web browser. An example of
such a language is Javascript. The same-origin policy allows the web
browser to execute the client-side code only on a web page from which
the code originated.

There are three types of XSS attacks:

Reflected XSS

The webpage is vulnerable if it accepts the user input and displays its
contents on a web page without proper validation of special characters
like slash ('/'), apostrophe ('"'), etc. In such cases we can include a
Javascript in the URI that we send to the user, which clicks on a link.
Upon that, the included Javascript is executed in the users' browser.
The Javascript can grab the users' cookie and sends it to the attackers'
network. An example of an application that contains the reflected XSS
vulnerability is seen below:

First we're checking to see if the parameter p is set and displaying
its value without filtering any of the special characters. We can store
a Javascript code in a value of parameter p that will be executed
when the user clicks on the URI (which also includes that malicious
Javascript code). An example of the URI that contains the Javascript
code, which will display the user's cookie, is as follows:

GET /index.php?p=<script>alert(document.cookie)</script> HTTP/1.1

Stored XSS

A stored XSS attack is present when we can store the malicious code
inside the vulnerable web page permanently. Thus, our code will be
executed every time the user visits the vulnerable web page. Because the
code is stored right in the web page, we don't have to send emails to
users convincing them to click on the link or something. Such a web page
must use some kind of a backend database where the user inputted values
are stored. When a user visits a web page, those values are taken from
the database and displayed on the web page, thus executing the malicious
code.

DOM-based XSS

DOM-based XSS attack happens when we send a malicious URI to the user,
who clicks on it. But this isn't the same as with reflected XSS attack,
because the web site returns a valid non-malicious response (thus the
web site is not vulnerable to reflected XSS attack). The attack happens
because the web site uses a Javascript code that in turn uses the values
from the URI address. An example of a DOM-based XSS is presented in the
code below:

From the source code we can see that we're getting that Javascript back
as a response on a request. That Javascript first reads the value of
parameter p from the used URI address into a variable p.
Afterwards it displays the value of the parameter p. Because of
this, the Javascript is actually referring to the value stored in
parameter p, which can be a malicious Javascript. Let's say that
we're executing the request below:

/index.php?p=<script>alert(document.cookie)</script>

When the Javascript from the response is executed, it will read the
value of parameter p, which is
<script>alert(document.cookie)</script> and include it into
processing. Therefore the malicious code in parameter p is executed
nevertheless, even if the web site itself is not vulnerable to reflected
or stored XSS attack.

Buffer Overflow

Sometimes we can see executable programs being used as part of the
application providing unique features. But even though the executables
are being used as part of web applications, buffer overflow
vulnerabilities still exist. Imagine that a web application is calling a
system function to call an executable with the user inputted
parameter. This doesn't prevent the buffer overflows that could be
present in executables from overflowing the program stack or heap
structures.

An example of a C program that contains a buffer overflow vulnerability
is as follows:

The program accepts an input argument, but doesn't check for the length
of the argument. When it accepts the input argument, that argument is
sent to the copy function, which copies the argument into a local
buffer with the strcpy function call. But there are only 20 reserved
bytes in the local array, so if we copy an argument that is longer than
20 characters, a buffer overflow will occur. This will crash the program
at least, but a specifically crafted input argument could execute
arbitrary code on the target system.

Format String

Format string is a special vulnerability where the user can control what
gets inputted into a function call like printf, fprintf, sprintf,
snprintf, vprintf, vprintf, vsprintf and vsnprintf. To understand
this attack it's best to look at the example. An example code written in
programming language C that contains a format string vulnerability is
presented below:

We can see that the program accepts one input argument, which is
directly passed to the printf function call. By default, the program
echoes the input argument on the screen, but what if we enter some
special character that the printf function will treat differently,
like %n, %x or %s. If we enter the special character %x, the printf
function will output four bytes from the stack, if we enter two %x
characters, the printf function will output eight bytes from the stack,
etc. This happens because we've called the function printf without the
necessary parameters, which should be present. But the function can't
know if those parameters are present or not and takes the next value
from the stack (where the missing parameter should be).

With the %x we can read arbitrary values from the stack, whereas with %n
we can write an arbitrary value on an arbitrary address in the memory.
With both the %x and the %n, we can gain control over the execution of
the program and execute arbitrary code.

Directory Traversal

The working directory traversal vulnerability can be present in an
application that allows the users to read the files from the filesystem,
but fails to properly identify which file the user is allowed to read.
The vulnerability is usually present because the application doesn't
check what file the user is trying to read. The basic problem is that
application is not checking whether the user is trying to move up the
directory chain into the parent directory with the use of special
characters "../" or "..". Therefore the user can not only read
files from the allowed directory, but also from all other directories
the application has access to.

In the above code we're first checking whether the parameter file
exists and contains a value. After that we're constructing a whole path
to the file we're trying to read with the use of getcwd function
that gets the current directory and appends it the value of the
parameter p. At the end we're reading the file from the constructed
path and displaying it to the user.

The problem occurs because we're not checking for any malicious
characters in the value of parameter p. This allows the attacker to
traverse up the directory tree by using the special sequence of
characters "../" or "..". Let's present the request that would
read the file /etc/password from the system even though the application
doesn't have access to that file. The request would have to look
something like as follows:

GET /index.php?file=../../../../etc/passwd HTTP/1.0

This effectively reads and displays the system file /etc/password that
contains all the usernames on the system.

File Inclusion

The file inclusion attack is very similar to directory traversal attack.
The only difference is that with directory traversal attack, we can only
read the file we're not allowed to read, but with file inclusion we're
including the file into the current web page execution, thus executing
the file we're not allowed to execute.

We must know that there are two types of file inclusion attacks:

LFI (Local File Inclusion)

Here we're including the local file into current execution. By local
file we mean the file that is already present on the server's system.
The LFI attack is possible because the application doesn't
encapsulate the user inputted data.

RFI (Remote File Inclusion)

Here we're including the remote file into current execution. This can
happen if the application has an option to upload the file to the
server's filesystem. In such cases, we can upload the malicious file
from our client to the server and execute it. With this attack, we
can upload a malicious web shell onto the vulnerable application and
obtain total control of the web server (under the context of the
application's user of course).

An example of a vulnerable code can be seen in the source code output
below:

In the above code we're first checking whether the parameter file
exists and contains a value. After that we're constructing a whole path
to the file we're trying to read with the use of getcwd function
that gets the current directory and appends it the value of the
parameter p. At the end we're including the file from the
constructed path into the current execution of the web page.

Command Injection

The command injection vulnerability can be present in an application
where the user inputted value can affect the command that gets executed
on the server. An example of a vulnerable application written in PHP is
as follows:

In the above code we're first checking if the parameter user exists
and if it does, we're reading the value of that parameter into a local
variable. After that we're executing the command "id user " on the
system. The vulnerability is present because the application doesn't
check the inputted value for special characters. Because of that we can
execute a second command on the system if we pass a value like
"root;ls -l / " in parameter user. The application will then
execute the following command: "id root;ls -l / ". But because the
';' is a separator between multiple commands, the application will
actually execute two commands one after another, returning the result of
both of them.

Privilege Escalation

Privilege escalation attack is the attack where we're using the logical
error in the application to obtain privileges to do something we're not
supposed to do. This vulnerability often happens in applications that
use multiple user roles like unauthorized user, authorized user,
administrator, etc. It's redundant to say that some user roles have more
permissions than others. For example, the administrator should have the
right to add other user accounts, while other user roles shouldn't have
that privilege. The vulnerability would then happen if the normal user
could create new user accounts nevertheless.

Conclusion

We've seen that there are many vulnerabilities that we need to watch out
for when programming a web based application. We looked at basic
examples of most common vulnerabilities and explained them in detail to
better present the vulnerabilities out there. This can be a reference of
most common mistakes in web applications that web developers can study
and use.