Medium Feed

 

Tuesday, August 23, 2022

ShadowDOM and rootDOM - Calculate the DOM max depth and width

An automated way to find the depth and width of shadowDOM/RootDOM


                                Find depth & width of shadowDOM / RootDOM
                        

Heey Heeey stop stop stop !!!. What is DOM Depth( should I measure in cm?? ) what is DOM Width( does DOM gains weight ? )

The Shadow DOM allows hidden trees to be attached in the regular DOM tree. it starts with a shadow root, underneath we can have any number of element.

console.log(getDomStatus(document.body, true));// Includes shadowDOMThe sample result will be :
sample result from above function.

Sunday, April 24, 2022

Native web components vs Lit element: The key practical differences

LIT web component

Vanilla web component

Vanilla/native web components can be created by extending the native HTMLElement class and registering to the browser by calling customElements.define API.


As we know, we can achieve a custom web component from either a vanilla web component or a LIT-based component. But below are key features highlights which approach makes a developer’s life easier, and produce less code, easy maintenance, and better performance.




Vanilla Web component => Imperative
Lit Element => Declarative

 Rendering Template

Vanilla Web Component => JS InnerHtml binding Or <template> cloning nodesLit Element => Lit Template (Tagged Template Literals functions)
Vanilla Web Component => constructor, connectedCallback disconnectedCallback, attributeChangedCallback, adoptedCallbackLit Element => Lit introduces a set of render lifecycle callback methods on top of the native Web Component callbacks
Vanilla Web Component => Normal CSS stylesheet Lit Element => Constructable stylesheet
Vanilla Web Component => Yes, SupportedLit Element => Yes, supported
Vanilla Web Component => Achieved by getter / setter propertiesLit Element => Lit handles it as part of reactive lifecycle
Vanilla Web Component => Achieved with attributedChangedCallbackLit Element => Lit handles it as part reactive lifecycle
Vanilla Web Component => Event listener needs to be initialized programmatically in the connectedCallback and diconnectedCallback lifecycle.Lit Element => In lit templates supports adding event listener to node with @EVENT_NAME binding syntax.



Thursday, February 17, 2022

React/Redux hooks Vs equivalent implementation in React class feature

I am writing this article as an attempt to challenge myself to do a deep dive comparison between react/redux hooks used in functional component vs the equivalent implementation in react class component.

Note: I could not find equivalent class feature implementation for all the hooks. But I tried to the maximum which I can.

In this article, we will discuss the below list of mapping b/w react & redux hooks and it is equivalent implementation in class components. 

                                        React and Redux hooks Vs class feature mappings

useState hook Vs equivalent implementation in class Component


useEffect hook Vs equivalent implementation in class component


useRef hook Vs equivalent implementation in class Component


useMemo hook Vs equivalent implementation in class component


useSelector redux hook Vs redux Connect (mapStateToProps)


useDispatch redux hook Vs redux Connect(mapDispatchToProps)


Sunday, September 26, 2021

Container Security - Learn with exploiting the weakness

In our container environment, the moment we started thinking about protecting containers with the right security practices then the first buzz word would come in all our minds is "isolation". 

 You are right !, In container security, the real buzzword is "isolation". The more you isolate container runtime from a container Host, the more you isolate one container from another container then the security is almost there. To bring these "isolation", the docker as a framework by default supports some of the isolation practices such as 
  •   Docker Namespace 
  •   Cgroups 
  •   Kernel capabilities. 
Docker namespace brings much isolation by providing namespace separation for "process"," mount", "network stack", etc., etc. For example with the docker process namespace, the isolation is provided between the process in the container and the process in the host. The process in the host will have a different process ID, and the same process inside the container will have a different process ID. The processes in running in a host cannot be accessed inside the container and vice versa. This way docker provides isolation of one container is not disturbing other container and also not disturbing the host. 

CGroups is another key component that supports isolation in docker. They implement resource accounting and limiting. They provide many useful metrics, but they also help ensure that each container gets its fair share of memory, CPU, disk I/O; and, more importantly, that a single container cannot bring the system down by exhausting one of those resources. 

If we take Kernel capabilities, the docker by default restricts the set of kernel capabilities within the container. For example, the root user in the docker Host will NOT have all the capabilities inside the docker container.

Along with the aforementioned isolation practices, we will look at some of the docker secure practices which docker and Linux Kernel support.

Below is the list of container secure practices, we will discuss in this article. Also, according to me if we want to learn how to protect something we should first be knowing how to break it too. Let's do our learning with easy exploitation practice on some of the container security weaknesses in the docker environment.


Let's start with docker architecture to understand why we do we say "isolation" is important in docker security.  If we look at the below diagram, you could imagine how the kernel is positioned in docker architecture while comparing traditional VM architecture. In VM architecture the individual VM process will have it is own dedicated Kernel, but when it comes to docker architecture this is not the case. Each container's process will share the same host Kernel across the cluster.

This is one of the reasons why "isolation" is important in docker security terms.  Let's take an example if one container is damaged with attacker arbitrary code then eventually there is a possibility
of the vulnerability breakout from the container to the host kernel. As the kernel is shared across the container and the docker engine is positioned above the host kernel the attack surface will be extended to break out to the other containers in the cluster also. This is the risk the docker architecture poses in terms of sharing host kernel across container processes. 



Rootless containers


Running your containers as a "Rootless container".  It means running the entire container runtime as well as the containers without the root privileges.

In a normal scenario when a docker engine spins a new container process the default privilege
the container that will be running is "root" privilege, though the default docker isolation
practices limit the root user capabilities within the container but still the container
will be running in an as the root user. In any case, if the container runtime is processed it could maximum 
impact to the container and also if the vulnerability breakout the vulnerability will have access to docker engine and host machine kernels.

Also, if we really look into the need for a running container in ROOT mode. Absolutely 90 % there is NO need to run the container in root mode. 

Below are the potential threats of running container in ROOT mode




Within the container

A compromised container runtime:  With root, context can perform any action inside the container including installing new software editing files, mount file system, modify permission, etc.,


Outside the container

In a compromised container, the vulnerability could:
  •      Breakout the container and escalate permission to Host.
  •      Breakout the container to damage another container 
  •      Breakout to docker engine and can make requests to the Docker API server.
      

How to exploit the root containers 


Here I will show you how the container running with root mode can be exploited in simple ways.

I've used Katacoda as a testing environment.

As a first step to exploit, you can verify the container running mode as shown below.
In the below container I verified that container is running mode by running the "whoami" command
inside the container.




Privilege escalation to host machine

In the below steps, I've shown how privilege escalation happens from the docker container to the Docker host.
To simulate I've mounted the host machine filesystem as a volume into the container, then I run
the command "cat /host/etc/shadow". The output is listing the user's details of the host machine.



Small DoS attack within the container

In the below step, I'll show a simple DoS attack exploitation within the docker container.
Here the container is running in a root user mode, hence it has the privilege to install any software's within the container. Taking advantage of that, I install the Debian package called "Stress", then using the "stress" package I make heavy load to container memory thereby bring down the container to "OOMKilled" mode. Successfully made the DoS exploit.


How to run as a "Rootless container"


Here the some of the basic steps to consider running your container as a "rootless container"

1. Update your YAML file (if using K8s) and the security context section to 
       "runAsNonRoot" : true
   "runAsUser" : 1000
   
2. Add a new non-root user in your docker file

RUN groupadd --gid 1000 NONROOTUser && useradd --uid 1000 --gid 1000 --home-dir /usr/share/NONROOTUser --no-create-home NONROOTUser
USER NONROOTUser

3. In case your container port is running in privileged port anything below 1024 for example port 80, please modify
to run in an unprivileged port (anything above 1024), for example, port 5000.


Rootless Docker Engine


Running docker-engine or daemon in a NON-ROOT user context.

In the above section, we saw "rootless container", here the other secure practice is to run your docker engine /host itself in a rootless mode.

Docker recently introduced a "rootless docker-engine" as part of Docker version 19.03. Docker recommends
to run your container as rootless mode, however, this feature is still previewed mode and yet to 
be used by many peoples.

With the below command, you can check your docker engine is running in root mode or rootless mode.



Docker Seccomp Profile


Secure computing mode (second) is a Linux kernel feature.

  • Seccomp acts like a firewall for systems (syscalls) from container to host kernel.
  • Sample list well known syscalls: MKDIR  <> , REBOOT <>, MOUNT <>,KILL <>, WRITE <>.
  • Docker default Seccomp profile disables 44 dangerous system calls, out of 313 available in 64-bit Linux systems
  • As per Docker incident CVE’s list,  most docker incidents are due to privileged Syscalls.
  • Docker default  Seccomp profile provided whitelisted Syscalls most of the time NOT necessary for our product needs. It is recommended to have a product-specific custom seccomp profile by whitelisting only Syscalls used by our container.



How to check Container Seccomp Profile

We can verify your container runtime is enabled with default seccomp profile protection or not. Just go inside your container terminal mode and run the below command grep Seccomp /proc/$$/status ( as shown below)

Seccomp value 2 means it is ENABLED
Seccomp value 0 means it is NOT enabled



Docker Limited Kernel capabilities


By default, Docker starts containers with a restricted set of capabilities. This provides
greater security within the container environment.

It means though your container's process is running with a root mode, the Kernel capabilities
within the container are limited. Docker will allow only limited capabilities within the
container which the user process can execute. However, this default protection from docker 
can be overridden if you run your container in a "privileged" mode.

To understand better. If you log into your Linux host machine as a Root user then you will
have the below Linux kernel capabilities will be allowed.

CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID, CAP_KILL, CAP_SETGID, CAP_SETUID, CAP_SETPCAP, CAP_LINUX_IMMUTABLE, CAP_NET_BIND_SERVICE, CAP_NET_BROADCAST, 
CAP_NET_ADMIN, CAP_NET_RAW, CAP_IPC_LOCK, CAP_IPC_OWNER, CAP_SYS_MODULE, CAP_SYS_RAWIO, CAP_SYS_CHROOT, CAP_SYS_PTRACE, CAP_SYS_PACCT, CAP_SYS_ADMIN, CAP_SYS_BOOT, CAP_SYS_NICE, CAP_SYS_RESOURCE, CAP_SYS_TIME, CAP_SYS_TTY_CONFIG, CAP_MKNOD,
 CAP_LEASE, CAP_AUDIT_WRITE, CAP_AUDIT_CONTROL, CAP_SETFCAP, CAP_MAC_OVERRIDE,  CAP_MAC_ADMIN, CAP_SYSLOG
 
 
But the same root user enters into the docker container the most above kernel capabilities will 
be dropped and only below restricted list of capabilities will be allowed. 

CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID, CAP_KILL, CAP_SETGID,
CAP_SETUID, CAP_SETPCAP,CAP_NET_BIND_SERVICE, CAP_NET_RAW,CAP_SYS_CHROOT,CAP_MKNOD, CAP_AUDIT_WRITE

DO NOT RUN CONTAINER IN – –PRIVILEGED MODE !!

The privileged container can do almost everything that the host can do. 
The --privileged flag gives all capabilities to the container,  and it also lifts all the limitations enforced by the device cgroup controller. 

Using the below command you can verify whether your command is running in PRIVILEGED Mode or normal mode.

If the command returns TRUE, it means the container is running in a PRIVILEGED mode.


Run container with limited or NO Kernel capabilities


Absolutely, in normal scenarios, most of the Microservices running in a container does NOT need 
all Kernel capabilities provided by Docker.

Hence, the best practice is to DROP all capabilities and add only the required capabilities.

This can be done from Kubernetes docker Yaml file security context configuration. In your security
context either DROP all capabilities. Example
 
 SecurityContext => Capabilities => drop : ALL
 
Or add only the required capabilities. Example

 SecurityContext => Capabilities => add : ["NET_ADMIN", "SYS_TIME"]

Docker SE Linux Protection


Docker SELinux controls access to processes by Type and Level to the containers. Docker offers two forms of SELinux protection: type enforcement and multi-category security (MCS) separation.

  • SELinux is a LABELING system
  • Every process has a LABEL. Every File, Directory, and System object has a LABEL
  • SE Linux Policy rules control access between labeled processes and labeled objects.
!! To enable SE Linux in a container, your Linux host machine must have SE Linux enabled and running !!




Docker UNIX Socket (/var/run/docker. Sock) usage


There are approaches followed by developers to achieve container management related functionalities
they will mount the docker UNIT socket inside the container and using the docker socket they
will do achieve the container management functionalities implementations such as for  collecting logs from all containers, creating a container, stop container...etc

BE CAUTIOUS WHEN YOU MOUNT THE DOCKER UNIX SOCKET INSIDE YOUR CONTAINER!

It is a more dangerous combination of the Root context, container privileged mode, and UNIX socket mounted.

Below is a sample scenario that mounts the docker UNIX socket inside the container for log management of all the containers running by the docker engine.



Docker Network security 


Be cautious on how you expose the services inside the container to outside the cluster.

  • Do NOT expose the container with External IP ( if there is NO explicit need to run in external IP)
  • When there is a need to expose with External IP ensure that the inbound connection is encrypted and listening in 443 port.
  • Always try to expose your services only with Cluster IP mode.
  • If there is a need to expose with Node Port, ensure that the inbound connection is encrypted and listening in 443 port

Ingress and Egress rules:

Control traffic to your services with Ingress and Egress network policies. 
  • With strict ingress rules supported by Kubernetes you can restrict the inbound connections to your containers.
  • With strict egress supported by Kubernetes you can restrict the outbound connections from your connection to another network.

Other Docker Security Practices


  • Volume mount – as read-only
  • Ensure SSHD does not run within the containers
  • Ensure Linux host network interface is not shared with containers.
  • Having no limit on container memory usage can lead to issues where one container can easily make the whole system unstable in case a DoS attack happened
  • Don't mount system-relevant volumes (e.g. /etc, /dev, ...) of the underlying host into the container instance to prevent an attacker can compromising the entire system and not just the container instance.
  • Incase Docker daemon is available remotely over a TCP port. Ensure TLS communication.
  • Consider read-only filesystem for the containers.
  • Leverage secrets store/wallets instead of environment variables for sensitive data storage inside a docker container.

Thursday, July 8, 2021

Understand the Anatomy of how HTTPS works ( Asymmetric, Diffie-hellman, symmetric) : my way of representation

Step 1 : Initial Handshake, Local CA validation and Asymmetric encryption establishment


Step 2 : Diffie-Hellman Key exchange

Step 3 : Switching from Asymmetric encryption to Symmetric encryption

Saturday, December 12, 2020

Custom HTTP interceptor hook to Intercept Iframe Window HTTP requests from Parent Window in Angular

 As we all know, angular provides a default HTTP Interceptor as part of angular HTTP module. We can use this interceptor to intercept the HTTP requests. But this has a limitation of intercepting HTTP calls only from the current window object. 

Recently I had a requirement to intercept the HTTP requests triggered from Iframe window object and add the intercept values from parent object. We tried with default angular HTTP interceptor object, as I initially expected it did not work. Because the default HTTP interceptor does not provide provision to intercept the iframe window object. 

Hence, I've written a quick hook using JavaScript which will intercept all the HTTPRequests triggered from the Iframe object.  

This will be a hook within the XMLHTTPRequest open object and the hook will stay permanent in the iframe object until the iframe window object itself completely destroyed. 

Here is the custom hook you can add in your parent window object. You just have to inject the interceptor in the iframe load event.



Tuesday, October 22, 2019

Kubernetes NFS encrypted communication: Kubernetes pod applications (as NFS client) and Linux based machine (as NFS server) – secure traffic using Tunnel Over SSH

As we all know, to encrypt NFS share traffic b/w NFS client and NFS server the couple of options are used in general are Kerberos Authentication with privacy (krb5p) Or Tunnel over SSH known as port forwarding.

This article I am going to discuss about the option of Tunnel over SSH with Kubernetes pods application which mount the shard path from the NFS server. In general, Tunnel over SSH implementation is common and easy to implement for the scenarios of port forwarding between two machines NFS server and NFS server. This machines can be either windows or Linux or combination of both.




The challenging part comes into picture for the scenarios with Kubernetes cluster in place and when your NFS clients wants to mount the NFS server shared path into a Kubernetes application. The reason why it’s challenging is because Kubernetes pods does not mount the shared path directly instead it depends on cluster “Persisted Volume Claims” and this would raise a request resource to the “Persistent volume” of the cluster. 

1. RHEL – Linux master as NFS server
2. RHEL – Linux node as NFS client and also maintaining running pods and providing the Kubernetes runtime environment.

A share with name “ NFS_Senstive_Data_Share” will be created in NFS server and which will be accessed from an Kubernetes pod application as an mounted path.

Before we start into implementation, would like to give quick explanation of how tunnel over SSH works with a sample in short.

ssh -fNv -c aes192-ctr -L 2049:127.0.0.1:2049 SERVICEUSER@NFSServerIP sleep 365d

The above command runs in NFS client takes any traffic directed at NFS client's local port 2049 just forwards it, first through SSHD on the remote server (NFS server), and then on to the remote server's(NFS Server) port 2049. This port forwarding can run as background process which can be running in defined long periods. The user session b/w NFS client and NFS Server will be created by the SSH Session Key pair (RSA public & private keys) and login will happen through the key files instead of typing passwords.

Hoping it would have given a basic understanding of how Tunnel over SSH port forwarding work.

Lets move into the implementation:

Configuring NFS Server and NFS client




Now the Tunnel over SSH successfully enabled, all incoming traffic to NFS client ports will be forwarded to NFS server ports through SSHD.

Few points to notice in above commands
Aes256 – forward forwarding uses AES 256 cryptography algorithm
-f - which makes the port forwarding to run in background ssh persists until you explicitly kill it with the Unix kill command.

Now let's configure the Kubernetes

Configuring Kubernetes persistent volume and claims

That’s all, now just deploy this pod and K8s PV volume files. Once deployment done, a persistent volume within K8s with Tunnel over SSH enabled mount will be created in NFS client (linux node)

Let’s verify things :

First, lets verify the PV volume mount is created in the NFS client (linux node)

[root@NFSClient ~]# mount | grep nfs

You would get an output like

localhost:/NFS_Senstive_Data_Share on /var/lib/kubelet/pods/794ea09e-0354-436d-9498-6038f352e64c/volumes/kubernetes.io~nfs/nfs-pvclaim-sensitivedata type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=127.0.0.1,local_lock=none,addr=127.0.0.1)

and also verify SSH Tunnel is active using below command

sudo lsof -i -n | egrep '\<ssh\>'

Second, let’s try to access the volume mount path inside Kubernetes pods.

[root@NFSServer ~]# kubectl exec -it nfs-in-a-pod -n myproductNamespace -- sh
[root@NFSServer ~]# cd /mnt
[root@NFSServer ~]# ls  ------ here you can see the files inside the NFS shared folder.

That’s all, now the volume mount is created inside Kubernetes POD and the traffic between NFS Server (Linux Mode) and NFS Client (Linux node or K8s pods) are ENCRYPTED !!!