Security Risk for MQ Model Queue

Well, I learnt something new today: an MQ model queue is a security risk!

It is not that a model queue in of itself is a security risk but rather what you can do with a model queue to get a backdoor to a queue or maybe it is called a ‘side channel attack’ of a queue.

An application uses a model queue as a template when creating either Temporary Dynamic Queue (TDQ) or Permanent Dynamic Queue (PDQ).

MQOD od = {MQOD_DEFAULT};
strncpy( od.ObjectName,
         "SYSTEM.DEFAULT.MODEL.QUEUE",
         MQ_Q_NAME_LENGTH);
MQOPEN( Hcon,
        &od,
        MQOO_INPUT_EXCLUSIVE,
        &Hobj,
        &CompCode,
        &Reason );

(1) If the ‘Definition Type’ for the model queue ‘SYSTEM.DEFAULT.MODEL.QUEUE’ is ‘Temporary Dynamic’ (i.e. DEFTYPE(TEMPDYN) ) which is the default value then the above code will create a temporary dynamic queue that begins AMQ. i.e. AMQ.5B2A92F303EB5525

(2) If the ‘Definition Type’ for the model queue ‘SYSTEM.DEFAULT.MODEL.QUEUE’ is ‘Permanent Dynamic’ (i.e. DEFTYPE(PERMDYN) ) then the above code will create a permanent dynamic queue that begins AMQ. i.e. AMQ.5B2A92F303EB5635

When a TDQ or PDQ is created, the creator of the queue gets full access to the queue. And you would say yes, of course. Note: This is an important point to remember.

Now, if you don’t like AMQ as a prefix, you can use your own. Lets say you want a prefix of ‘GOAL’ then the code would look like:

MQOD od = {MQOD_DEFAULT};
strncpy( od.ObjectName,
         "SYSTEM.DEFAULT.MODEL.QUEUE",
         MQ_Q_NAME_LENGTH);
strncpy( od.DynamicQName,
         "GOAL.*",
         MQ_Q_NAME_LENGTH);
MQOPEN( Hcon,
        &od,
        MQOO_INPUT_EXCLUSIVE,
        &Hobj,
        &CompCode,
        &Reason );

(1) If the ‘Definition Type’ for the model queue ‘SYSTEM.DEFAULT.MODEL.QUEUE’ is ‘Temporary Dynamic’ (i.e. DEFTYPE(TEMPDYN) ) which is the default value then the above code will create a temporary dynamic queue that begins GOAL. i.e. GOAL.5B2A92F303EB5525

(2) If the ‘Definition Type’ for the model queue ‘SYSTEM.DEFAULT.MODEL.QUEUE’ is ‘Permanent Dynamic’ (i.e. DEFTYPE(PERMDYN) ) then the above code will create a permanent dynamic queue that begins GOAL. i.e. GOAL.5B2A92F303EB5635

For OAM permissions of a model queue, they are exactly the same as a local, alias, remote or cluster queue. If you don’t have access to ‘SYSTEM.DEFAULT.MODEL.QUEUE’ then you cannot create a TDQ or PDQ – WRONG.

Most MQAdmins will set the OAM permissions for application-related model queues to allow everyone (or pretty much everyone) access. What does that mean? If you don’t have access to ‘SYSTEM.DEFAULT.MODEL.QUEUE’ then you can use any other model queue that exists in the queue manager to create a TDQ or PDQ. i.e. ‘APPL.MODEL.QUEUE’

So, lets put our evil hats on!!! Off the top of my head, I can think of 2 situations where evil doers can do harm.

Hole #1: Let’s say you know that within the next few days or weeks, the MQAdmin will be creating new queues in a queue manager for a production application that will have confidential information in the messages. Let’s say the local queue will be called ‘RETAIL.CC.DATA.Q’. The MQAdmin has set the OAM permissions such that you do NOT have access to any queue that begins with ‘RETAIL.’. You are locked out, not if you think fast!!!

So, you create a program, doesn’t matter the language, that does:

MQOD od = {MQOD_DEFAULT};
strncpy( od.ObjectName,
         "ANY.MODEL.QUEUE",
         MQ_Q_NAME_LENGTH);
strncpy( od.DynamicQName,
         "RETAIL.CC.DATA.Q",
         MQ_Q_NAME_LENGTH);
MQOPEN( Hcon,
        &od,
        MQOO_INPUT_SHARED,
        &Hobj,
        &CompCode,
        &Reason );

The ‘ANY.MODEL.QUEUE’ model queue can be any model queue that has Definition Type of Permanent Dynamic. i.e. DEFTYPE(PERMDYN)

Note: I used the option of MQOO_INPUT_SHARED rather than MQOO_INPUT_EXCLUSIVE because I don’t want the real application noticing that I’m stealing the messages!!!!

Now the rogue user now has FULL access to queue ‘RETAIL.CC.DATA.Q’ (see point above about full access).

Why did MQ allow you to create the queue? The OAM checked the user’s permission of the queue name in the ObjectName field (i.e. model queue). One check and it is done. OAM does NOT check the value in the DynamicQName field or the ResolvedQName field if an asterick ‘*’ was used in the DynamicQName field.

When the MQAdmin runs their scripts to create the new queues (i.e. ‘RETAIL.CC.DATA.Q’), they may not even notice that the queue already existed and when they apply permissions via setmqaut commands, everything will work. But the rogue user has a nice backdoor to ‘RETAIL.CC.DATA.Q’.

Hole #2: Let’s say you have 4 queue managers (MQA1, MQA2, MQA3 & MQA4) participating in a cluster called ‘RETAIL_CLUS’ and a cluster queue called ‘RETAIL.CC.DATA.CLUSQ’. Let’s further say that the cluster queue ‘RETAIL.CC.DATA.CLUSQ’ is ONLY defined locally in queue manager ‘MQA4’ and not in the other 3 queue managers participating in the cluster.

This is a pretty typical setup. So, lets put our evil hats on again and create a program, doesn’t matter the language, which will connect to either MQA1, MQA2 or MQA3 and does:

MQOD od = {MQOD_DEFAULT};
strncpy( od.ObjectName,
         "ANOTHER.MODEL.QUEUE",
         MQ_Q_NAME_LENGTH);
strncpy( od.DynamicQName,
         "RETAIL.CC.DATA.CLUSQ",
         MQ_Q_NAME_LENGTH);
MQOPEN( Hcon,
        &od,
        MQOO_INPUT_SHARED,
        &Hobj,
        &CompCode,
        &Reason );

Now leaving behind a permanent dynamic queue in this situation may not be a good idea. I would go with a temporary dynamic queue. The evil program would get the messages, the application would be losing messages and when the program disconnects, there would be no trace and everybody would blame MQ for losing the messages!!!!

Hence, the ‘ANOTHER.MODEL.QUEUE’ model queue should be any model queue that has Definition Type of Temporary Dynamic. i.e. DEFTYPE(TEMPDYN)

Again, the OAM checks the user’s permission of the queue name in the ObjectName field (i.e. model queue). One check and it is done. OAM does NOT check the value in the DynamicQName field or the ResolvedQName field

I’ve worked with MQ for about 25 years and this is something I didn’t know you could do. Shocking. I always thought the OAM did a second check against either DynamicQName field or the ResolvedQName field. But no.

Bottom-line, make sure you put SUPER tight security on your model queues of a queue manager.

Regards,
Roger Lacroix
Capitalware Inc.

This entry was posted in .NET, C, C#, C++, HPE NonStop, IBM i (OS/400), IBM MQ, IBM MQ Appliance, Java, JMS, Linux, Programming, Security, Unix, Windows, z/OS.

One Response to Security Risk for MQ Model Queue