shineworld 73 Posted March 17, 2023 Hi all, First of all, I apologise if what is required is poorly described, but unfortunately I know very little about networks and their knowledge. But let's get down to facts. In an industrial machine control application, I have inserted a server, a TCP/IP server based on JSON messages, which allows the connection of several clients at the same time and enables motor movement commands to be executed or information to be retrieved from the system. A client programme connects to the server and from then on can do anything with the device it has connected to. At this point, security problems arise, especially for the operator standing at the machine, since a malicious client intruding into the network could trigger dangerous operations for the operator standing near the machine and unaware that someone unauthorised has taken control of it remotely. Now I have been asked to add a security layer, but as a complete ignoramus on the subject, I deal mainly with compilers of languages and UI environments and not with networks, I was wondering how to add a system of certification and authorisation of the client to the server connection. For the client I use python while the server is done with Indy 10 using TIdTCPServer. Thank you in advance for any suggestions and help. Best regards Silverio Share this post Link to post
mjustin 23 Posted March 17, 2023 To clarify: you are looking for protection against malicious clients, and the server is not a concern? Share this post Link to post
Fr0sT.Brutal 900 Posted March 17, 2023 You're able to modify clients? If yes, use TLS and check certificates of both server (at client side) and client (at server side), ensure certificate corresponds to server host and, for the maximum security, add auth by login-password 3 Share this post Link to post
shineworld 73 Posted March 17, 2023 1 hour ago, mjustin said: To clarify: you are looking for protection against malicious clients, and the server is not a concern? The API Server (based on TCP/IP JSON requests) permits commands as {"cmd":"start.axis.movement"} so a TCP/IP client can connect to API Server, ask for an axis motor to start. At moment any TCP/IP client, eg: Telnet, can ask for an API Server connection and is not safe for machine operator. I would like to permit connection ONLY on trusted client applications (I my case a python program or a Delphi program which run in office). And I would like that client/api messages are crypted during transport so none can intercept and learn what commands are used. I can crypt/decript JSON messages to obfuscate them using for eg: bluefish or similar but I can't avoid a not trusted/client connection. Share this post Link to post
shineworld 73 Posted March 17, 2023 34 minutes ago, Fr0sT.Brutal said: You're able to modify clients? If yes, use TLS and check certificates of both server (at client side) and client (at server side), ensure certificate corresponds to server host and, for the maximum security, add auth by login-password I will try to learn how to add TLS in TIdTCPServer and TIdTCPClient 🙂 1 Share this post Link to post
Remy Lebeau 1398 Posted March 17, 2023 (edited) 9 hours ago, shineworld said: I would like to permit connection ONLY on trusted client applications (I my case a python program or a Delphi program which run in office). And I would like that client/api messages are crypted during transport so none can intercept and learn what commands are used. That is exactly what TLS is meant for. It handles ALL of that stuff for you. Clients can validate that they are connected to the official server and not another server (especially a man-in-the-middle). And the server can validate that only trusted clients are connecting to it. And ALL communication is encrypted back and forth. Edited March 17, 2023 by Remy Lebeau 1 Share this post Link to post
DelphiUdIT 176 Posted March 17, 2023 10 hours ago, shineworld said: I will try to learn how to add TLS in TIdTCPServer and TIdTCPClient 🙂 I post a simple TCP sample using SLL (TLSv1_2). It's only a little start point, but may help you. Inside there are the OpenSSL Win64 dll 1.0.2u and one certificate self signed valid for one year (localohst, 127.0.0.1). There is also a DHParam file used for DH "chiper" protocol, not necessary and not used. From there you can improve security, authentication, etc .... Bye TCPS Demo.zip 1 Share this post Link to post
DelphiUdIT 176 Posted March 18, 2023 On 3/17/2023 at 11:35 AM, shineworld said: I would like to permit connection ONLY on trusted client applications (I my case a python program or a Delphi program which run in office). And I would like that client/api messages are crypted during transport so none can intercept and learn what commands are used. A reflection on the discussion and on the concepts of "trusted". If by trusted it is meant that the connection between the client and the server is practically secure and that the client knows who the server is, then the concept of trusted is verified with the use of a server-side certificate (possibly issued by a recognized certifier and not by a self-signed certificate) and an encrypted connection via TLS, and that's what the example I posted does. But if we expand the concept of trusted, as I think @shineworld intends, then it is more complex to apply it. The "expanded" concept is that the connecting client is known and certified as if it were a server. A standard certificate (similar to that of the server) on the client side is not applicable because the files are exposed, especially the private key even if protected by a password, and anyone who can access the station could "copy" it. A solution would be a "hardware" certificate (as in a USB token), but it is not an economic solution and there is a fairly important management for the tokens: it must be said that many private companies and all public companies have by now equipped employees with a USB token or similar (token like credit card, etc ....). Other easily applicable solutions are then: apply the concept of "registration": at the very first connection (client installation) the client sends runtime data to the server (date and time of installation, processor UUID, etc ....) which the server registers (with its own coding ) and will use to test future connections. The client will send this data at each new connection and the server will refuse the connection if they are not included in the list of already registered clients. OBVIOUSLY THESE DATA MUST NOT BE DISCLOSED, IE MUST NOT PUBLICLY KNOW IF AND WHAT THE CLIENT SENDS TO THE SERVER (otherwise it is enough for a fake client to replicate the data of a real client to replace itself). apply the classic concept of username / password, but it makes sense if the entry is done by operator, if it has to be automated it means that username and password must be stored locally .... so other local encryption, .... etc ... . Bye 1 Share this post Link to post
mjustin 23 Posted March 18, 2023 (edited) 1 hour ago, DelphiUdIT said: A standard certificate (similar to that of the server) on the client side is not applicable because the files are exposed, especially the private key even if protected by a password, and anyone who can access the station could "copy" it. A client certificate should be stored in a safe place, which is not even accessible / exportable by the logged in user. Just an idea: using a cert store, the certificate may be installed with private keys marked as not exportable. Reference: How to protect private key for client cert in machine store? Is it acceptable for it to be exportable? https://security.stackexchange.com/q/260614 The accepted answer describes a different solution, using a 'user cert store'. If I understand correctly, other users would not be able to access the certificate and private key. Edited March 18, 2023 by mjustin Share this post Link to post
DelphiUdIT 176 Posted March 18, 2023 It would be a good idea but there are two problems: 1) Create a different user (different from an administrator user and from the user where the application runs) on all the machines where the application runs ... I see it as a real complication for management and maintenance. And in any case the credentials to impersonate the user must be "hard coded" in the program or in an external file, therefore local encryption ... at this point it is better to locally encrypt the direct access credentials to the server or directly the certificate files. .. but it doesn't make much sense, you just lengthen the chain and don't solve the underlying problem; 2) Indy does not support access to the Windows Cert Store ... at least as far as I know, until the keys are exportable .... Bye Share this post Link to post
mjustin 23 Posted March 19, 2023 18 hours ago, DelphiUdIT said: 1) Create a different user ....I see it as a real complication for management Yes, this would cause more work / administration. But maybe you missed the last part: "The accepted answer describes a different solution, using a 'user cert store. (...)" With this solution, no additional user would be needed. The certificate will reside in a user cert store, and is readable only for the user, inaccessible for other users.. 18 hours ago, DelphiUdIT said: 2) Indy does not support access to the Windows Cert Store ... at least as far as I know, until the keys are exportable .... Currenly the client is in Python: > For the client I use python while the server is done with Indy 10 using TIdTCPServer. So if there is Python support for cert stores it should be solvable. Alternatively, with Delphi, other HTTP clients may support reading from cert stores (TNetHTTPClient or others). Share this post Link to post
DelphiUdIT 176 Posted March 19, 2023 (edited) 5 hours ago, mjustin said: But maybe you missed the last part: "The accepted answer describes a different solution, using a 'user cert store. (...)" With this solution, no additional user would be needed. The certificate will reside in a user cert store, and is readable only for the user, inaccessible for other users.. These not resolve other question about i wrote: where and how you maintain the couple of accounts right (Username / Password) to impersonate the user of the "cert store" ? ..... like I told another level of crypto .... This is a non sense for a simple TCP / IP communications: client with a "hidden" user that should have a "certificate" in personal windows store (with private key and a password for that) and a crypto for username / password of hidden user ... I don't think a sysadmin of any company would agree to such a choice: i asked to 3 company one little, two big, of course in private and unofficial conversation and they negate these approach. All three would impose the use of the supplied USB stick on all their staff, or in second hand the registration of the software (this last would be my preferred solution). This choice depends on whether the application is autonomous (for example the customer launches it and then it must "run" as long as the customer is logged in) or if it is launched in autorun when the customer logs in and runs without particular interactions with the 'user. But we are in a free world and everyone is free to make their own choices. The important thing is to continue to offer solutions. 5 hours ago, mjustin said: Alternatively, with Delphi, other HTTP clients may support reading from cert stores (TNetHTTPClient or others). @shineworld talks about TCP / IP communications with is "proprietary protocol" and not about HTTP. Using Http is another question. Bye Edited March 19, 2023 by DelphiUdIT Share this post Link to post
DelphiUdIT 176 Posted March 19, 2023 This might be "OT", but just one piece of advice I want to give to @shineworld In general, expressly if commands are given to automations, the software (see for example SCADA) requires an authorization level. These levels are normally kept inside a server-side db and have nothing to do with PC users, Windows users, Linux users, etc ... So in the end, in your client communication you could simply enter a name / password that the server program will validate among those in the archive to validate the request. You wouldn't need anything on the client side other than this data pair. If a command is executed, the operator enters this pair by hand and the client sends it to the server together with the command, if instead a status request is executed it could also be that the client sends a hardcoded name / password by default. Of course the server must validate the couple of auth to actuate the request. The communication between client and server (and vice versa) remember that it is always encrypted if you use TLS. Bye Share this post Link to post