Introduction

In graphite-web version between 0.9.5 and 0.9.10, a vulnerability exists as a result of unsafe use of the “pickle” module by the product.

The Common Vulnerabilities and Exposures (CVE) project has assigned the name CVE-2013-5093 to this issue. This is an entry on the CVE list (http://cve.mitre.org), which standardizes names for security problems.

Timeline

2013-08-06 – Vendor contacted

2013-08-06 – Vendor confirms issue

2013-08-07 – Sent CVE request, CVE-2013-5093 is assigned

2013-08-20 – Graphite 0.9.11 released

2013-08-20 – Advisory released

Analysis

In graphite-web 0.9.5, a “clustering” feature was introduced to allow for scaling for a graphite setup. This was achieved by passing pickles between servers, and it was introduced in this commit.

The function “renderLocalView”, seen below, takes a request that contains a chart type, and a pickle:

def renderLocalView(request): try: start = time() reqParams = StringIO(request.raw_post_data) graphType = reqParams.readline().strip() optionsPickle = reqParams.read() reqParams.close() graphClass = GraphTypes[graphType] options = pickle.loads(optionsPickle) image = doImageRender(graphClass, options) log.rendering("Delegated rendering request took %.6f seconds" % (time() - start)) return buildResponse(image) except: log.exception("Exception in web.render.views.rawrender") return HttpResponseServerError() 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 def renderLocalView ( request ) : try : start = time ( ) reqParams = StringIO ( request . raw_post_data ) graphType = reqParams . readline ( ) . strip ( ) optionsPickle = reqParams . read ( ) reqParams . close ( ) graphClass = GraphTypes [ graphType ] options = pickle . loads ( optionsPickle ) image = doImageRender ( graphClass , options ) log . rendering ( "Delegated rendering request took %.6f seconds" % ( time ( ) - start ) ) return buildResponse ( image ) except : log . exception ( "Exception in web.render.views.rawrender" ) return HttpResponseServerError ( )

However due to no explicit safety measures having been implemented to limit the types of objects that can be unpickled, this creates a condition where arbitrary code can be executed, as has been documented by Nelson Elhage.

Proof of concept

The proof of concept can be found as a part of the Metasploit Framework graphite_pickle_exec module.