I. Versions involved in the Vulnerability
Discuz! Free versions earlier than 2.0 (commercial version not available ). 1.01 and lower vulnerabilities may be exploited differently, but they still exist.
Ii. Vulnerability Analysis
Due to a program writing error in install. php, malicious user construction statements can be written to webshell to control the entire server.
In the last few nights, I read all the variables in the front-end file, as long as they are the variables in the database call. Check whether there is any lax filtering. After reading it, I think there are indeed a lot of lax filtering, but they are all protected by single quotes. In php, if magic_qoute_gpc = on (default), the compiler will automatically escape special characters such as single quotes, which is very difficult to change the program execution process. This greatly increases the difficulty of intrusion, and ensures its security to some extent. This is also why a friend asks that magic_qoute_gpc can still be used when it is on. If you need single quotes to exploit the vulnerability, go to Discuz! The Forum is basically useless.
After reading the database connection of all files, I did not find anything valuable. At this time, my thinking started to get a little messy. I was wondering if I should try to read all the code from the programmer's thinking logic loophole, find out what programmers are not fully aware of when writing a program. These vulnerabilities are mostly caused by incorrect context logic, or they are not unique. Some of them should be noted, however, the Administrator ignores this issue.
It seems that nothing can be left to read the code. Since the target is a logical error, you must take a closer look at the context relationship. Therefore, choose to start reading from the entry point. The entry point should be logging. php, because this is the place to log on, and everyone will log on to the Forum from here. Come on!
Old Rules: Let's look at a piece of code first:
========= Codz begin ============
50 $ errorlog = "$ username". substr ($ password, 0, 2 );
......
54 $ errorlog. = substr ($ password,-1). "$ onlineip $ timestamp ";
55 $ password = md5 ($ password );
56 $ query = $ db-> query ("SELECT m. username as discuz_user, m. password as discuz_pw, m. status, m. styleid AS styleidmem, m. lastvisit, u. groupid, u. isadmin, u. specifiedusers LIKE % $ username % AS specifieduser
FROM $ table_members m left join $ table_usergroups u ON u. specifiedusers LIKE % $ username % OR (u. status = m. status AND (u. creditshigher = 0 AND u. creditslower = 0 AND u. specifiedusers =) OR (m. credit> = u. creditshigher AND m. credit WHERE username = $ username AND password = $ password order by specifieduser DESC ");
......
69 if (! $ Discuz_user)
{
70 @ $ fp = fopen ($ discuz_root ../forumdata/illegallog. php, );
71 @ flock ($ fp, 3 );
72 @ fwrite ($ fp, $ errorlog );
73 @ fclose ($ fp );
74 showmessage (login_invalid, index. php );
}
========= Codz endz ========================
Let's take a look at this code. He first records the user name and password entered. The password only takes the first two digits, then the last one, and assigns the ip address and time together. Then, store the md5 value of the password in the database. If you think we can change the database statement execution process, it will be wrong. There is nothing we can do with single quotes (at least I can't do anything, unless it is encrypted ). If the user name and password are incorrect, the invalid user name and password will be recorded in illegallog. php. During the entire process of recording the wrong password, the variable has not been verified. That is to say, if I enter the wrong user name, it will not be checked and recorded directly. If my wrong user name is an executable code, it will be recorded. After it is recorded, we can call this file to form a shell.
Are you excited now? Sorry, your excitement is invalid. I am not excited at all, because I paid special attention to Discuz when I read it for the first time! For file handle operations, it does not filter individual variables, but it is installed. during the initialization in php, all the operations used are provided. A sentence is added at the beginning of the data file ending with php: . This is written during initialization. We should all understand the role of this sentence. You cannot call what you write, because it has ended at the beginning.
This is obviously unsuccessful. I'm a little bored. Do you think five sheep are good? Lose! I threw down the code in a bid and ran to my grandmother's house. I put my eyes on her. (It is one of my favorite tasks to play in front of my grandmother, play tricks, and make troubles) I repeatedly cursed Discuz in front of my grandmother! How can I read the code carefully. Grandma doesn't know what I'm talking about, and doesn't care if I make trouble with her. She continues watching her TV. After a while, I replied, "You are a child. You are careless and not careful at all. What code do you think you have? (it is probably code) it's broken again ". I climbed back to my room with a smile. Sitting in front of the computer, I drank a cup of boiled water and calmed down.
It is necessary to be a safe person who is careful, persevering, self-taught, and good at summing up. Go back and read the logging. php file again to see if there is anything you ignore. The file is not long. I read it again and thought it was okay. Since there is no problem here, let's put it here. How is this sentence written?
So I flipped through this code in install. php:
=========== Codz begin ============
29 function loginit ($ log ){
30 echo initialization record. $ log;
31 $ fp = @ fopen (./forumdata/illegallog. php );
32 @ fwrite ($ fp ," ");
33 @ fclose ($ fp );
34 result ();
35}
......
1389 loginit (carmalog );
1390 loginit (illegallog );
1391 loginit (modslog );
1392 loginit (cplog );
1393 dir_clear (./forumdata/templates );
1394 dir_clear (./forumdata/cache );
=========== Codz endz ============
Obviously, the loginit function is written to illegallog. php. This sentence. In this way, even if the code is written, the execution cannot be called because of the existence of the sentence. We have completely entered a dead end. However, I seem to have some problems with this code. I have read it carefully. Why is that fopen so difficult. If you remember correctly, the syntax format of fopen should be as follows:
Resource fopen (string filename, string mode [, int use_include_path [, resource zcontext])
The first two parameters are the file handle or the file to open. The second parameter specifies the open mode, such as read or write. We would like to remind you that these two parameters are required. For example, we write Jambalaya in the directory. php: fopen (. /Jambalya. php, w), which must be selected later for opening; otherwise, an error will be reported. But we noticed that there is only one parameter in his code, so how can the program be correctly executed?
Let's do a test, create a 1.php, and write the following code:
============= Codz begin ==============
$ Fp = @ fopen (./2.php );
@ Fwrite ($ fp ," ");
@ Fclose ($ fp );
Echo "success! ";
============= Codz endz ==================
Make one and Discuz here! If the program is successfully executed, a 2.php file is generated in the root directory, and the first line of 2. php is And success is displayed on the screen. In fact, success is used to let us know where the program is executed. We submitted http: // 127.0.0.1/myhome/1.php in the url. success is displayed on the screen, which indicates that it has been executed to the end of the program. But when checking the directory, we found that the file named 2. php was not generated, that is, we failed to write. You may be surprised that there should be an error message when writing fails. Yes, but because @ is added before fopen, @ is used in php to suppress all errors generated by calling functions. In other words, even if an error occurs, no error is reported.
My lessons are correct. I am so careless!
If everything passes through my ideas, it means that during the installation and initialization, The discuz/forumdata directory will never contain The code's illegallog. php file, but because of the suppression of error information, the installation will still show that the initialization is successful, but it is not initialized, not to generate illegallog. php. If no Initialization is performed here, the generation and initialization of illegallog. php will be completed in logging. php. The initialization of logging. php does not write any protection statements or filter measures to the file to avoid user calls. Everything is clear here. To put it bluntly, it is because the install. php file is incorrectly initialized. We can write malicious code through logging. php, and then call that file to generate a shell to control the entire website.
Iii. Exploitation Methods
You do not need to register any account. On the login page, enter 123456. Press enter. You may understand that the first two digits of the password are displayed, so what is saved in illegallog. php is:
* ***** 6 127.0.0.1 1022383175
You can check the php settings. Let's first check whether the register_globals setting is on. (Most websites are on) Well, then we enter It is better not to use system () Here. Many websites disabled the system () function during the test.
Then we call http: // 192.168.0.13/forumdata/illegallog. php? Cmd = dir
A bunch of junk information is coming out. Can you see at the bottom that the directory is listed? However, writing data in this way is a little troublesome, because during the experiment, there were more than 0.1 million registered users on large websites, so the file would be surprisingly large and the opening speed would be very slow.
We can write the data in this way. , We changed the php shell to a jpg image and uploaded it to the host.
Call in URL:
Http: // 192.168.0.13/forumdata/illegallog. p... chments/Jam. php
Then let's go straight