Files
hpr-knowledge-base/hpr_transcripts/hpr2863.txt

242 lines
16 KiB
Plaintext
Raw Normal View History

Episode: 2863
Title: HPR2863: Simplified application architectures for improved security
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2863/hpr2863.mp3
Transcribed: 2025-10-24 12:25:50
---
This is HBR episode 2008-163 entitled Simplify Application Architecture for Improved Security.
It is hosted by MEMA and in about 16 minutes long and currently in a clean flag.
The summary is a thought experiment in whether reducing runtime dependency can improve security
and how to do it.
This episode of HBR is brought to you by An Honesthost.com.
Get 15% discount on all shared hosting with the offer code HBR15.
That's HBR15.
Better web hosting that's honest and fair at An Honesthost.com.
Hello again, this is Beezer on Hacker Public Radio.
Whenever I install a new Linux application, I'm often struck by a large number of dependencies
that are installed alongside it.
We accept it as part and parcel of the way applications are constructed, but it raises
an issue which is becoming increasingly important in our area of cybercrime and cyber
terrorism.
Every interface between the components in an application is an attack surface, the
sound at being the case, and every dependency represents a potential vulnerability.
There are greater number of dependencies, and the greater potential for the application
to be compromised in one way or another.
It must follow then that if we reduce the number of dependencies an application relies upon,
then the more secure that application will be.
Well, that got me wondering how realistic it would be to change the way applications
are developed, and the implications that will bring with it.
When I first started developing software in the 1980s, it was on our Vax computer running
the VMS operating system.
The projects I worked on used for train and a language called Coral 66, which was the
standard in a defence industry for either took over from it.
Now the workshop, but the workflow was the same for each, a simple three-stage process.
You wrote your code, you compiled it into an object file, and then used a linker to produce
it executable.
If you're working alone, then there was usually just a single object file, but depending on
how you chose to organise your project, you might have several, which was sometimes a
handy approach if you wanted to reuse code across multiple projects.
At the end of that process, you had a single executable which could in principle be copied
to any other Vax, with the same version of the VMS running on it, and the application
would run fine.
It made the distribution and the installation of the application very simple.
If I look at the way applications are structured now, whether it's on Linux, Windows, or
Mac, it's all very different.
The 1000s library's providing functionality which in theory can be shared by any application
designed to use them.
It's a powerful approach in which removes the need for developers to be forever writing
new code to deliver what's really fundamental or generic functionality.
It does, however, make the distribution and the installation of the application a lot
more complex.
While it is the way developers have become accustomed to working, is it really the right way in
this day and age when security considerations alter out ways simple convenience?
Could there be an alternative approach which simplifies application architectures and
in doing so improves security while coincidentally providing a big win for open source software?
Before I elaborate, I'll just make it clear that I'm a huge supporter of free software
as defined by the FSF.
In this context, though, I really do mean open source software, software whose source code
is available to view, regardless of whether the license attached to it is free or comes
with some kind of restriction.
It's probably best to start with a view of how things have come to be the way they are
now.
When the personal computer first became mainstream, memory was both expensive to buy and it was
in short supply in terms of how much of it your PC could address.
640k was the limit on early PCs, the amount of display you could use was less restricted
by the operating system, but highly restricted by the death of your pockets.
My first PC, an Amstrad 1512, came with a single 7-inch floppy disk drive and the disk
it could read held just 360k.
What I really wanted though was to get into the big league and have a hard disk.
Eventually I bought one and it cost me £200, which at the time was best Bible weeks wages
and had a capacity of 20 megabytes.
Here you heard that right, megabytes.
With those kinds of restrictions, there was a huge incentive to keep application executables
as small as possible.
Now, fortunately in those early days when everything ran in text mode, the amount of memory
required to rend your user interface was small.
In about 6K of memory, you could define that in entire screen displaying the standard 80
by 25 character matrix, including the 4 round and the background 8 bit colours for each.
That is, if you had a colour monitor, which was far from standard in those days, there
still left most of your RAM available for the operating system and the applications to
run in.
The introduction of graphics mode changed all that.
If you were lucky, your monitor had a graphics resolution of 640x480 pixels and that could
generate the same 16 colours.
It made for a much sharper and more useful display, but suddenly you could be close to using
half your RAM just to render an image on your monitor.
That provided even more sense to the keep application small.
As time went by, Microsoft developed what could only really be described as workarounds
to allow the operating system to address memory above 640k.
This was the so-called upper memory which enabled a total of 1024k or one megabyte to be
addressed.
Eventually that progressed further still and we got extended memory, which in theory
provided the potential up to 4 gigabytes of RAM.
I saved theory because that kind of RAM just wasn't available at that time for any price.
In 1990 when companies were just beginning to take Microsoft Windows seriously, the IBM
PS2 was pretty much the benchmark machine for corporate buyers and that typically came
with no more than 2 megabytes of RAM at a hard disk or perhaps 40 megabytes.
At that time, Windows was really just a graphical interface to DOS.
You effect by default, your computer would still boot to a DOS prompt and it was only through
a command in your auto-exec file that you end up in Windows and start up.
Now with DOS and Windows running, you're reaching out to a lot of that very limited memory
and using a substantial chunk of your hard disk as well, and that's before you installed
and run any applications over what came standard with Windows.
Now fortunately, Windows had a trick up its sleeve to make the most of those mega resources.
This was the dynamic mint library.
This was essentially a new executable file which could be called by any application that
would be running.
The clever part was that a copy was only loaded into memory by the first application
calling it.
Any subsequent application calling it would use that same copy.
This meant that the use of memory was optimised and through the liberal use of standardised
DLLs delivered as part of the operating system, the size of the application's own executable
could be reduced, thereby easing the demand for both disk space and RAM.
The typical amount of disk space available on a PC grew a lot faster than did the typical
amount of RAM.
Microsoft addressed this fact and implemented more and more functional components and Windows
as DLLs.
It meant that a well-crafted Windows application could minimise its own compiled size, so
the introduction of fundamental runtime components in visual basic and visual C++ automated as
principle.
The application executable would make most of its cores at a runtime, and the runtime
was designed to involve those cores to the appropriate DLLs.
Each of the B3 operating systems in widespread use today implores this principle of functional
devolution which ensures developers are not forever reinventing the wheel.
It's a principle which does, however, sometimes create cascade of dependencies.
In its worst cases, the existence of some of those dependencies may be mutually exclusive
resulting in applications which cannot be run in the standard operating system environment.
On Linux, new packaging technologies such as Snap, Flatpack and App Image were being
developed to address this scenario by installing application into a compartmentalised environment.
But the application still has the same number of dependencies, each of which represents
a potential security vulnerability.
When we look at the typical laptop or desktop today, there's no fair comparison with the
PC's, early 8's and 90's.
With RAM and display, it multiplied by a factor of well over 1000 to levels which would
have seen miraculous in the days of the PS2.
I have a display of memory and CPUs in my Linux desktop, but neither often exceeds 25%
of what is available, and even when it does, it's only for the briefest periods.
Well there will always be some users like gamers and graphics people who flock their machines
to the maximum for most of the time of course, but they are the exception most desktop
class computers are far more RAM than ever really need for a typical use.
You'll see then that we are still constructing our applications according to the practicalities
in the constraints of 30 years ago rather than the realities of today, and in doing so
we're creating opportunities for attackers which could be significantly reduced if we
made better use of the kind of resources available to the average present day computer.
So they are to be simplified the architecture and application.
In principle we just need to internalize as far as possible the functionality which is
currently delegated to external libraries.
I say just, but how simple that is depends on a number of factors.
If your application is developed using a compiled language, then libraries can be statically
linked at compile time so that their functionality becomes embedded within the applications executable.
That means gathering object files for all the libraries you'll be calling and then linking
them to the object file of your application.
Perhaps in time it will be possible to create object file repositories but most straightforward
way to obtain them at the moment be for the application developer to compile them from
source.
All mainstream compiled languages as far as I'm aware can be linked to libraries coded
in different language.
Typically it will be CRC++.
What happens though if you've developed your application in an interpreter language such
as Python?
I'm no Python expert but I believe it will be necessary to translate the source and library
or release the parts that you need to use into the same language.
Of course, executable libraries do get upgraded from time to time, so help me ensure that
those changes get propagated into every application that has its functionality embedded through
code inclusion or static linking.
Well on the face of it that's another problem but let's look at the evolution of a library
compared with the evolution of an application.
When the library is an external object called dynamically runtime, as long as the interface
remains unchanged, a new version can be installed without any change required to be application
or calls it.
That's very handy.
However, why would a library need to change anyway?
Once its core functionality is proven and trusted, there may be a change to improve performance
but the likelihood is that the main driver for change will be security and the impact
of that will almost certainly be at the interface.
However, if that interface is not exposed due to being within the application instead
of external to it, then it ceases to be a consideration.
There's probably no need to modify the expanded application code or relink against an updated
object file.
In effect, if the library developer publishes a new version, since it's open source that
developer of any application he used it can study the release notes and decide whether
any change to the application is needed.
It's scarcely needs to be pointed out that there's more logic is encapsulated in application
that bigger will become its executable.
Now, I've already addressed the fact that for the majority of use cases, the modern
computer has plenty of surplus memory and plenty of storage, accommodating and running
larger executable should really not be an issue.
I have not reached the theoretical advantage of low once run many times that applies to
many libraries will be lost.
Again, though, with the results profile of a modern computer, that's hardly an issue
at the application level.
I would agree, though, that at the operating system level, where a low level function may
be called a huge number of times, you'd not want a separate copy loaded every time.
I stress over for the purpose of this discussion, I'm really looking just at many level applications.
So, to summarize, what is it that I'm suggesting, well, I'm proposing that the installation architecture
of menu level applications be simplified by reducing the number of external dependencies?
The purpose, by reducing number of dependencies, you reduce the number of interfaces and thereby
the number of attack services.
So what are the downsides?
Well, there's several.
A green and implementing new ways of managing libraries would need to be found, given
that phasing out most external dependencies would take a long time, it would require repositories
or object files and source translations to be maintained in parallel, and that's no
small task.
Application developers will need to keep a watch on the third party code or object files
they use and assess what impact any changes have on their application, and that's potentially
a long-term commitment.
So, as anybody actually going to do this, is anybody going to say, you know, that bloated
piece of HPR is right, I'm going to re-engineer all my applications to get rid of external dependencies.
Well, no, of course not.
The effort and organisational changes seem hard to justify at the moment.
However, cyber attacks are not going to go away.
If anything, they're going to increase both in number and in sophistication.
The time will come when the industry starts to look for additional ways in which an application
can be made less vulnerable.
I don't in any way claim to have followed every strand of this idea to its logical conclusion,
but fundamentally though, I do believe that reducing number-extel dependencies and application
uses has got to reduce its vulnerability to attack.
The installation architectures we use now date are convenient, but they have arisen from
the need to operate within the technical constraints of decade to go.
Convenience can no longer be the overriding consideration, but that's not to say new
ways of working cannot become equally convenient once they become established.
There's a big advantage here for open source software.
Preparatory software developers are not bit of willing to open source their products or
provide object files for third-party developers to link against, as it could open the door
to a measure of reverse engineering.
Software security people have to acknowledge that there are practical limits to which a
lot of proprietary software can be simplified architecturally in order to increase security
In total contrast, developers of open source software will already be able to audit and
verify every line of code that makes our application will be able to give additional
reassurances regarding security by virtue of that simplified architecture.
Just a thought, bye.
We are a community podcast network that releases shows every weekday Monday through Friday.
Today's show, like all our shows, was contributed by an HPR listener like yourself.
If you ever thought of recording a podcast and click on our contributing to find out how
easy it really is, HECA Public Radio was founded by the Digital Dove Pound and the Infonomicon
Computer Club and is part of the binary revolution at binwreff.com.
If you have comments on today's show, please email the host directly, leave a comment
on the website or record a follow-up episode yourself.
Unless otherwise stated, today's show is released on the creative comments, attribution,
share a light 3.0 license.