Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

We May Have Finally Fixed Python’s 25-Year-Old Vulnerability- 1767

Yehuda ChikvashviliPosted 4 Months Ago
  • Pickle, a serialization format in Python, is actually a small bytecode format that is a small interpreter. It can import modules and execute arbitrary code. Because of this, accepting pickle files as input is an automatic RCE vulnerability in your website. pickle.loads() is the sink to look for. Hugging Face had a vulnerability recently that could have been exploited this way.
  • It's crazy that a serialization format can execute arbitrary code. Imagine is JSON could do this... Pickle has been a bad security mistake for years. So, this post is about trying to fix the security of Pickle in Python!
  • Taint analysis is a strategy to use static code analysis tools to track the flow of untrusted data. In this case, they're trying to use taint analysis into a runtime domain for Python pickle deserialization. The key insight is that if there is a dangerous operation during deserialization, then we can block it. This requires two important things: a hook into dangerous calls and context awareness (are we in a deserialization or not).
  • PEP 578 is Python Audit Hooks. It's a great for auditing Python execution at runtime with custom hooks. Things like os.system can be hooked. This part is super easy once we know what's a well-defined "bad sink". PEP 567 has context variables for thread-local state. This can be placed as taint to specify whether the execution is within Pickle or not. This doesn't work in our case because the taint variable could be modified by the runtime itself. So, it was added at the CPython level, making it impossible to alter. Another alternative was to inspect the call stack. However, this has really bad performance penalties and has zero introspective of C code.
  • Using the audit hooks, it's possible to monitor for security sensitive operations. There is a set of strncmp() with various packages being checked. For instance, os., ctypes. and many others. This blacklist approach works well but broke a bunch of things. The initial version of this blacklist had easy evasion vectors via using global hooks. Many things still had issues, like multiprocessing. Finally, some calls were unaudited for some attributes and not others, making it incomplete. So, back to the drawing board!
  • Almost all sensitive operations appear during the import mechanism. By distinguishing between import related events and other operations, it would create a nice boundary. On the actual execution of bytecode, they were then able to use a whitelist of very specific audit events that have no impact. So, this solves the security problem! This has the limitation that it relies on an audit.
  • They do something unique at the end though: they have a Pickle sandbox with these protections and are asking researchers to escape! I really like this idea, as it gives people a chance to test the security of Pickle. Great article!