Vous êtes sur la page 1sur 4

Practical assignment 2 (INFOINP)

Bas van Doren, bdoren, 3401898

2.1
1)
It shows an HTML form. On submission it writes the contents of the input field to
itself (!) and redirects the user to the newly created page.

2)
The new contents should be written to a separate file. The default
value of the form field should be read from this file as well. The seperate file can be included at the
end of the page. The file permissions on the script itself should be read-only, so the separate file can
not write to it.

3)
The code in the first PHP block should be wrapped in an if-statement which checks the login state
of the user. To allow users to be registered and logged in, additional scripts should be made that
make this possible. It would be a nice addition if the script redirected the user to the login page if
the login state check fails.

4)
Before the seperate file is included, the script should read its contents and that of youshallnot.txt.
The latter should be split on newline characters so it becomes an array. Then the contents of the
former file should be scanned for presence of each function name. If one exists, the inclusion does
not happen. This check can also be performed on submit, so the submitted content is not written
unless no matches are found.

The above solution is not perfect. A less naive hacker can still use blacklisted functions by splitting
their names into multiple variables, concatenating them into one variable and then use the variable
as a function call. http://php.net/manual/en/functions.variable-functions.php

2.2
Account hijacking is possible (by setting `id` in the GET request)
?action=save
&id=1
&name=attacker
&password=easy
&birthdate=2000-10-10

SQL injection is possible (allowing us to add a WHERE-clause that updates all accounts)
?action=save
&name=attacker
&password=easy
&birthdate=2000-10-10" WHERE id > 0; --

First of all, the `id` variable should be protected using the session mechanism. If it is stored in
$_SESSION, an attacker can not directly change it.
Secondly, the input parameters should be escaped in such a way that they do not have any special
meaning in SQL. This can be done using a function like pg_escape_string() or
mysql_real_escape_string() (depending on the DB system being used).
2.3
The source code of the main script (or any file in the script's directory or its subdirectories, for that
matter) can be read if the attacker passes ?page=index.php to the script.
This gives us a nice entry-point for further investigation of the site. login.php contains interesting
details about the login procedure.
Including safe/secreet (path obtained from login.php) gives us login and encrypted passwords for
admin and member.

A little bit of manual bruteforcing (and smart guessing based on a rather vague encryption
algorithm), reveals the admin password (fonkyzeit). A little more manual bruteforcing (and logical
thinking), reveals the member password as well (alsjehaarmaargoedzit).

To fix these security holes, first of all, the ability to view script files should be removed. This can be
done my making a white-list of allowed files (or maybe a black-list of protected files) and checking
the `page` variable against it.
For maximum security, the safe/secreet file should not be viewable via the web (by black-listing or
not white-listing as mentioned above). The encryption algorithm could be replaced with a more
tried and test one, like md5 in combination with a 'salt' (to prevent attacks using a rainbow table).

2.4
The login procedure kan be circumvented entirely by creating (or modifying) the `koekje` cookie.
The cookie value consists of 2 parts separated by a hyphen. A normal login reveals that the first part
is the username and the second part is a timestamp.
For a username, `admin` is the most obvious choice. Curiously enough, the timestamp part can be
any value (including void) as long as the hyphen is present... no validation whatsoever. The
MarkAdmin now gives us the ability to modify the grades.

This vulnerability can be fixed by simply storing the login state server-side using a session
mechanism instead of a cookie. This prevents the attacker from changing his username to one with
more rights.

2.5
1)
8 groups of hexadecimal numbers each a maximum of 4 digits.

/^([0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$/i

2)
One or more titles, one or more names (separated by one space) and/or initials (separated by
nothing or one space), multiple lowercase prefixes (such as van, den, 't), one surname.

/^([a-z]+\.\x20)*(([A-Z][a-z]+|([A-Z]\.)+)\x20)+('?[a-z]+\x20)*([A-Z][a-
z]+)$/

3)
<?php
echo (verify_date($_GET['d'])) ? 'VALID' : 'INVALID';
function verify_date($input)
{
$date = array();
preg_match('/^([0-9]{1,2})-([0-9]{1,2})-([0-9]{1,4})$/', $input,
$date);
if(!empty($date))
{
$d = (int) $date[1];
$m = (int) $date[2];
$y = (int) $date[3];
// Leap year check
if(0 == $y % 400) $leap = true;
else if(0 == $y % 100) $leap = false;
else if(0 == $y % 4) $leap = true;
else $leap = false;
// Month check
if(0 < $m && 13 > $m)
{
if(2 == $m) $days = ($leap) ? 29 : 28;
else if((7 > $m && 0 == $m % 2) || (7 < $m && 1 == $m %
2)) $days = 30;
else $days = 31;

if(0 < $d && $days >= $d)


return true;
}
}
return false;
}
?>

4)
The scheme name (eg. http://, https://) is missing from the expression. The hostname part of the
expression allows only two labels ([sub]domains) and a TLD. The underscore (_) character is not
allowed in the hostname part, but the expression allows it. Each label must be 1-63 characters long,
this is not enforced by the expression. Only one label is required (apart from the TLD), but the
expression requires two or more. The expression allows hostnames with two consecutive dots,
which is not correct. The pathname part is quite limited (no query strings and %xx hexadecimal
characters). The forward slash after the TLD is now always optional, but it should be required if
there is a pathname.
An improved version (assuming HTTP URLs only):

/^(https?:\/\/)([A-Z0-9-]{1,63}\.)*[A-Z0-9-]{1,63}\.[A-Z]{2,4}(?(?=.)\/)
(%[0-9A-F]{2}|[A-Z0-9\/._?&=-])*$/i

2.6
A)
Although the e-mail address check seems pretty solid, the `bidding` field seems to have no
validation at all. We can enter all the HTML we want (including the very interesting <script> tag)
and it appears on the confirmation page.
It seems quite reasonable that the seller has a page which shows all the biddings (or evil code) for a
specific item. Since Javascript can read cookies, an attacker now has the ability to read the sellers
session, hijack it and probably make a very nice deal.

To solve this, the bidding format could be restricted, but this leaves no option for bids that are "not
restricted to money". So instead of validating the input, we must secure the output. Converting all
special HTML characters to their 'meaningless' equivalents should do the trick (PHP provides the
functions htmlentities() and htmlspecialchars() for that purpose).

B)
User info is 'protected' using two CAPTCHAs. The first is generated by check.php?
user=<username> and solving it correctly sends us to the second which is generated by
check2.php?user=<username>. However, the first check is completely bogus because it can be
skipped by going to check2.php directly.
Solving the CAPTCHA doesn't require complex OCR. In fact, the cookie
`cyclicredundancycodecheckvalue` simply tells us what the CAPTCHA word is (after shifting each
letter by one position forward in the alphabet).

The first problem can be fixed by keeping track of the 'solved state' of both CAPTCHAs (in a
session, of course). check2.php would only grant access if both CAPTCHAs have been solved in
one go (failing a CAPTCHA would reset the state for both). I do think that two CAPTCHAs might
become frustrating to real users, though.
The other problem can be fixed by storing the CAPTCHA value on the server using the session
mechanism.

2.7
SQL injection is possible through the calendar item `id` (and maybe through other query variables
as well). The consequences of this are complex, whereas the fix is simple. Validate the input for
proper format (only allow integers for `id`, for instance) and escape other input using the
appropriate functions (in PHP, there are pg_escape_string() and
mysql_real_escape_string()).
(audit will be extended in next version if finished in time)

Vous aimerez peut-être aussi