CVE-2023-3033

This walkthrough presents another vulnerability discovered on the Mobatime web application (see CVE-2023-3032, same version 06.7.2022 affected). This vulnerability allows an authenticated user to impersonate another one, possibly having more privileges.

Authorisation mechanism

This application is essentially a single page, and the pieces of information are retrieved through AJAX calls. To get adequate pieces of information, the requests carry the user identifier, in order to fetch data related to them. The issue is that this identifier is controlled by the user, and the request body is not protected. It is therefore possible to change this identifier, and impersonate someone else.

A typical AJAX call is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
POST /Webengine/api/ajax_api.aspx HTTP/1.1 Accept: */*
Accept-Encoding: gzip, deflate, br
... snipped ...
Sec-GPC: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0
Safari/537.36 X-Requested-With: XMLHttpRequest

@64eyJhcnJheV9pbnQiOltdLCJmdW5jdGlvbiI6NTA3LCJpcGFyYW0xIjoxNTQsImlwYX
JhbTEwIjowLCJpcGFyYW0xMSI6MCwiaXBhcmFtMTIiOjAsImlwYXJhbTEzIjowLCJpcGF
yYW0xNCI6MCwiaXBhcmFtMTUiOjAsImlwYXJhbTIiOjg0MTUsImlwYXJhbTMiOjAsImlw
YXJhbTQiOjAsImlwYXJhbTUiOjAsImlwYXJhbTYiOjAsImlwYXJhbTciOjAsImlwYXJhb
TgiOjAsImlwYXJhbTkiOjAsImxwYXJhbTEiOjAsInBhcmFtMSI6IiIsInBhcmFtMiI6Ii
IsInBhcmFtMyI6IiIsInBhcmFtNCI6IiIsInBhcmFtNSI6IiIsInRva2VuIjowfQ==

One can recognise here a base64-encoded JSON (prefix eyJ), which gives us, once decoded:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
"array_int":[],
"function":507,
"iparam1":154,
"iparam10":0,
"iparam11":0,
"iparam12":0,
"iparam13":0,
"iparam14":0,
"iparam15":0,
"iparam2":8415,
"iparam3":0,
"iparam4":0,
"iparam5":0,
"iparam6":0,
"iparam7":0,
"iparam8":0,
"iparam9":0,
"lparam1":0,
"param1":"",
"param2":"","
param3":"",
"param4":"",
"param5":"",
"token":0
}

Now, let’s assume that our ID is 154, and that we want to impersonate 155. Keen eye may see that the payload is not signed, hence forgeable. Since the application is a single page, it was likely that this value 154 was carried by a JS variable, and that we could change it at a single place. All subsequent AJAX calls would probably embed the modified ID, and make us act as 155.

Hunting the identifier

Analysing the traffic reveals that the AJAX requests originate from a call to the routine Get in the file MobaBridge3.js. One can suppose here that this routine probably deals with the JSON payload so as to authenticated the request:

trace.png

debug.png

A breakpoint was therefore put at line 1’316, before the function end. Refreshing the page reveals that the attribute this._param holds the value 154. It comes from the second argument (param). Since the value 154 was already known there, one can step over LaunchThread to get back to the calling routine ($ctor1).

dataapi.png

In this routine, a call to Get is indeed performed, and the second argument containing the identifier is referred to as s. The variable s is obtained thanks to a call to JsonConvert.SerializeObject, hence was likely to be built based on the variable function (line 17). The latter is passed as argument (line 13), and to analyse it, one should once again climb up the calling stack.

dataapi1.png

The caller lies in the class MensualView.cs, where the func variable is initialised (passed as function in the callee). It is worth noting that one of the attributes of func is named iparam1, just like the attribute carrying the identifier in the JSON stream. Its value is held by the attribute Workflow.pid. By looking where such variable is set thanks to a regular expression, only two results are returned. One of them lies on the class LoginLinkWorkflow.cs

loginlinkworkflow.cs.png

By putting a breakpoint at line 139 and refreshing the page, the breakpoint is hit. The value of the variable PId could be turned into 155, and letting the execution flow continue normally, and the page would be rendered as if we were 155.

Conclusion

Since only the advertised identifier seems to be used to verify the authorisations, a malicious user could trick the application into thinking that they are someone else by changing their ID on the client side. Since the server trusts this ID, they would serve inappropriate content. The server should use server-side variables to store the ID of a user, based on a session identifier. An alternative could make use of signed JWTs to make them inalterable.