Ecmall: a third round of SQL Injection
Although the anti-injection code is added to the anti-injection patch of 20140618, it can be barely bypassed.
In app/my_goods.app.php
Function edit ()
{
$ Id = empty ($ _ GET ['id'])? 0: intval ($ _ GET ['id']);
If (! IS_POST)
{
$ This-> assign ('goods ', $ this-> _ get_goods_info ($ id ));
/* Obtain the product category */
$ This-> assign ('mgcategories ', $ this-> _ get_mgcategory_options (0); // level 1 of mall category
$ This-> assign ('sgcategories ', $ this-> _ get_sgcategory_options (); // store category
/* Current page information */
$ This-> _ curlocal (LANG: get ('Member _ Center'), 'index. php? App = member ',
LANG: get ('My _ goods '), 'index. php? App = my_goods ',
LANG: get ('goods _ list '));
$ This-> _ curitem ('My _ goods ');
$ This-> _ curmenu ('edit _ goods ');
$ This-> assign ('page _ title', Lang: get ('Member _ Center'). Lang: get ('My _ goods '));
$ This-> import_resource (array ('script' => 'mlselection. js, jqtreetable. js, jquery. plugins/jquery. validate. js ',
'Style' => 'jqtreetable.css '));
/* WYSIWYG editor */
$ This-> assign ('build _ editor', $ this-> _ build_editor (array ('name' => 'description ')));
$ This-> display('my_goods.form.html ');
}
Else
{
/* Obtain data */
$ Data = $ this-> _ get_post_data ($ id );
/* Check Data */
If (! $ This-> _ check_post_data ($ data, $ id ))
{
$ This-> show_warning ($ this-> get_error ());
Return;
}
/* Save the product */
If (! $ This-> _ save_post_data ($ data, $ id ))
{
$ This-> show_warning ($ this-> get_error ());
Return;
}
Follow up on this function _ save_post_data
Function _ save_post_data ($ data, $ id = 0)
{
Import ('image. func ');
Import ('uploader. lib ');
If ($ data ['goods'] ['tags'])
{
$ Data ['goods'] ['tags'] = $ this-> _ format_goods_tags ($ data ['goods'] ['tags']);
}
/* Save the product */
If ($ id> 0)
{
// Edit
If (! $ This-> _ goods_mod-> edit ($ id, $ data ['goods'])
{
$ This-> _ error ($ this-> _ goods_mod-> get_error ());
Return false;
}
$ Goods_id = $ id;
}
Else
{
// Add
$ Goods_id = $ this-> _ goods_mod-> add ($ data ['goods']);
If (! $ Goods_id)
{
$ This-> _ error ($ this-> _ goods_mod-> get_error ());
Return false;
}
If ($ data ['goods _ file_id '] | $ data ['desc _ file_id'])
{
$ Uploadfiles = array_merge ($ data ['goods _ file_id '], $ data ['desc _ file_id']);
$ This-> _ uploadedfile_mod-> edit (db_create_in ($ uploadfiles, 'file _ id'), array ('item _ id' => $ goods_id ));
}
If (! Empty ($ data ['goods _ file_id '])
{
$ This-> _ image_mod-> edit (db_create_in ($ data ['goods _ file_id '], 'file _ id '), array ('goods _ id' => $ goods_id ));
}
}
/* Save specifications */
If ($ id> 0)
{
/* Deleted specifications */
$ Goods_specs = $ this-> _ spec_mod-> find (array (
'Condition' => "goods_id = '{$ id }'",
'Fields' => 'spec _ id'
));
$ Drop_spec_ids = array_diff (array_keys ($ goods_specs), array_keys ($ data ['specs']);
If (! Empty ($ drop_spec_ids ))
{
$ This-> _ spec_mod-> drop ($ drop_spec_ids );
}
}
$ Default_spec = array (); // initialize the default Specification
Foreach ($ data ['specs'] as $ key => $ spec)
{
If ($ spec_id = $ spec ['spec _ id']) // update an existing specification id
{
$ This-> _ spec_mod-> edit ($ spec_id, $ spec );
}
Else // newly added specification ID
{
$ Spec ['goods _ id'] = $ goods_id;
$ Spec_id = $ this-> _ spec_mod-> add ($ spec );
}
If (empty ($ default_spec ))
{
$ Default_spec = array ('default _ spec '=> $ spec_id, 'price' => $ spec ['price']);
}
}
/* Update the default specification */
$ This-> _ goods_mod-> edit ($ goods_id, $ default_spec );
If ($ this-> _ goods_mod-> has_error ())
{
$ This-> _ error ($ this-> _ goods_mod-> get_error ());
Return false;
}
/* Save the product category */
$ This-> _ goods_mod-> unlinkRelation ('belongs _ to_gcategory ', $ goods_id );
If ($ data ['cates'])
{
$ This-> _ goods_mod-> createRelation ('belongs _ to_gcategory ', $ goods_id, $ data ['cates']);
}
/* Set the default image */
If (isset ($ data ['goods _ file_id '] [0])
{
$ Default_image = $ this-> _ image_mod-> get (array (
'Fields' => 'thumbnail ',
'Condition' => "goods_id = '$ goods_id' AND file_id = '{$ data [goods_file_id] [0]}'",
));
$ This-> _ image_mod-> edit ("goods_id = $ goods_id", array ('sort _ order' => 255 ));
$ This-> _ image_mod-> edit ("goods_id = $ goods_id AND file_id = '{$ data [goods_file_id] [0]}'", array ('sort _ order' => 1 ));
}
$ This-> _ goods_mod-> edit ($ goods_id, array (
'Default _ image' => $ default_image? $ Default_image ['thumbnail ']: '',
));
First, let's look at this function.
$default_image = $this->_image_mod->get(array(
'fields' => 'thumbnail',
'conditions' => "goods_id = '$goods_id' AND file_id = '{$data[goods_file_id][0]}'",
));
$ Default_image: this variable can be seen from the warehouse to see where the Warehouse is stored.
First register a member to publish a product and then
Writing payload directly to the image address will be escaped, but it will be stored in the database and not renamed.
$default_image = $this->_image_mod->get(array(
'fields' => 'thumbnail',
'conditions' => "goods_id = '$goods_id' AND file_id = '{$data[goods_file_id][0]}'",
));
$this->_image_mod->edit("goods_id = $goods_id", array('sort_order' => 255));
$this->_image_mod->edit("goods_id = $goods_id AND file_id = '{$data[goods_file_id][0]}'", array('sort_order' => 1));
}
$this->_goods_mod->edit($goods_id, array(
'default_image' => $default_image ? $default_image['thumbnail'] : '',
));
You can see that after $ default_image is released
$ This-> _ goods_mod-> edit ($ goods_id, array (
'Default _ image' => $ default_image? $ Default_image ['thumbnail ']: '',
Directly into the edit function, resulting in secondary injection.
Here, when we edit this item, the warehouse is exported, causing injection.
Data Output successfully