Sunday, 24 March 2024

Having a Distrustful Mindset

 


I've talked previously about the concept of zero trust as it relates to security. When trying to apply an over arching philosophy like this it can feel quite daunting as to where to start.

Rather than having to create a comprehensive design in how to re-engineer your existing applications and network it can help to start with a shift in mindset in how you view the security properties of your system.

Security is an ever evolving discipline with many different facets so I wouldn't want to give the impression that the items I mention below are the only things you need to think about, but I think they do help foster the kind view that you need to have a healthy distrust of the world around you.

Authenticate

Authentication is the process of identifying the actors within a system. Traditionally this means authenticating users via them supplying a username/password or other such shared secret.

But this can also be extended to cover many other links in the chain.

This might include identifying the client or application the user is using to make the requests, the network the requests are coming from or even the physical device that is being used to communicate.

It's possible for all of these aspects of the flow of data to be used to indicate that something malicious maybe happening, and therefore properly identifying all these elements will enable you to asses if you can trust them.

Properly identifying all elements also enables comprehensive logging of any actions performed.

Authorise

Once you've identified these elements you can move onto to authorisation. This is the process of deciding if the requested operation should be allowed. Normally this would mean is this user allowed to view this data or perform this action.

But again the concept can be extended to cover more aspects of the system. Should this client or application be allowed to perform this action? Should these kinds of requests be allowed from this area of the network? Should this physical device be used to perform this action?

Going beyond authorising just the user again increases your ability to both detect malicious actions and prevent them.

Authorisation can also be linked to the method being used for authentication. Some actions a user may want to perform might be linked to needing a higher level of authentication. As an example some admin actions might require multi-factor authentication onto top of a username and password.

Encrypt

Pretty much all applications involve the movement and manipulation of data, and a large number of threats will relate to trying to expose that data to parties that shouldn't be able to view it.

One defence against this is to make sure that at the points where the data doesn't need to be viewed or worked with it is encrypted.

This will broadly come down to encrypting the data at rest and in transit. When the data is being stored and when it is being moved it should always be encrypted, the only time it should be in plain text is when it is being shown to the user. A user that has been properly authentication and authorised to view that data, via that application, from that network using that device.

This mindset should also be applied to other aspects of data sensitivity, identifying which data items are sensitive and how they are being transported. An example of this would be considering what data items are being included in the query string of requests, because this might be logged in various places data within it should be assessed for sensitivity.

Authentication, authorisation and encryption aren't the only security related factors you need to be thinking about. But embracing them and thinking about them in a greater depth will help you dive deeper into the security of your software and system and be aware of a greater breadth of possible threats. 

Saturday, 16 March 2024

Hacking Humanity

 


The modern technological world is a dangerous place, many evil actors are lurking around every dark corner with designs on your data, or simply wishing to impact your business just to show they can.

Many of these potential hackers will look to exploit flaws in your software, we should all be aware of the OWASP top ten and how code can be made to do things it wasn't intended to do. 

However there is a class of attacks that have nothing to do with exploiting flaws in software and instead are about taken advantage of flaws in human nature. Social Engineering is the process of using human psychology in order to manipulate someone into undermining the security of a system and play an unwitting role in an attack.

The nature of these types of attacks are very different to technological based attacks and so therefore are the possible defences against them.

Cognitive Bias

All Social Engineering attacks exploit some aspect of cognitive bias, this is the human tendency to make incorrect decisions based on flaws on how we interpret information being presented to us.

The exploitation of these biases can take many forms but most are trying to persuade us to take an action that will ultimately lead to harm. The below is not an exhaustive list but demonstrate some of the techniques and why they work.

The Halo Effect attempts to get you to concentrate on a particular aspect of a communication whilst ignoring information that should lead you to question what is on offer. An example would be receiving a notification that you've won a prize, the positivity of that news is designed to distract you from thinking about the fact that you never entered any kind of competition or how your contact details were obtained.

Recency bias exploits the tendency to place more importance on recent events over historical ones. Attacks of this nature are timed to appear to align with recent experiences, many examples of this would have been seen during the COVID pandemic.

Authority bias takes advantage of our unwillingness to challenge someone or something that has perceived authority over us. Examples of this would be emails that claim to come from a senior work colleague or a government department.

There are many more examples of cognitive bias all of which use some aspect of human psychology to get us to ignore information that should make us suspicious in favour of information that makes us feel we should act.

Vectors of Attack

Social Engineering can be exploited in many different forms of social interaction and communication. Again the below is not an exhaustive list but acts as examples of the vectors these attacks may use.

By far the biggest vector is phishing and its variations. Whether it be an email, instance message, SMS or phone call all phishing attacks are designed to get the victim to expose information or take an action because they are duped into thinking the instruction is coming from someone it isn't.

This might be someone exposing their credit card information because they think they are communicating with their bank or someone clicking on a link that installs malware because they think it relates to a planned delivery.

Spear phishing attempts to make these attacks even more convincing by crafting the attack to be specific to an individual rather than generic in nature. 

A similar vector is that of impersonation, access may be granted to a building to an individual because they are dressed in an official looking manner or because they meet a stereotype of how we expect certain individuals to present themselves.

Tail gating is another example of a physical social engineering attack where an attacker will follow someone into a secure building looking to exploit a human tendency to avoid conflict or to openly question an individuals actions.

Possible Defences

The first and most affective defence against social engineering is education. Teaching people that these techniques exist and the impact they can have will hopefully foster a natural suspicion of unsolicited communication before taking action.

Combined with this education many organisations undertake regular testing of employees. This will often take the form of them being exposed to emails or other communication that exploits the same aspects of cognitive biases to get them to take a certain action. This represents a safe way for people to realise they have been exploited and learn for next time when the attack may be real.

Some defences are technical in nature, for example employing principles of least privilege and zero trust can help to ensure that the blast radius of any attack is kept to a minimum. An example would be ensuring employees have the minimum level of system access needed to fulfil their roles, meaning if their account is compromised the attack gains limited access and influence.

Social Engineering is at least as bigger cyber threat as attacks that exploit technical flaws. The aims are usually the same, information exposure and taking control over a system. Where code can be scanned and tested on a continual and automated bases to find and rectify technical flaws, it is often a harder problem to solve to make individuals aware of their cognitive biases and how they can be exploited.

But knowing they exist is a pretty good step in the right direction.

Sunday, 25 February 2024

Resting in Style

 


The majority of software engineers who have had any exposure to server side applications, either by building them or consuming their functionality, will be familiar with the idea of a RESTful API.

Sometime the concept of an API being RESTful is framed just in terms of its interface, its use of URIs, HTTP verbs etc.

However Representational State Transfer (REST) actually goes beyond just a definition of an interface and describes an architectural style for how server side software can be built and consumed by clients.

Early Days of the Web

By the early 90s the web was starting to become prevalent in peoples lives with websites becoming available beyond the academic institutions that had pioneered the web's invention.

As it became clear that the web's adoption was growing at pace, pressure started to grow to formalise its as yet relatively loose architecture. This flexibility was one of the web's strengths but without some formal standards to govern how its functionality could be consumed there was a risk it would become fractured.

To address these concerns organisations such as the World Web Consortium (W3C) and the Internet Engineering Task Force (IETF) put together a series of working groups to document a more formal approaches to some of the key web technologies such as HTTP an HTML.

One of the people involved in these working groups was a computer scientist called Roy Fielding. As part of this work Fielding developed the concept of a REST architecture that cumulated in his 2000 PhD thesis "Architectural Styles and the Design of Network-based Software Architectures".

This thesis defined a series of constraints that when followed would create a system with a RESTful architecture.

REST Constraints

The first REST constraint is the one we are maybe most familiar with, that of a Uniform Interface. The constraint dictates that your system should have a uniform API interface where data within your system is represented by a collection of resources.

Resources might be customers, products, user reviews or any other data your system provides access to. Request URIs identify the resources they want to work with. The data returned in API responses are a representation of a resource rather than necessarily being tied to how the resource might be stored in the backend.

Resource representations are self describing to give the client all the required metadata in order to process the data, an example of this would be the Content-Type header that includes metadata about the data representation. Resources should also demonstrate Hypermedia as an Agent of Application State (HATEOAS) where it provides links that can be used to obtain related resources, such as customer linking to their previous orders.

The next constraint is that of Client/Server, this states that clients and servers should be able to evolve independently without a dependency on each other. A client should know only about the API interface being offered by a system and have no knowledge or dependency on how that interface is being implemented.

A constraint which follows from the client/server approach is that of a Layered System. Building a system as a series of layers allows for a loosely coupled architecture where multiple systems maybe involved in data processing and storage whilst a uniform interface is presented to clients.

The next constraint says that all interactions between a client and server should be Stateless. A server should not store state related to previous requests from a client. If a client applications state is relevant in the processing of a request then this request should contain all the necessary information the server needs in order to process it. An example of this would be the fact that all requests should contain authentication and authorisation information to prove a user of the client has previously logged in.

Resources will often not change on a frequent basis, in order to address this and make sure interactions are efficient, then each resources should indicate whether or not it is Cacheable. This involves both the resource representation indicating if its cacheable and for how long, as well as clients being able to query if the resource representation they currently have is still accurate.

The final constraint was deemed optional and is not one that you will see frequently applied. Mostly when consuming APIs they will be data driven and provide static representations of data in formats such as JSON, HTML or XML. However a situation was envisioned where it might be necessary for an API to return functionality to deal with data as part of the response. The Code on Demand constraint described how an API could return executable code alongside data to increase the functionality that could be offered via APIs.

Modern Relevance

The use of the web in the modern world is probably far beyond even that which was envisioned in the early 90s when the need for engineering standards was first being identified. 

It is testament to the work done by the working groups involved that the REST constraints are as relevant today as they were then.

You will not see many server applications that completely follow all these constraints, some pragmatism is often required to adapt them to your particular application and its nuances. 

What is more important is to value the architectural properties they promote. Scaleability, modifiability, portability and reliability are examples of these properties that are never going to fall in or out of fashion even if the technologies being employed are subject to these changes in favourability.

Good engineering and an understanding of what good looks like for an application will always remain relevant even if the world the applications exists in does.

Sunday, 4 February 2024

Leading in Software Engineering

 


Aspiring software engineers are often keen to understand how they can progress in their career to a leadership position within their team or their organisation.

Clearly a certain level of technical competence is going to be a requirement but there is also a number of soft skills that are often the make or break factor. 

If you have the correct aptitude then correcting any omissions in technical knowledge can be easily addressed, but developing the softer skills can often require a more conscious effort.

Software within Context

The majority of the companies you will work for aren't in the software engineering business. Software is instead a tool being employed to achieve other business goals.

Understanding the business context within which you are creating software is important, the software itself isn't the end goal, the things it can achieve are. Allowing this context to influence the engineering decisions you make will increase the effectiveness of your engineering output.

You don't necessarily have to become an expert in how your company operates. But an understanding of its source of profitability, its customer base and its goals and motivations will enable you to become a more rounded operator.

Don't just see yourself as an engineer, see yourself as someone with engineering skills working towards a common goal.

The Reality of Technical Debt

Many engineers will frequently become frustrated at business decisions that they feel are impinging on the quality of their software.

This passion to be involved in quality engineering is an asset and is much better than a "that'll do" attitude. But a pragmatic outlook is going to be required to avoid becoming too disheartened.

It is unlikely to be the goal of your company to produce quality software, that will probably never be stated, but going back to the idea of business context, the business will have goals that are wider than pure engineering excellence.

This means decisions will be made, for legitimate business reasons, that are counter to what you might like to see within an engineering context. This means technical debt is just a reality of life, but there are good and bad ways to deal with and manage technical debt.

Technical debt is only technical debt if you understand you are incurring it, if you are oblivious to it then you're just writing bad software. Often the skill as a leader is to identify where technical debt is unavoidable, trying to limit its scope, making sure a plan exists for paying the debt back in the future and ensuring the fact it is being incurred and its impacts are properly communicated.

Being a zealot and refusing to compromise or co-operate with the business is going to make you less effective. 

Helping People Help Themselves

When you move into a leadership position its often tempting to think you have to do everything yourself, this lack of delegation can lead to a tendency to do rather than teach.

As a leader others will often come to you with problems they are struggling to solve. It may be tempting to simply solve the problem for them, but in doing this you are restricting their ability to learn and grow.

Sometimes a problem might be urgent or have severe implications meaning you need to take ownership of the situation. But on other occasions rather than solve the problem for somebody you can instead guide them to the right solution and give them the skills to repeat the process in the future.

This will also extend to letting other know it's ok to not know the answer. Others will often assume that you know the answer to all problems, making them understand that you don't and in fact you just have developed a set of skills to help you find the answer will help those individuals acquire the same skills.

It's tempting to think that a leader in a software engineering team is equivalent to the chief geek and the best engineer. While it's likely that someone with the aspiration to lead will also have strong technical skills that is not the only qualifying factor in being an effective in a leadership role.

There are other softer factors that can require us to re-think the way we view our role but will ultimately make you a more well rounded engineer and successful leader.

Sunday, 28 January 2024

The Problem with Castles and Moats

 


Pretty much any system accessible via the internet can expect to come under regular attacks of varying sophistication. This may range from the simply curious to those that mean to cause harm and damage.

Protecting yourself from these intrusions is therefore a key activity in the day to day operation of any team.

But is it realistic to expect to always be able to keep attackers at bay on the edge of your infrastructure? Are external threats the only thing you should be concerned about?

Zero Trust Security takes an approach that answers no to both those questions. It tries to instil defence in depth to ensure you protect yourself from many different attack vectors and actors.

Castles and Moats

A traditional approach to security, often termed castle and moat, takes an approach where access to a network is hard obtain, but once access is granted then there is an implicit trust of anyone and anything inside the network perimeter.

The source of this implicit trust probably comes from a desire for convenience but also a belief that attackers should be kept outside the network at all times.

Of course keeping attackers outside should be the goal, but the problem with castle and moat is that if an attacker does gain access, which is unfortunately likely to happen given the abundance and skill of some attackers, they then have free reign within the network to do what they like.

Principles of Zero Trust

Zero trust security is based on a set of principles designed to remove the implicit trust that comes with a castle and moat approach. These principles assume that attackers and both inside and outside the network, therefore no user or device should be trusted unless they are verified and their access validated.

The fact that both users and machines are part of the trust evaluation is key. Rather than a network being open with access permitted from any part to any other part, the network is segmented into different areas with rules enforced over which parts of a network can connect to which other parts.

Another important consideration is that of least privilege, this means even after a user or device has been authenticated they are only authorised to have the lowest level of access required to fulfil their role.

Zero trust will often also employ mechanisms to limit the risk of the exposure of credentials. This might be the regular rotation of passwords, implementing multi-factor authentication and a requirement for regular re-authentication rather than long running sessions.

Advantages and Benefits  

All of these measures are deigned to limit what an attacker on the inside of the network can achieve, and crucially to prevent them being able to roam the network at will.

Rather than fighting one battle with attackers on the perimeter with high stakes we assume at some point we will lose and try to defend our assets and resources on multiple levels.

Zero trust also acknowledges that threats don't just come from the outside world. Someone who has legitimate access to the network might also have malicious intents. These so called malicious insiders can cause as greater damage as any external attacker, and have the added advantage of understanding the network topology and operation.

It's an unfortunate reality of the modern technology landscape that no system or part of a system can be deemed completely safe. The battle with would be attackers often becomes an arms race, placing your faith in your ability to always win this race can leave you open to large amounts of damage for any momentary slip in your ability to repel attackers.

Assume its possible they might get in and protect your network and your data from all possible angles. In this instance it isn't paranoia, they really are out to get you. 
      

Sunday, 14 January 2024

Backend for Frontend

 


Any software engineer that has worked within the client server model will be familiar with the generalised categorisation as applications as frontend or backend.

Backend applications provide access to data and apply the necessary business logic around this access and the updating of these data sources. Front end applications provide an interface for users to view and interact with this data.
In most situations these applications are running in separate environments, such as a users browser or mobile phone in the case of the front end applications, and a remote server for the backend application. Interaction between these two applications is then generally achieved via some sort of API interface.

Having this separation allows both applications to be developed and deployed independently but the design of the APIs that binds the two together is key to drive this source of efficiency. One approach is of course to have a traditional generic API interface designed to serve many possible uses, but a Backend for Frontend (BFF) takes a different road in order to provide an interface specific to the needs of the frontend it is serving.

The Problem of Many Frontends

Let's imagine we start working on a web frontend application to provide functionality to users via the browser. We develop a backend API to provide access to the necessary data and functions with the development of both apps proceeding in tandem.

Our product is a success so we are asked to produce a mobile app to provide access to the same functionality, so we drive this mobile app from the same backend API. Clearly it will be possible to build the app using this API, but is it the optimal approach? A mobile device comes with very different limitations to a desktop browser. This is in terms of performance, network access, screen real estate and just the general way in which users tend to interact with it.

We are then asked to provide access via a voice based app for a digital virtual assistant where we have to deal with the problem of having a very different medium to communicate with our users.

These competing needs put a lot of pressure on the team developing the backend application, creating a bottle neck in development and making it difficult to maintain a consistent and coherent interface to the API.

But what about if we took a different approach?

Backend for Frontend

That different approach is the concept of a Backend for Frontend (BFF).

A BFF is a backend application where the API interface is tailored specifically for the needs of the frontend it is designed to serve. This tailoring includes the data it exposes, both in terms of depth and shape, as well as the orchestration of business processes the user may wish to trigger.

In our above example we would build separate BFFs to serve web, mobile and voice.

The web BFF would expose larger amounts of data and provide access to more complicated business flows requiring multiple interactions. The mobile BFF provides access to a more compact dataset to reduce the amount of data passing between frontend and backend, as well as providing an increased level of orchestration to reduce the number of API calls involved in implementing an outcome. The voice BFF returns a very different data schema to provide for the unique user interface thats required.

Most likely all three BFFs are built on top of an internal enterprise API layer meaning their sole responsibility is to provide the optimised interface for the frontends they aligned to.

Development of the BFF can sit alongside the team developing the paired frontend application leading to less bottle necks in development allowing for each channel to operate on its own release cadence.

Pitfalls and Considerations

So does this mean a BFF is an obvious choice when developing within the client server model? There are very few absolutes in engineering so like any pattern its never the case that it should be applied in every situation, and careful consideration still needs to be given to its implementation.

Firstly you do need to confirm that your frontends do have different needs. Above I've made the generalisation that mobile and web frontends can't efficiently be driven by the same API. In general that might be a reasonable assumption to make but you should take the time to asses if the optimal API surfaces would actually be different for your use case.

Secondly you should consider how to implement multiple BFFs whilst maintaining strict separation of concerns to avoid duplication. A BFFs implementation should be solely concerned with the shaping of data and functionality for the frontends they serve. Internal business rules should be implemented in a different shared layer rather than duplicated across the BFFs, failure to do this will lead to inconsistencies in experience as well as creating inefficiencies in development.

Lastly consideration should be given to the fact that a BFF approach leads to more applications being developed and deployed. Failure to have teams structured to develop within this model and to have a good DevOps story to manage the increased number of deployments will stop you achieving the promised increase in efficiency.

So many systems demonstrate the frontend/backend split that the devil in the detail of how these applications will interact is one of the most important factors in how successful your efforts will turn out to be. The performance, usability and development efficiency of your applications is in large part going to be related to how you implement this interaction. BFFs should be one of the tools at your disposal to ensure frontend and backend can work in harmony to deliver great outcomes.

Sunday, 7 January 2024

Teaching the Machine



In my previous post on Large Language Models (LLMs) I referred several times to the models being trained, but what does this actually mean?


The process I was referencing is known as Machine Learning (ML), it comes in many different forms and is probably the most important and time consuming aspect of building Artificial Intelligence (AI).


Much like our own learning, the training of an AI model is an iterative process that must be fine tuned and repeated in order to ensure a workable and useful model is delivered.


Logic vs Maths


Traditionally engineered software is a collection of logical statements, such as if-else, do-while and for-each, that form fixed predetermined paths from input to output. The problem the software deals with must essentially be solved in the minds of the engineers producing it so they can determine these logical paths.


However there are many classification of problems where it is impractical to solve them by writing software in this way. This may be complex medical problems, problems of processing complex data such as natural language or problems where the actual solution isn't known in advance.


The process of Machine Learning exposes statistical algorithms to large amounts of data in order to find relationships. This allows the trained model to generalize and make predictions or observations about unseen data without the need for explicit instructions on how the data should be processed.


Supervised Learning


Broadly speaking Machine Learning falls into two categories, supervised and unsupervised with the difference between the two being whether the required output is known in advance.


Supervised learning uses datasets that consist of many input data items, referred to as features, and a desired output known as a label. As an example we might have a medical dataset covering many different aspects of a persons health and a marker of whether or not they have a disease such as diabetes. The goal of the training is to develop a model that given someones health data can predict if they are likely to develop diabetes.


The model learns by processing the training data and identifying the relationships between the various data items, with its accuracy being assessed by how well it can produce the required output. When via a process of iteration and tweaks to the mathematical algorithms being used the model is deemed to be trained it is used to process previously unseen data.


Many types of supervised learning use some form of mathematical regression to define trend lines for datasets where this trend line forms the basis for prediction and definition of the output label.


Human experts in the problem space the model is dealing with are key in the process of identifying the data features that the model should work with and ensuring the data it is trained with is of sufficient quality and diversity to produce a workable and accurate model. 


Unsupervised Learning


Unsupervised learning, also sometimes referred to as deep learning, involves datasets that don't have a predefined label defining what the output should be. The model identifies previously unknown relationships in the data in order to cluster datapoints and find commonalties, this then enables the model to look for the presence of these commonalties in new data it is exposed to.


Examples of this type of learning might be analysis of customer buying behaviour in order to predict future purchases, the ability to recognise the content of images, or in the case of an LLM like ChatGPT the ability to predict the natural language that forms an answer to a question.


Supervised learning is generally based on neural networks. Originally based on the organisation of the human brain, a neural network consists of a number of interconnected neurons. However rather than being biological in nature, these neurons are mathematical models that take a number of inputs and produce a single output to pass onto the next neuron in the chain.


Although the types of problems that are addressed by supervised learning are generally those where there is no preconceived wisdom on the relationship between the data items, human experts still play a crucial role in analysing the outputs of the model in order to drive the iterative training process that will increase the models accuracy.


The portrayal of AI in science fiction would have us believe that a switch is flipped and a fully formed intelligence springs into life holding infinite knowledge. The reality is that its a pain staking, costly and time consuming process that requires many cycles to perfect. Machine Learning is essential the nuts and bolts of AI, services such as ChatGPT live or die based on the expertise and engineering that is applied in this phase. The fundamentals of the learning process applies equally to machines as to humans.   

Monday, 1 January 2024

The Power of Maths and Data

 


Artificial Intelligence (AI) is one of those relatively rare terms that has made the jump from software engineering into the lexicon of everyday life.

Many of the usages of the term are really nothing more than marketing ploys to engender products with a greater technological cachet. However the publics exposure to Large Language Models (LLMs), most notably in the form of ChatGPT, has given a glimpse into the potential of AI.

There is however an unfortunate anthropomorphic effect that comes with the term intelligence. When we observe LLMs like ChatGPT in action we tend to equate its operation with our own intelligence and imagine the machine thinking and reasoning for itself.

While you could have a philosophical debate about what it means to "think", I don't believe viewing the technology in this way is helpful, and is what leads to many of the perceived doomsday scenarios we are told it could lead us towards.

So what is actually happening inside an LLM?

Patterns Leading to Understanding

AI is a very broad term covering many different technologies and applications. But in general it can be viewed as using mathematics to find patterns in data and using this knowledge to predict, classify or in the case of LLMs generate output.

Whilst some applications of AI may look at a narrow dataset such as, credit card transactions to classify activity as fraud, or health data to predict the likelihood of disease, LLMs are trained on extremely large amounts of human language.

The vast size of the datasets used means the patterns the model is able to identify gives it a general purpose understanding of natural language. This enables it to have an understanding of language supplied to it as well as generating language in response.

The key aspect to keep in mind here is that this understanding of language relates to knowing the patterns and relationships between words based on the observations of a large dataset rather than an understanding of the actual words themselves. Given this set of input words, what is the most likely set of output words that statistically would form an answer to that query.

Transformers

The most common architectural pattern used to build LLMs is called a Transformer Model.
Transformer Models are an example of something called a neural network. Originally based on the organisation of the human brain, a neural network consists of a number of interconnected neurons.

However rather than being biological in nature, these neurons are mathematical models that take a number of inputs and produce a single output to pass onto the next neuron in the chain.

A Transformer consists of an encoder and a decoder.

The encoder takes input language and divides it up into a number of tokens which we can think of the constituent parts of words. Mathematical equations are then applied to these tokens to understand the relationship between them. This produces a mathematical representation of the input language allowing the model to predict the potential output language.

The decoder then runs this process in reverse to move from the mathematical representation of the output back into tokens to form the language to provide to the user.

When trained on a significantly large amount of varied data this allows the model to provide answers to questions on many subjects.

Use Cases and Downsides

The generative nature of LLMs makes them ideal for use cases such as chat bots, document generation, and if trained on appropriate data sets even specialised tasks such as code generation.

Their ability to interact also enables them to be used for applications such as chat bots along with a conversational approach to information retrieval from large datasets.

The LLM approach can also be applied to data sources other than language, allowing for audio and image generation as well as language.

However the nature of how LLMs are trained can lead to some downsides its important to be aware of. LLMs will reflect the nature of the data they are trained on, if that data has natural human bias then this will be reflected in the output language that the model produces.

LLMs can also display a behaviour called hallucination. This is where the model produces output language that while coherent isn't factually accurate or doesn't relate to the input language. There are many reasons for this but most relate to the earlier point that the models output is based on mathematical analysis rather than an in built understanding of the language it is provided or returning.

The AI revolution is real, and its potential impacts are made visible to the majority of us via LLMs such as ChatGPT or Google's Bard. It is also the interactions with these models that drives a lot of peoples fears about the direction the technology will take us. But it's important to appreciate how these models are doing what they do before becoming overly fearful or pessimistic.

Sunday, 16 May 2021

Security Pitfalls

 


Whether or not a software application will be exposed to security threats is mostly a case of when rather than if. We can often be tempted to think that we need to be more concerned by the attention of a sophisticated attacker with a large arsenal of weapons. However it's unfortunately the case that most threats are a result us failing to learn from previous mistakes.

The OWASP top ten, largely seen as the industry standard guide to prevalent security threats, has consistently been dominated by well known attacks. These vulnerabilities have been with us for a long time and have well known mitigations, yet they continue to be seen in countless applications.

In this article I won't go through all of the OWASP top ten, instead I will highlight some of the categories that the threats fall under and the mitigations that should always be at the forefront of your mind.

Don't Trust The Outside World

Still by far the most commonly observed vulnerabilities relate to applications putting too much trust into input received from the outside world. These injection attacks fall broadly into three categories, SQL Injection, Cross Site Scripting (XSS) and Cross Site Request Forgery (XSRF). 

SQL Injection can come in many forms but occurs whenever user input is directly included in SQL statements without being sanitised. This either causes more data to be exposed to the caller than they are entitled to view or allows them to run potentially destructive commands against the database.

XSS occurs when an attacker is able to inject client script into web pages being viewed by other users. XSS scripting attacks are often categorised as Non-Persistent (reflected) and Persistent. An example of a reflected attack might be when an attacker is able to manipulate the query string submitted to a page that is then in some form included in the page contents causing the script to execute within the victims browser. An example of a persistent attack might be if an attacker is able to include client side script into data that is stored by the server and subsequently rendered in multiple victims browsers, this could be via a message forum or some kind of profile page that is viewable my multiple users.

XSRF occurs when an attacker is able to get a victim to submit client side script to a page that trusts the user. This will generally involve trying to get a user to click a link or otherwise submit data to a site they are currently logged into. An example might be sending a user a link to a site that includes potentially damaging query string parameters if the user has administrator privileges.

The protection against all these attacks is to distrust all input from outside your application. Never assume that a user will only ever submit data in the intended format, sanitise all inputs and block where necessary where script or potentially executable code is detected.        

Not Implemented Here

Many well defined and proven techniques for securing applications exist, these range from encryption and authentication to data integrity checks. Often these techniques rely on necessarily complex logic and mathematics.

Although sometimes flaws in this logic can be found it is far more common for attacks to exploit mistakes in their implementation rather than weaknesses in the core algorithm. Many of these techniques can be interesting to implement, and many engineering teams will frequently have a "not implemented here" attitude only wanting to rely on code written internally.  

Security is not an area of coding to have this attitude towards, unless you are an expert in the field it will be very likely that you will make a mistake in its implementation. These mistakes may not be immediately visible and may not relate to the core application of the technique but none the less they may give an attacker the crack in the door that they are looking for.

Trust in the implementations written by experts, even they will have to release patches when small mistakes are uncovered but their expertise and ability to verify their work will put you in a much better position than if you try and go it alone.  

Undefined Behaviour

Many categories of attacks revolve around getting applications to behave in an unexpected way. These range from buffer overflow and arbitrary code execution to memory corruption and insecure deserialisation. 

Quite often these attacks exploit the very low level details of code execution, also thankfully many built in defences such as stack canaries and Address Space Layout Randomisation (ASLR) exist to try and protect you against them being exploited against your application.

Despite this you still need to be alert to when your application is exhibiting unintended behaviour. This is true even if the observed behaviour is not considered a bug. It may be that the apparent side effects are benign but it's important you always understand why your application behaves the way it does.

Attackers will very often begin probing your system by doing unusual or unexpected things to view your systems response. They will look for ways to exploit the behaviour they observe and possibly chain together multiple instances of unexpected behaviour to get the result they want.

Always take the view that if something isn't supposed to happen then the system should be configured to not allow it to happen regardless of whether or not the consequences of it happening seem dangerous. In a similar manner to injection attacks show a healthy distrust for the world outside your application and its adherence to how your application is supposed to be used.

We sometimes assume that all potential attackers are extremely sophisticated. Although such attackers exist there are many that continue to exploit relatively simple and well known attack vectors. Because these attacks are well known and have existed for some time they also have well proven mitigations. Try to ensure that your application doesn't fall prey to these defensible attacks and always be mindful of the OWASP Top Ten.