This is a discussion on Security in PHP within the PHP Programming forums, part of the Web Development category; Database related issues Designing Databases The first step is always to create the database, unless you want to use one ...
| |||||||
| Register | FAQ | Members List | Calendar | Mark Forums Read |
| |||
| Database related issues Designing Databases The first step is always to create the database, unless you want to use one from a third party. When a database is created, it is assigned to an owner, who executed the creation statement. Usually, only the owner (or a superuser) can do anything with the objects in that database, and in order to allow other users to use it, privileges must be granted. Applications should never connect to the database as its owner or a superuser, because these users can execute any query at will, for example, modifying the schema (e.g. dropping tables) or deleting its entire content. You may create different database users for every aspect of your application with very limited rights to database objects. The most required privileges should be granted only, and avoid that the same user can interact with the database in different use cases. This means that if intruders gain access to your database using your applications credentials, they can only effect as many changes as your application can. You are encouraged not to implement all the business logic in the web application (i.e. your script), instead do it in the database schema using views, triggers or rules. If the system evolves, new ports will be intended to open to the database, and you have to re-implement the logic in each separate database client. Over and above, triggers can be used to transparently and automatically handle fields, which often provides insight when debugging problems with your application or tracing back transactions.
__________________ With, J. Jeyaseelan Everything Possible |
| Sponsored Links |
| |||
| Connecting to Database You may want to establish the connections over SSL to encrypt client/server communications for increased security, or you can use ssh to encrypt the network connection between clients and the database server. If either of these is used, then monitoring your traffic and gaining information about your database will be difficult for a would-be attacker.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Encrypted Storage Model SSL/SSH protects data travelling from the client to the server, SSL/SSH does not protect the persistent data stored in a database. SSL is an on-the-wire protocol. Once an attacker gains access to your database directly (bypassing the webserver), the stored sensitive data may be exposed or misused, unless the information is protected by the database itself. Encrypting the data is a good way to mitigate this threat, but very few databases offer this type of data encryption. The easiest way to work around this problem is to first create your own encryption package, and then use it from within your PHP scripts. PHP can assist you in this with several extensions, such as Mcrypt and Mhash, covering a wide variety of encryption algorithms. The script encrypts the data before inserting it into the database, and decrypts it when retrieving. See the references for further examples of how encryption works. In case of truly hidden data, if its raw representation is not needed (i.e. not be displayed), hashing may also be taken into consideration. The well-known example for the hashing is storing the MD5 hash of a password in a database, instead of the password itself. See also crypt() and md5().
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| For example while using hashed password field PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| SQL UPDATE's are also susceptible to attack. These queries are also threatened by chopping and appending an entirely new query to it. But the attacker might fiddle with the SET clause. In this case some schema information must be possessed to manipulate the query successfully. This can be acquired by examining the form variable names, or just simply brute forcing. There are not so many naming conventions for fields storing passwords or usernames.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Normal users click on the 'next', 'prev' links where the $offset is encoded into the URL. The script expects that the incoming $offset is a decimal number. However, what if someone tries to break in by appending a urlencode()'d form of the following to the URL Code: 0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
select 'crack', usesysid, 't','t','crack'
from pg_shadow where usename='postgres';
-- If it happened, then the script would present a superuser access to him. Note that 0; is to supply a valid offset to the original query and to terminate it. ????: It is common technique to force the SQL parser to ignore the rest of the query written by the developer with -- which is the comment sign in SQL. A feasible way to gain passwords is to circumvent your search result pages. The only thing the attacker needs to do is to see if there are any submitted variables used in SQL statements which are not handled properly. These filters can be set commonly in a preceding form to customize WHERE, ORDER BY, LIMIT and OFFSET clauses in SELECT statements. If your database supports the UNION construct, the attacker may try to append an entire query to the original one to list passwords from an arbitrary table. Using encrypted password fields is strongly encouraged.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| A frightening example how operating system level commands can be accessed on some database hosts. PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| MSSQL Server executes the SQL statements in the batch including a command to add a new user to the local accounts database. If this application were running as sa and the MSSQLSERVER service is running with sufficient privileges, the attacker would now have an account with which to access this machine.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| You may plead that the attacker must possess a piece of information about the database schema in most examples. You are right, but you never know when and how it can be taken out, and if it happens, your database may be exposed. If you are using an open source, or publicly available database handling package, which may belong to a content management system or forum, the intruders easily produce a copy of a piece of your code. It may be also a security risk if it is a poorly designed one.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| These attacks are mainly based on exploiting the code not being written with security in mind. Never trust any kind of input, especially that which comes from the client side, even though it comes from a select box, a hidden input field or a cookie.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| * Never connect to the database as a superuser or as the database owner. Use always customized users with very limited privileges. * Check if the given input has the expected data type. PHP has a wide range of input validating functions, from the simplest ones found in Variable Functions and in Character Type Functions (e.g. is_numeric(), ctype_digit() respectively) and onwards to the Perl compatible Regular Expressions support. * If the application waits for numerical input, consider verifying data with is_numeric(), or silently change its type using settype(), or use its numeric representation by sprintf(). * Quote each non numeric user supplied value that is passed to the database with the database-specific string escape function (e.g. mysql_escape_string(), sql_escape_string(), etc.). If a database-specific string escape mechanism is not available, the addslashes() and str_replace() functions may be useful (depending on database type). See the first example. As the example shows, adding quotes to the static part of the query is not enough, making this query easily crackable. * Do not print out any database specific information, especially about the schema, by fair means or foul. See also Error Reporting and Error Handling and Logging Functions. * You may use stored procedures and previously defined cursors to abstract data access so that users do not directly access tables or views, but this solution has another impacts.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| here the example for more secure way to compose a query for paging PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Using Register Globals When on, register_globals will inject your scripts with all sorts of variables, like request variables from HTML forms. This coupled with the fact that PHP doesn't require variable initialization means writing insecure code is that much easier. It was a difficult decision, but the PHP community decided to disable this directive by default. When on, people use variables yet really don't know for sure where they come from and can only assume. Internal variables that are defined in the script itself get mixed up with request data sent by users and disabling register_globals changes this.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Let us demonstrate with an example misuse of register_globals: PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| From the above example When register_globals = on, our logic above may be compromised. When off, $authorized can't be set via request so it'll be fine, although it really is generally a good programming practice to initialize variables first. For example, in our example above we might have first done $authorized = false. Doing this first means our above code would work with register_globals on or off as users by default would be unauthorized.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Example is that of sessions. When register_globals = on, we could also use $username in our example below but again you must realize that $username could also come from other means, such as GET (through the URL). use of sessions with register_globals on or off PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| It's even possible to take preventative measures to warn when forging is being attempted. If you know ahead of time exactly where a variable should be coming from, you can check to see if the submitted data is coming from an inappropriate kind of submission. While it doesn't guarantee that data has not been forged, it does require an attacker to guess the right kind of forging. If you don't care where the request data comes from, you can use $_REQUEST as it contains a mix of GET, POST and COOKIE data.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Simply turning off register_globals does not mean your code is secure. For every piece of data that is submitted, it should also be checked in other ways. Always validate your user data and initialize your variables! To check for uninitialized variables you may turn up error_reporting() to show E_NOTICE level errors.
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| Here is the example for detecting simple variable poisoning PHP Code:
__________________ With, J. Jeyaseelan Everything Possible |
| |||
| If you are on a shared host with register_globals turned off and need to use some legacy applications, which require this option to be turned on, or you are on some hosting server, where this feature is turned on, but you would like to eliminate security risks, you might need to emulate the opposite setting with PHP. It is always a good idea to first ask if it would be possible to change the option somehow in PHP's configuration, but if it is not possible, then you can use these compatibility snippets.
__________________ With, J. Jeyaseelan Everything Possible |