A Logo

Feel free to include my content in your page via my
RSS feed

Help Irongeek.com pay for
bandwidth and research equipment:

Subscribestar or Patreon

Search Irongeek.com:

Irongeek Button
Social-engineer-training Button

Help Irongeek.com pay for bandwidth and research equipment:


Mutillidae: A Deliberately Vulnerable Set Of PHP Scripts That Implement The OWASP Top 10

Mutillidae: A Deliberately Vulnerable Set Of PHP Scripts That Implement The OWASP Top 10

Newer version of this page moved to:

         As I figure most people reading this know, I make infosec video tutorials for my site Irongeek.com. I wanted to start covering more web application pen-testing tools and concepts in some of these videos. Of course, I needed a vulnerable web app or two to use for these demos. I dig WebGoat, but sometimes it's a little hard to figure out exactly what they want you to do to exploit a given web application. Also, WebGoat may be a little too complex to use when introducing a web programming newbie to web application security (it's easy to get lost in the code, especially J2EE). In an attempt to have something to use as a demo in my videos and in class, I started the Mutillidae project.

        What I'm attempting to do with Mutillidae is implement the OWASP Top 10 in PHP, and do it in such a way that it is easy to demonstrate common attacks to others. Feel free to use it in your own classes or videos, but if you do I'd love to hear about it. Many web app hobbyists and professionals used PHP, and it's pretty easy to pick up the basics of the language. The Mutillidae webpage is a set of relatively simple PHP scripts meant to illustrate the core concepts of the OWASP Top 10 vulnerabilities list. For the sake of teaching core concepts, I plan to implement all of the OWASP Top 10 vulnerabilities in multiple ways (but I could always use some help, especially in writing the hints sections).


        Mutillidae implements the OWASP Top 10 in PHP. Feel free to use it in your own classes or videos, but if you do I'd love to hear about it.


1. Make the code and examples simple to understand so as to get the point across of how a given vulnerability works.
2. Be geared in such a way that it's easy to update with new modules and hints.
3. Easy to install and run. Just download XAMPP Lite for Windows or Linux, put the scripts in the htdocs directory, and click the "Setup/reset the DB" link in the main menu .


Go to the OWASP Top 10  page to read about a vulnerability, then choose it from the list on the left to try it out.

Mutillidae currently has two modes: secure and insecure (default). In insecure mode, the project works like Mutillidae 1.0. Pages are vulnerable to at least the topic they fall under in the menu. Most pages are vulnerable to much more. In secure mode, Mutillidae attempts to protect the pages with server side scripts. Also, hints are disabled in secure mode. In the interest of makign as many challenges as possible, this can be defeated. In Mutillidae 2.0, the code has been commented to allow the user to see how the defense works. To get the most out of the project, avoid reading the source code until after learning how to exploit it. But if you get stuck, the comments should help. Learning how the attack works should help to understand the defense.


  1. Extract the files somewhere in the htdocs folder of of XAMPP (for example htdocs/mutillidae), or run it from your Linux box after installing Apache/PHP/MySQL.
  2. By default, Mutillidae trys to connect to MySQL on the localhost with the username "root" and a blank password. To change this, edit "config.inc" with the correct information for your environment.
  3. Do NOT  run this code on a production network. Either run it on a private network, or restrict your web server software to only use the local loopback address. By default Mutillidae only allows access from localhost (127.*.*.*). Edit the .htaccess file to change this behavior (not recommended on a public network). If for some reason .htaccess is not parsed you can restrict the IP by finding the "Listen" line in the http.conf file and changing it to read: Listen
  4. Get rid of PHP "strict" errors. They are not compatible with the OWASP ESAPI classes in use in Mutillidae 2.0. The error modifies headers disrupting functionality so this is not simply an annoyance issue. To do this, go to the PHP.INI file (default location C:\xampp\php\php.ini) and change the line that reads "error_reporting = E_ALL | E_STRICT" to "error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECIATED".
  5. Once PHP 6.0 arrives in XAMPP, E_ALL will include E_STRICT so the line to change will probably read "error_reporting = E_ALL". In any case, change the error_reporting line to "error_reporting = E_ALL & ~E_NOTICE & ~E_DEPRECIATED".


Among the fun things that Mutillidae implements from the OWASP top 10 are:

OWASP Top 10 2010

A1 - Injection (SQL and Command)
A2 - Cross Site Scripting (XSS)
A3 - Broken Authentication and Session Management
A4 - Insecure Direct Object References
A5 - Cross Site Request Forgery (CSRF)
A6 - Security Misconfiguration
A7 - Insecure Cryptographic Storage
A8 - Failure to Restrict URL Access
A9 - Insufficient Transport Layer Protection
A10 - Unvalidated Redirects and Forwards

Items from the 2007 OWASP Top 10 that do not correlate to the 2010 list

A3 - Malicious File Execution
A6 - Information Leakage and Improper Error Handling

Video Series using Mutillidae :

Mutillidae 1: Setup
Mutillidae 2: The Top 5


Change log:

06/21/2011: Jeremy Druin

Change Log for Mutillidae 2.0.9:

  • Added new menu items under SQLi for SQLi Insert Injection
  • Added new menu item for documentation
  • Moved constants into constants.php file
  • Patched tabbing in home.htm
  • Added additional instructions on supressing PHP errors with XamppLite. Thanks to Miguel Wherner for the tip.

06/15/2011: Jeremy Druin

Change Log for Mutillidae 2.0.8:

  • Added more comments to the code to explain how defenses work
  • Added support for the <u></u> tag to the blog. In secure mode Mutillidae will allow this tag but still safely encode output and stop XSS.
  • Added JavaScript filtering to prevent single quotes from being entered in blog entries. This give practice bypassing JavaScript "security" and helps the user understand JavaScript cannot provide security.
  • Added lots of JS filtering to login.php. Nearly all characters are filtered. Users are encouraged to understand that JavaScript and filtering are useless for security.
  • Added autofocus to login.php and add-to-blog.php
  • Added more "allowed dangerous HTML tags" to the blog. Until now only the bold HTML tag was supported. Also the output was not HTML5 compliant. For example, if the user entered a bold tag, then a bold tag was output however the bold tag is depreciated. Styles must be used. So Mutillidae allows the user to input a bold tag but will correctly encode this as a sytle upon output. The italic tag is now supported as a dangerous input which is safely output without fear of Cross Site Scripting. These defenses only operate in secure mode of course. In insecure mode, the site allows any input and simply outputs whatever is input without any encoding.
  • Changed menu for OWASP A1 - Injection to differentiate between SQL, HTML, and Command Injection. This should make it more clear which pages exhibit vulnerabilities with the specific injecton sub-types. Also added new link for Blind SQL Injection.
  • Changed menu for OWASP A2 - Cross Site Scripting to differentiate between XSS coming in via user supplied fields (GET/POST) and values within HTTP Request Headers.
  • Added tutorials feature.
  • Added SQL Injection Totorial
  • Added Cross Site Scripting tutorial
  • Added Command Injection tutorial
  • Added new feature. Hints can now be at different levels. Each time the user clicks Hints, the level increases by 1 until rolling over.
  • Removed the installation instructions from the home page. A new page for instructions is created and linked from the menu.
  • Augmented the installation instructions to include running from Samurai, creating a custom ISO, installing to XAMPP, and running in virutal machines.
  • Reformatted install instructions and main home page to be compliant with HTML 5


05/22/2011: Jeremy Druin

Change Log for Mutillidae 2.0.7:

  • Added a new page rene-magritte.php to explore click-jacking. In secure mode, Mutillidae will send the X-FRAME-OPTIONS: DENY header. In modern browsers, this will cause the browser to throw an error rather than allow the page rene-magritte.php to be framed.
  • Added a resources link to the main menu. Links are to information or tools that can help with testing Mutillidae.
  • Added new class LogHandler to take over logging. Previously logging statements has to be copied to each spot that logging was needed. With the new class, logging requires only one line of code and the logger automatically logs based on the current security level. If in insecure mode, no attempt to stop XSS or SQLi is made. With the new class, many less lines of code are needed and many more places log. With more places logging, there is a much better chance of finding a log exploit and taking advantage (insecure mode). Logging added to pages: add-to-your-blog, dns-lookup, text-file-viewer, source-viewer.php, register.php, redirectandlog.php, and user-info.php
  • Added more default users to initial setup to give more targets.


05/10/2011: Jeremy Druin

Change Log for Mutillidae 2.0.6:

  • Added a new security vulnerability and counteracting secure code. The "business requirements" for the add-new-blog-entry page now require users to be able to enter a bold tag in their blog. In secure mode, Mutillidae allows this functionality while still protecting the users from mallicous injection input.
  • A new secret page has been added. There are lots of test scripts that the developers used to hack Mutillidae inside. It will be very hard to guess the name of the file but there are plenty of vulns that will allow users to locate and open the file.


04/24/2011: Jeremy Druin

Change Log for Mutillidae 2.0.6:

  • Added a new security vulnerability and counteracting secure code. Cookies are unprotected in insecure mode, but in secure mode, the cookies will have the HTTPOnly attribute applied to them. In reality this vulnerability was always in Mutillidae since ignoring the issue opens the vulnerability (the ability for scripts to access the cookie values). The change is acknowleging this issue and adding the defense. Once we get an SSL certificate installed, the next logical step will be to add the "Secure" attribute to cookies in secure mode, but to not add this attribute in insecure mode.
  • Added the X-FRAME-OPTIONS: DENY click-jacking defense in secure mode. In insecure mode, the site does nothing and ignores the issue entirely. This defense only works in newer browsers and javascript framebusters are needed to help older browsers.
  • Added insecure comments vulnerability and defense. Some developers use HTML or JavaScript comments instead of using the frameworks comments (ASP.NET, Java, PHP, Etc.)
  • Rearranged instructions on home page to emphasize the PHP.ini configuration changes that are needed to get rid of errors.
  • Rewrote opendb.inc to have error trapping and custom error handling. If there is an error, there will be some diagnistic information available.


04/14/2011: Jeremy Druin

Change Log for Mutillidae 2.0.5 Beta:

  • browser-info.php - Patched a bug which disabled entire page if the whois server is not reachable. Now only that one line will be disabled. Also replaced Windows style file path slashes with Unix style. Either slash will work in Windows but Linux only accepts the Unix style path else throws an error.

04/13/2011: Jeremy Druin

Change Log for Mutillidae 2.0.4 Beta:

  • user-info.php - Added XSS defenses to the output so that users cannot poison their username, password or signature to cause XSS. This only works in secure code.
  • register.php - Added XSS defenses to the output so that users cannot poison their username to cause XSS. This only works in secure code.
  • header.php - Added link to this changelog. Changed style of upper header to allow more space for logged in user text. In very small screens, the text was overlapping. Also, the size of the mascot image was reduced to give the user more screen space.
  • change-log.php - Added new XSS vulnerability for users to try.


            Small change to fix source-viewer.php.

03/30/2011: Jeremy Druin

Change Log for Mutillidae 2.0.3 Beta:

  • index.php - Added PHP version detection and altered forms caching defenses and server header information defenses to use header_remove() only if the version of PHP is at 5.3 or above. Made version string variable that contains whatever version string is for Mutillidae plus "nice" output. Samurai is going through a PHP version change to 5.3 right now and XAMPP just went through the same change. This code is meant to bridge users caught between versions.
  • header.php - Made version output simpler. header.php only outputs the header string.
  • footer.php - Added PHP version to footer output in insecure mode. In secure mode, server version is not shown.

03/25/2011: Jeremy Druin

Change Log for Mutillidae 2.0.2 Beta:

Whole site

  • Made local relative links without leading dot
  • Installed on Samurai 0.95 for testing. Found that Samurai doesnt like the leading dot in local file paths. Those were removed from the index.php page.
  • Made version a variable in index.php to make updating version string easier
  • Added new forms caching information leakage vulnerability
  • Added new vulnerability for X-Powered-By and discussed removing the Server HTTP header in comments

 03/24/2011: Jeremy Druin

Change Log for Mutillidae 2.0.1 Beta:

Whole site

  • Replaced root relative links with local relative links to allow more freedom in root folder name
  • Added email address for Jeremy
  • Added change log to site
  • Added Toggle Hints into core menu but link disappears in secure mode
  • Added new failure to restrict URL access vuln

03/23/2011: Jeremy Druin, a professional developer (unlike me) added sooooooo many new features to the project. To quote him:

Change Log for Mutillidae 2.0 Beta:

Whole site

  • Site implements the OWASP ESAPI API for PHP including showing how to instantiate classes and call methods for output encoding.
  • Site now allows user to switch between secure and insecure mode to allow the user to employ an attack then try the same attack against more secure code
  • All code for both modes of operation are available for inspection and include large amounts of explanation comments for both the insecure and secure sections. Code is commented in such a way to help developers understand the security concepts as opposed to only seeing the PHP implementation
  • Added custom error handling to site which reacts differently depending on security mode
  • Site has larger hint sections with more hints included
  • Added menuing system for easier navigation
  • Added toolbar at top of each page for critical functions (hints, security mode, home page, etc.)
  • Converted styles to CSS
  • Collected images into single folder
  • Added links to helpful tools and sites with more information: OWASP, Toad for PHP, Eclipse PDT, Samurai WTF, and Backtrack 4 R2
  • Released new web interface design and navigation for each page
  • Installed TRY/CATCH handling in all pages


  • additional reflected XSS vuln added
  • SQLi vector added
  • additional stored XSS vuln added
  • demonstrates output encoding
  • demonstrates SQLi prevention
  • non-input box attack vector added


  • demonstrates safer JavaScript
  • created ClientInformationHandler class to gather client information
  • demonstrates output encoding
  • added JavaScript attack vector using innerHTML


  • added Insecure Direct Object Reference defenses


  • In secure mode, added strong server-side validation for page. Page allows both ip based and DNS name based attacks and includes defenses for both.


  • added new attack vector to allow refelected XSS via HTTP headers
  • added defenses for input coming from HTTP headers
  • added comments encouraging developers to treat ALL input as evil and not just the input boxes they created


  • Replaced menu with mouseover navagation and updated menu with new attacks
  • Added new stored cross site scripting attacks and defenses
  • Added code to allow site to ignore user created cookies in secure mode and react to user created cookies in insecure mode


  • Added instructions
  • Added warning about PHP.ini files that come with new XAMPP/PHP versions 5.3 and 6.0 (future)


  • Created newly formatted hints section


  • Created new processing framework
  • Added the ability to use session storage
  • Installed initialization code


  • added HTML maxlength to allow practice of circumventing trivial and useless HTML based defenses
  • Added detection of whether user is currently logged in with new funcitonality. Site will auto-detect when users are logged in and change links appropriately
  • Added new reflected XSS vector


  • new file which collects all "do" commands together
  • installed several new attack vectors and defenses based on the "do" commands


  • Created new HTTP parameter pollution attack
  • Installed advanced mapping defences with validation
  • Installed strong validation defenses


  • installed SQLi and XSS defenses
  • reformatted page with new design and error feedback


  • installed DOS defenses
  • added DOS attack vector
  • installed tabular output
  • added defenses for injection attacks and XSS
  • added attack vector against log


  • Added/augmented attack vectors
  • Added new attack vectors to allow loading of local server files
  • Filename injection (Insecure Direct Object Reference)
  • SQL Injection, (Fix: Use Schematized Stored Procedures)
  • Cross Site Scripting, (Fix: Encode all output)
  • Cross Site Request Forgery, (Fix: Tokenize transactions)
  • Insecure Direct Object Reference, (Fix: Tokenize Object References)
  • Denial of Service, (Fix: Truncate Log Queries)
  • Loading of Local Files, (Fix: Tokenize Object Reference - Filename references in this case)
  • Improper Error Handling, (Fix: Employ custom error handler)
  • SQL Exception, (Fix: Employ custom error handler)
  • HTTP Parameter Pollution (Fix: Scope request variables)
  • Added mapping defenses


  • added SQL and XSS defenses
  • added tabular output


  • installed SQLi and XSS defenses
  • installed trivial and useless "tokens" to allow user to bypass HTML code which intends to confuse instead of defend.

06/16/2010: I changed it so that now, by default, Mutillidae only allows access from localhost (127.*.*.*), assuming the .htaccess file I've written is honored. Thanks for the suggestion Kevin. I've also made the install instructions somewhat better.

04/29/2010: Updated to version 1.4 to make Mutillidae compliant with the 2010 version of the OWASP Top 10. Also added some modules, and fixed a bug I must have introduced at some point that keeps the user from inserting a single quote into their blog.

09/03/2009: I found out that my little teaching app stopped working with new versions of XAMPP. It seems I have to use <?php to start my PHP tags, using just <? no longer worked. I've updated Mutillidae to 1.3 and made it work again.

04/29/2009: Added link to first  Mutillidae video.

03/18/2009: Added the activity log section so I could show off stored user agent XSS, added information on cookie stealing with XSS to the tips section, added catch.php to show how to grab data after an XSS and did a few other minor little tweaks. Also, I changed some of the text around to include the "Ate up with suck" slogan.

03/18/2009: Thanks to Seth Misenar and the Pauldotcom guys for giving me the new tagline for this project: "Ate up with suck".

03/02/2009: Changed the comment system into a blog, and straighten up some code.

03/01/2009: First posted to the public.

Printable version of this article

15 most recent posts on Irongeek.com:

If you would like to republish one of the articles from this site on your webpage or print journal please contact IronGeek.

Copyright 2020, IronGeek
Louisville / Kentuckiana Information Security Enthusiast