From f8c299c85865f192a4b122238d07a0574e263c32 Mon Sep 17 00:00:00 2001 From: wmayer Date: Tue, 3 Jul 2012 14:32:19 +0200 Subject: [PATCH] 0000762: cPickle allows to trigger arbitrary code execution from FCStd file --- src/App/PropertyPythonObject.cpp | 49 +++++++++++++++++++++++++++++++- src/App/PropertyPythonObject.h | 1 + 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/App/PropertyPythonObject.cpp b/src/App/PropertyPythonObject.cpp index b461075ca..611122f2a 100644 --- a/src/App/PropertyPythonObject.cpp +++ b/src/App/PropertyPythonObject.cpp @@ -35,6 +35,7 @@ #include #include #include +#include using namespace App; @@ -134,6 +135,31 @@ void PropertyPythonObject::fromString(const std::string& repr) } } +void PropertyPythonObject::loadPickle(const std::string& str) +{ + // find the custom attributes and restore them + try { + std::string buffer = str; + boost::regex pickle("S'(\\w+)'.+S'(\\w+)'\\n"); + boost::match_results what; + std::string::const_iterator start, end; + start = buffer.begin(); + end = buffer.end(); + while (boost::regex_search(start, end, what, pickle)) { + std::string key = std::string(what[1].first, what[1].second); + std::string val = std::string(what[2].first, what[2].second); + this->object.setAttr(key, Py::String(val)); + buffer = std::string(what[2].second, end); + start = buffer.begin(); + end = buffer.end(); + } + } + catch (Py::Exception&) { + Base::PyException e; // extract the Python error text + Base::Console().Warning("PropertyPythonObject::loadPickle: %s\n", e.what()); + } +} + std::string PropertyPythonObject::encodeValue(const std::string& str) const { std::string tmp; @@ -264,6 +290,8 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader) reader.addFile(file.c_str(),this); } else { + bool load_json=false; + bool load_pickle=false; std::string buffer = reader.getAttribute("value"); if (reader.hasAttribute("encoded") && strcmp(reader.getAttribute("encoded"),"yes") == 0) { @@ -274,9 +302,23 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader) } try { + boost::regex pickle("^\\(i(\\w+)\\n(\\w+)\\n"); + boost::match_results what; + std::string::const_iterator start, end; + start = buffer.begin(); + end = buffer.end(); if (reader.hasAttribute("module") && reader.hasAttribute("class")) { Py::Module mod(PyImport_ImportModule(reader.getAttribute("module")),true); this->object = PyInstance_NewRaw(mod.getAttr(reader.getAttribute("class")).ptr(), 0); + load_json = true; + } + else if (boost::regex_search(start, end, what, pickle)) { + std::string nam = std::string(what[1].first, what[1].second); + std::string cls = std::string(what[2].first, what[2].second); + Py::Module mod(PyImport_ImportModule(nam.c_str()),true); + this->object = PyInstance_NewRaw(mod.getAttr(cls).ptr(), 0); + load_pickle = true; + buffer = std::string(what[2].second, end); } } catch (Py::Exception&) { @@ -285,7 +327,12 @@ void PropertyPythonObject::Restore(Base::XMLReader &reader) } aboutToSetValue(); - this->fromString(buffer); + if (load_json) + this->fromString(buffer); + else if (load_pickle) + this->loadPickle(buffer); + else + Base::Console().Warning("PropertyPythonObject::Restore: unsupported serialisation: %s\n", buffer); restoreObject(reader); hasSetValue(); } diff --git a/src/App/PropertyPythonObject.h b/src/App/PropertyPythonObject.h index 381929995..bd4bec933 100644 --- a/src/App/PropertyPythonObject.h +++ b/src/App/PropertyPythonObject.h @@ -77,6 +77,7 @@ private: void restoreObject(Base::XMLReader &reader); std::string encodeValue(const std::string& str) const; std::string decodeValue(const std::string& str) const; + void loadPickle(const std::string& str); Py::Object object; };