Page MenuHomeFeedback Tracker

[SECURITY] concerns in MP
New, WishlistPublic

Description

The following code has been tested in dedicated server environment and all works.

The premise.

It is not unfeasible to think that even with security measures like Battleye and Steam own protection someone would still be able to run custom code on their client at some point. If the malicious code effect is only limited to the client then it could be treated as minor inconvenience. However if the hacker is able to execute the code globally on every PC, this becomes a serious problem. Having access to the server this way is a massive security concern.

What we have now.

There are at least 3 ways the hacker can exploit the system right now to execute his code globally.

  1. Old unit creation command which allows to have init param executed globally. A similar problem existed with vehicleInit command, which has been removed for this very reason, yet the old create unit format exists and thrives. The only backwards compatibility it offers is for the hacker to run his hacks with ease, considering this hack trick is one of the oldest.

Example:

Hacker runs this code on client once:
"Rabbit_F" createUnit [[0,0,0], group player, "'hack' addPublicVariableEventHandler {call (_this select 1)}"];

And then can repeatedly execute his malicious code with:
hack = {/*hackedcode*/}; publicVariable "hack";

Solutions:

a. Remove this format completely. createUnit_array is a good alternative and uses the same format as createAgent and createVehicle
b. Make init param require name of the function, so instead of (call compile "") make it (execVM "")

  1. Global MP event handlers. Code in MPKilled, MPHit and MPRespawn EH is executed globally (MPRespawn is bugged atm and server execution is excluded from it). So by attaching a MP event handler to his unit and dying hacker can plant his base code on every PC.

Example:

Hacker runs this code on client once then kills himself:
player addMPEventHandler ["MPKilled", "'hack2' addPublicVariableEventHandler {call (_this select 1)}"];

He then can repeatedly execute his code with:
hack2 = {/*hackedcode*/}; publicVariable "hack2";

Solutions:

a. Limit EH execution to the PC it was set on, just like many other EH can already do. i.e. change effect from global to local.
b. Make it require and call function name instead of code.

  1. While BIS_fnc_MP is pretty well written and only allows of passing function name instead of code, what good is it if BIS officially provides 2 functions (bis_fnc_spawn and bis_fnc_call) to just remote execute any code?

Example:

Hacker can run this code repeatedly. He can also set additional 4th param to make it persistent to welcome all newly joined players to his hack:

[{/*hackedcode*/},"BIS_fnc_spawn",true] call BIS_fnc_MP;
[{/*hackedcode*/},"BIS_fnc_call",true] call BIS_fnc_MP;

Solution:

Remove both BIS_fnc_spawn and BIS_fnc_call functions, there is no other way.

Tnanks

Details

Legacy ID
2300528173
Severity
None
Resolution
Open
Reproducibility
Always
Category
Multiplayer

Event Timeline

Killzone_Kid edited Additional Information. (Show Details)
Killzone_Kid set Category to Multiplayer.
Killzone_Kid set Reproducibility to Always.
Killzone_Kid set Severity to None.
Killzone_Kid set Resolution to Open.
Killzone_Kid set Legacy ID to 2300528173.May 7 2016, 5:45 PM
Killzone_Kid edited a custom field.

Dwarden, personally I think BE should be used as last resort and not to patch security holes that could be avoided otherwise.

As I mentioned in th eticket, createUnit with init syntax is absolete, no one is using it but hackers, there is alt syntax, which is safe.

A few other things. BIS_fnc_MP - put an on off switch on it via description.ext param. AFAIK only secondary explosions are using it in Arma 3, very easy to move to custom publicVriable, so that BIS_fnc_MP can be safely disabled.

Another, absolutely crucial feature would be to have ability to disable publicVariable CODE. Again, has to be param in description.ext Tightening security this way should make it more difficult for scriptkiddies and easier to add additional layer of defence with BE

Also it would have been great if there was a universal addPublicVariableEventHandler like this

"" addPublicVariableEventHandler {} available on the server

It already has 2 params 0 - name of the variable, 1 - value. What needed is also originating client.

so one can simply

switch (_this select 0) do {

case "PV1" : {//do something};

case "PV2" : {//do something};

default {//unknown PV, originating client is known do something about it}

};

Add to it waypoint statement, which is executed globally. setWaypointStatements ["true", "...i'm the nasty code here, do me globally..."]

Why transfer of the code in public variables should be optional.

//server function handling PV

"myPV" addPublicVariableEventHandler {diag_log _this};

//client broadcast

myPV = "hello"; publicvariable "myPV";

//server result

["myPV","hello"]

//client hacker broadcast

myPV = compileFinal ""; publicvariable "myPV";

//server result

["myPV",{}]

//client broadcast

myPV = "good bye"; publicvariable "myPV";

//server result

["myPV",{}] <-- PV value is now locked and cannot be changed. Great way for a hacker to broadcast malicious code and wrap it in unchangeable function, myPV in this case which will exist on every client including JIP.