We have a WMQ - WAS/JMS client setup through server connection channels where we are trying to put in security through user Ids.
Now, we set up a local user id on the MQ box, mquserid, and left the channel's MCAUSER blank.
We thought: the id running the MQ client (WAS in our case) wasuserid, when passed to MQ will fail as it is not setup on MQ box. So we shall then set up JAAS alias (with User Id: mquserid) for the Queue connection factory on WAS which will then be passed to MQ and will allow connections.
But, we are able to connect and put messages without the JAAS alias :(
I wrote a standalone Java program to connect to QMs and it is behaving correctly depending on the user Id I pass when obtaining connection.
Does WMQ treat WAS in a special way allowing connections without checking against its local user registry?
No, WAS is treated like any other connection.
In version 6 and earlier of WAS it will send a blank ID if the user ID on the WMQ connection is not specified. You can tell if this is the case by looking at the channel status while WAS is connected. The MCAUSER of the running channel will contain the ID that was used to connect. If the running channel status shows no MCAUSER value then WAS did not present an ID.
The other possibility is that the SVRCONN channel definition (not status) has a value such as mqm in the MCAUSER. In this case, the ID presented during the connection request is ignored. Again, check the channel status to see what ID is being used at run time or just check the SVRCONN channel definition to look for an MCAUSER value.
Now here's the kicker - if the channel's MCAUSER is blank then WMQ will accept whatever ID is presented. If no ID is presented, then the connected app or user runs as an administrator. If an app or user can be a WMQ administrator then they can do anything on the QMgr and can also remotely execute arbitrary OS commands on the server under the QMgr. Not good.
The correct answer is to set the MCAUSER on the channel to whatever value the app is supposed to connect as. At this point, the app cannot use any other ID because the channel will override it. However, anyone can connect to that channel so the next step is to authenticate the connection request. You can use an exit like BlockIP2 which is free or MQAUSX which is a commercial vendor product. BlockIP2 will filter incoming requests by IP address which may be sufficient for connections arriving from a static IP in a locked datacenter. MQAUSX will actually check the UserID and password sent during the connection request from WAS (or any client, for that matter). You can also use SSL and the channel's SSLPEER attribute to authenticate requests using X.509 certs. Note that if you use MQAUSX to validate a user ID and password either use SSL encryption with it or use both the client-side and server-side versions of the exit. Otherwise your credentials are flowed in cleartext over the wire which defeats the purpose.
Of course, if you secure the app's channel it's necessary to secure the other channels on the host such as SYSTEM.DEF.* and SYSTEM.AUTO.* or else an attacker will simply bypass the app channel.
Note that if the RCVR, RQSTR and CLUSRCVR channels do not authenticate requests or contain an MCAUSER value they also expose admin access. For example, if I want to control your QMgr and you locked the SVRCONN channels, I'd create a QMgr on my desktop, delete my SYSTEM.DEF.RECEIVER, create a new SDR channel called SYSTEM.DEF.RCVR and point it at yout QMgr. If your SYSTEM.DEF.RCVR (or S.D.RQSTR or S.D.CLUSRCVR) or any other of these channel types that you have defined lack SSL or an exit then I can connect and if they lcak an MCAUER then I can administer the QMgr anonymously and execute OS commands.
Any channel definition without an MCAUSER value allows administrative access.
Any channel without SSL/SSLPEER and/or an exit allows anonymous connections.
For more on this, please see the WMQ Hardening presentation and WMQ Security Lab documents at https://t-rob.net/links. Also, please see the articles on SSL and other WMQ security topics in the Mission:Messaging column on IBM developerWorks Tech Journal.
Related
I have a problem with the following scenario using MobileFirst HTTP javascript adapters:
let's say the adapters call 2 methods,
login, that calls a back end service which authenticates the user and also returns a customer_id (input: a username and a password).
retrieveData (protected by security-check) that retrieves sensitive data about a customer by calling a back end service (input: customer_id).
How can we make sure that some client that has credentials to authenticate and have access to retrieveData, will request only data that concern him and not be able to send a request sto retrieveData with a different customer_id from his own? (We assume that this client has tempered with the app and has made it send different customer_id's.)
With MobileFirst 7, after login was successful, we would call setActiveUser setting the returned customer_id as an atttribute of active user or we would call WL.Server.getClientRequest().getSession().setAttribute and again set the customer_id. So when a user called retrieveData, we would take his customer_id input and compare it to the customer_id in his session. If it was different, then they would get an error because they requested data that do not belong to them.
Since MobileFirst 8 does not have a session, how can we prevent this scenario from happening?
In 8.0, "Client Registration Data" is the closest thing to a session.
There are a lot of unknowns about your use case, but I will try to describe the expected behavior is most cases:
Assuming your security check extends UserAuthenticationSecurityCheck, as soon as the user succeeds to login, his user id will be registered in the client registration data on the server. This will map the client to the user in a database.
From that point on, on any adapter you can safely check who is the currently logged-in user by using securityContext.getAuthenticatedUser().
If you want to make sure that a client only accesses data it is allowed to, use this getAuthenticatedUser to check against your database that the requested data belongs to it.
If you really need to store extra custom data in the registration context (the closest thing to a session object) there are APIs in the security check to do so. See RegistrationContext.
In v8.0, the client is able to retrieve information from the backend system because it passed the challenge presented to it, and in return received an access token that enables it to access resources that are protected by a scope, which you define. This is how OAuth works more or less.
Have you read the Authentication Concepts tutorial? https://mobilefirstplatform.ibmcloud.com/tutorials/en/foundation/8.0/authentication-and-security/
I want to create a private message system using NodeJS and websockets.
I was wondering what the best way is to create such system.
Is it better to create 1 nodeJS server and bind listen-event for each user, or should I create a unique port/server for each conversation between 2 users.
i.e.
conversation 1 (user1 & user2): port 8080
conversation 2 (user2 & user3): port 8081
conversation 3 (user1 & user3): port 8082
Is it better to create 1 nodeJS server and bind listen-event for each
user, or should I create a unique port/server for each conversation
between 2 users. i.e.
Neither.
You can easily create a private conversation between two users with one server listening on one port and allowing users to connect to the server and then identify which other user they want to have a private conversation with.
A user identifies themselves to the server with some sort of credential when they login and connect to the server. Your server then knows which user belongs to which connection.
The server can then facilitate a private conversation between any two users by simply allowing userA to pass messages to userB and vice/versa, but not allowing anyone else access to those messages. No private server per user is needed. No custom port is needed. You do need some sort of user authentication service so you can know which user is which with some appropriate level of credibility.
You can see some pieces of what you're asking about in this socket.io demo chat server.
Here's a more detailed description for how this works:
UserA connects to the server and identifies themselves.
UserB connects to the server and identifies themselves.
UserC connects to the server and identifies themselves.
UserA sends a message to the server instructing the server to send a private message to userC.
The server receives that message from UserA and forwards it on to UserC.
UserC receives the private message from userA.
The server does not store the message from UserA or ever send it to any other users (thus making it a private message).
UserC can then respond to UserA using the same mechanism.
Note: It is a requirement of pretty much any scheme that you have both user authentication and you have a user identifier. You will then also have to surface that in a user interface so that a given user can identify which currently connected user they wish to communicate with.
Is there a way to make the client have only read-only permissions to channels since we are distributing the client key with the web app using the pusher.js sdk?
The application key itself does not determine the permissions of a client. It only identifies which application the client is connecting to.
By default all subscriptions are read-only. Pusher offers three channel types:
Public
Private - with a private- name prefix that also requires subscription authentication
Presence - with a presence- prefix that also require subscription authentication and additional functionality for adding functionality to show which users are subscribed to that channel
A above, in order to subscribe to either Private or Presence channels your server needs to authentication the subscription request.
If you actually want a client to be able to trigger events on channels you need to:
Enable client events for an application
Subscribe to, and be authenticated for, a private or presence channel: channel = pusher.subscribe('private-channel')
Once subscribed (check using the pusher:subscription_succeeded callback) call channel.trigger('client-event', eventData) being sure to prefix the event name with client-
All of Sails' publish methods take an extra parameter which allows me to tell Sails not to publish to one specific socket. What I'm not seeing is a way to restrict a whole class of sockets from receiving updates.
In my application, users manage a lot of personal information including things like names and addresses. When a person record is created or updated, I don't want that information broadcast to every single socket connected to the system. The only users who should receive the updates are users associated with the group that owns the record in question.
I need to be able to:
Review the session associated with each socket.
Determine if the user associated with that socket is a member of the group that owns the created/modified person record.
Only publish to the sockets that fit said criteria.
Does Sails support filtering on the server side? If that kind of filtering is left up to the client, then I can't secure my data.
For a startup considering making public notifications intended for website users available via a Pusher channel, how do you prevent people from subscribing to that channel for a long period of time (camping essentially)? I know you can disconnect users after a period of inactivity if they are connected from a web client (by checking for activity on the client and sending a disconnect after a period of inactivity), but what if users decide to connect via a command-line app or something similar?
Pusher provides private channels where the subscription to those channels need to be signed using your application secret in order for the subscription to be allowed.
Given the command-line app example you've provided the author of that application would not know the application secret and would therefore not be able to subscribe to the private channel.