During this time, I have been writing a whole site, and it was basically completed a few days ago. So I took some time to write a summary of php security. It doesn't matter if the technology content is not high. I hope some friends who are preparing to write a website can guide me a little.
During this time, I have been writing a whole site, and it was basically completed a few days ago. So I took some time to write a summary of php security. It doesn't matter if the technology content is not high. I hope some friends who are preparing to write a website can guide me a little.
At the beginning of the holiday, I took the time to read white hats about web security. Wu Hanqing basically summarized all the problems and solutions that can be encountered in web security, this is also the cornerstone of my overall code security.
I hope to share my experience in the following aspects:
Grasp the entire site structure to avoid leaking sensitive site Directories
At the beginning of the code writing, I also put index. php, register. php, and login. php under the root directory, just like many old source codes. The user clicks the registration page and jumps to the page. There are not many structure ideas. The biggest problem with code structures like this is not security, but code expansion and porting.
During code writing, we often need to modify the code. At this time, if the Code does not have a unified entry point, we may need to change many places. Later, I read a little emlog code and found that the real front-end code of the website is in the template directory, while the root directory only contains the entry point file and configuration file. In this case, the entire website structure was modified.
Place an entry point file in the root directory of the website to manage all the pages of the website. At this time, the registration page becomes. Any page is just a parameter of act, after obtaining this parameter, use a switch to select the file content to be included. The entry point file also contains constant definitions, such as the absolute path of the website, the website address, and the database user password. In the future, we will try to use absolute paths instead of relative paths in script writing (otherwise, the code will change if the script changes its position ), the absolute path comes from the definition in the entry point file.
Of course, in terms of security, an entry point file can also hide the background address. Such an address does not expose the absolute path in the background, or can be changed frequently without changing too much code. An entry point file can also verify the identity of a visitor. For example, if a website is in the background, no administrator can view any page. You can verify your identity in the entry point file. If you have not logged on, the 404 page is displayed.
With the entry point file, I added this sentence to the front of all non-entry point files:
<? Php if (! Defined ('www _ root') {header ("HTTP/1.1 404 Not Found"); exit ;}?>
WWW_ROOT is a constant defined in the entry point. If the user accesses () through the absolute path on the page, the Error 404 is returned. Only access through the entry point () is allowed (), to execute the subsequent code.
Use precompiled statements to avoid SQL Injection
Injection is a big problem in the past, but in recent years, it has become much better because we have attached great importance to this issue.
Wu Hanqing said very well in the web white hat. In fact, many vulnerabilities, such as SQL injection or xss, all separate "data" from "code. "Code" is the content written by programmers, and "data" is the content that users can change. If we write an SQL statement select * from admin where username = 'admin' password = 'xxxxx', admin and xxxxx are data, which are user names and passwords entered by the user, however, without any processing, the user input may be "code", such as 'or ''=', which causes a vulnerability. "Code" is definitely not accessible to users.
In php, mysql Databases have two modules: mysql and mysqli. mysqli means mysql improve. Mysql Ultimate Edition. This module contains the concept of "pre-compilation. Like the preceding SQL statement, change to select * from admin where username = '? 'Password = '? ', It is not an SQL statement, but you can use the pre-compilation function of mysqli to compile it into a stmt object first. After the user enters the account password, use stmt-> bind_param to bind the "data" entered by the user to the positions of the two question marks. In this way, the user input can only be "data", rather than "code ".
These two question marks define the location of "data" and the structure of SQL statements. We can encapsulate all our database operations into a class, and pre-compile all SQL statements. This completely avoids SQL injection, which is also the most recommended solution by Wu Hanqing.
Below are some code parts using mysqli (I have omitted all the code that determines whether the function runs successfully or fails, but it does not mean it is not important ):
<? Php // user-input data $ name = 'admin'; $ pass = '000000'; // create a new mysqli object. The constructor parameters contain database-related content. $ Conn = new mysqli (DB_HOST, DB_USER, DB_PASS, DB_NAME, DB_PORT); // you can specify the default encoding of the SQL statement $ this-> mysqli-> set_charset ("utf8 "); // create an SQL statement using wildcards $ SQL = 'select user_id FROM admin WHERE username =? AND password = ?; '; // Compile the statement to obtain an stmt object. $ stmt = $ conn-> prepare ($ SQL ); /********************** and the content can be reused, you do not need to compile *********************** // bind_param to bind data. // you can see, because I left two ?, That is to say, to bind two data to it, so the first parameter is the type of the bound data (s = string, I = integer ), the second parameter is the data to be bound $ stmt-> bind_param ('ss', $ name, $ pass ); // call the bind_param method to bind the result (if you only check whether the user and password exist or are only a DML statement, you do not need to bind the result) // The result is the field that I select. Several fields need to be bound to $ stmt-> bind_result ($ user_id); // execute the statement $ stmt-> execute (); // obtain the result if ($ stmt-> fetch () {echo 'login successful '; // be sure to release the result resource, otherwise, an error will occur later: $ stmt-> free_result (); return $ user_id; // return the content just selected} else {echo 'logon failed';}?>
Prevent XSS code. Do not use cookies if you do not need them.
I didn't use cookies on my website, and because I am very dead about permission restrictions, it is less risky for xss.
It is also a truth for xss defense to deal with the relationship between "code" and "data. Of course, the code here refers to javascript code or html code. For user-controllable content, we must use functions such as htmlspecialchars to process user input data and carefully output the content to the page in javascript.
Restrict user permissions to prevent CSRF attacks
Nowadays, the Script Vulnerability is prone to unauthorized operations. Many important operations are executed in GET mode or POST mode without verifying whether the performer knows.
Many CSRF users may be unfamiliar. Just give a small example:
A and B are all Forum users. This forum allows users to "like" an article. Users who click "like" actually access this page :. At this time, if B sends this URL to A, A opens it without knowing it, which is equivalent to A thumbs up for the article titled article Id = 12.
Therefore, this Forum adopts the POST method to like an article.
You can see that a hidden input box contains the ID of the article, so you cannot click a through a URL. However, B can create a "tempting" page, and a button is written as a form to seduce. A clicked and liked this article.
Finally, the Forum had to add a verification code to the form. Only A can enter the verification code to like. In this way, B's heart is completely killed.
However, which of the following forums do you need to enter the verification code for "like?
So Wu Hanqing also recommended the best way in white hats, that is, adding a random string token to the form (generated by php and saved in SESSION ), if the random string submitted by the user is the same as the string saved in the SESSION, the user can like it.
When B does not know the random string of A, the unauthorized operation is not allowed.
I have also used TOKEN for many times on the website. Whether it is the GET or POST method, it usually can withstand the CSRF estimation of 99%.
Strictly control the types of uploaded files
The upload vulnerability is a critical vulnerability. Any File Upload Vulnerability can execute arbitrary code and obtain webshell.
I am uploading this part. I wrote a php class that uses whitelist verification to control the user's upload of malicious files. On the client side, I verified the type of the file selected by the user through javascript, but this is just a good reminder to the user that the final verification part is still on the server side.
The whitelist is necessary. If you only allow uploading images, set it to array ('jpg ', 'gif', 'png', 'bmp '), after a user uploads a file, obtain the suffix of the file name and use in_array to verify whether the file is in the whitelist.