0000762: cPickle allows to trigger arbitrary code execution from FCStd file

This commit is contained in:
wmayer 2012-07-03 14:32:19 +02:00
parent b7ed88ad77
commit f8c299c858
2 changed files with 49 additions and 1 deletions

View File

@ -35,6 +35,7 @@
#include <Base/Console.h>
#include <Base/Interpreter.h>
#include <iostream>
#include <boost/regex.hpp>
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<std::string::const_iterator> 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<std::string::const_iterator> 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();
}

View File

@ -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;
};