Follow us on LinkedIn and Twitter

Access Control: What Most Developers Don’t Know Can Compromise Security

Row Column Access ControlYou are a long-time IBM i (AS/400, iSeries, IBM System i, etc.) programmer and you understand the details of how the system checks authority, don’t you? I bet you don’t!

It’s the authority of the JOB that really matters.

Why am I prodding this hornet’s nest?

When developers rely on users having explicit authority to objects (via default authority or explicitly through their user profile or associated groups), it becomes virtually impossible for administrators to properly protect sensitive objects like the credit card file.

However, when the mechanisms discussed in this article are used, users can successfully run the payroll application without being able to access the payroll file directly through the command line, SQL, FTP, rexec, etc.

Developer or not, stay with me on this. Whether you are a system administrator, security administrator, application developer or architect, in order to effectively fulfill your role in security management, the first thing you need to understand is what and how the system checks for authority. And today more than ever, we all need to work together to properly secure our systems.

This discussion, at a high level, is applicable to any operating system. The specific details and terminology are different from one type of OS to another, but the general overview is essentially the same. For the most part, I’ll be using IBM i OS specific details.

In addition, I’m going to take a slightly different tack in this description of authority checking than you’ve been accustomed to hearing.

Authority Checking — So Misunderstood

What’s the big deal about checking authority? The system checks if the user has the appropriate authority to the object being accessed, right?

Well, that’s only partially true.  Relying on this idea alone as your mental model of how authority is checked will lead you to invalid assumptions about who is responsible for managing access to data on a system.

You may be thinking that I’m now going to talk in depth about group and/or default (e.g. PUBLIC) authority.  That also would be an invalid assumption.  We all know that the system doesn’t only check the user’s authority to an object. It also checks the authority of all of the groups to which the user belongs to determine if any of them (individually or accumulatively) have the appropriate authority to an object that is being accessed.  If no authority is found after these checks, the system will check the default authority assigned to the object.  In IBM i, this is called “PUBLIC” authority, in UNIX/Linux systems this is referred to as “other” or “world” authority.  Whatever it’s called, it means the same thing.  If the user doesn’t have explicit authority, then the user is assumed to have whatever the default is set to.  This is all true and important.  And there are other important details about the authority checking algorithm that I’ve left out.  You can always look these details up in reference manuals.

No. I want to show you why you need to replace the mental model you currently have about what happens during an authority check with an entirely different one!

Here it is:

The system checks if the job is authorized to access an object! That is, the system checks the authority of the job to the object being accessed at the time program executing in the job attempts to access that object – not merely the authority of the “user.”

Job Authority vs. User Authority

Even though I and many folks like me have, for years, talked about “the user needing to be authorized to objects,” that’s not the full story.

The full story is that a job’s authority is only “initialized” to the authority of the user profile (and any groups of which that profile is a member) that caused the job to be started.  There are numerous ways that the job’s authority, and the authority of a particular job stack entry, can be augmented or changed entirely after the job is started!  These mechanisms allow developers to play a very important role in security management.

By understanding access control as a check of the job’s authority rather than the user’s, developers can leverage one or more of the many mechanisms provided by various systems to make access control management a virtual no-brainer for system administrators.  Developers can, through various APIs and/or program attributes, ensure that a job has sufficient authority whether or not the user profile under which the job is running has authority.  With this approach, end users don’t require any authority to objects accessed by an application.  This, in turn, means that system administrators don’t need to manage direct authority to objects and can rely on default PUBLIC authority of *EXCLUDE (or no authority on other systems).

Controlling Job Authority

All operating systems provide various mechanisms for programmers to manipulate the authority of the job (referred to as processes in many OSes).  Many are the same, plus each OS tends to have one or two unique mechanisms.

Each OS uses a data structure that contains information about each job (or process) on the system.  Some of the information in the data structure is used by the system to perform authority checking at the time that a program in the job attempts to access a specific object.  The attributes for each job include the user profile and the group or list of groups to which that profile belongs.  The authority of the job’s user ID and group(s) are always among those used to determine if a job has the appropriate authority to access an object.  These attributes are initialized to the user ID and its associated group(s) under which a job is started.  However, these attributes can be changed dynamically by developers, through system APIs they code in their programs. Not only that, though…..these are not the only user profiles from which a job can attain sufficient authority to access data. Jobs can get authority through other user profiles associated with a job!

Adopted User Profiles

In the IBM i, “other user profiles” refers to adopted user profiles.  Programs can be configured by programmers or system administrators so that when the program is executed, the user profile that owns the program is added (i.e. adopted) to the list of user profiles that system will use to check for authority. The value of the “use adopted authority (USRPRF)” attribute is used by the system to determine if the program being loaded for execution adopts the authority of its owning user profile.  The USRPRF program attribute can be set to *OWNER or *USER. *OWNER indicates to the system that the user profile that owns the program is to be “adopted” by the job in which the program executes. The USRPRF program attribute can be set by the system administrator after the program is compiled (CHGPGM) or by the programmer at the time a program is compiled.  The default value is *USER meaning that the program does not adopt authority.

Every active program has an entry within the job’s call stack.  An active program is one that has been called but has not yet completed execution. For example, a program may call another program and sit idle until control is returned to it from the called program. If a program’s USRPRF attribute is set to *OWNER, the profile that owns that program is added to the list of profiles from which the job can attain authority. The adopted user profile remains in the list of profiles from which the job can get authority until the program that adopted that profile ends and its call stack entry is removed.  In other words, adopted authority is inherited by programs called subsequently (either directly or indirectly) from the program that initially adopted authority. Therefore, a given program may derive its authority from the:

  • Job’s current user profile attribute;
  • Job’s current group profile;
  • Job’s current list of supplemental group profiles;
  • User profile that owns the currently executing program;
  • Plus, user profiles adopted by one or more other programs that are still in the call stack.

There is another program attribute, USEADPAUT, by which developers can prevent their program from using the adopted authority available to the job at the time that program is called.  The possible values are:

  • *YES
    this program should use adopted authority already established in the job prior to this program being called), or
  • *NO
    this program should not use adopted authority already established in the job prior to this program being called.

This attribute only affects the authority adopted by other active programs called prior to the current program.  If the program whose USEADPAUT attribute is set to *NO also has its USRPRF attribute set to *OWNER, then that program will adopt its owning profile.

There is also an MI instruction programmers can use to turn off adopted authority in programs called by the program issuing the MI instruction.  This MI instruction, MODINVAU (modify invocation authority), allows programmers great flexibility if needed. A single program can call one program that executes with the adopted authority that already exists in a job and call another program that executes without the adopted authority that already exists in a job.

The system provides many ways that developers can use, control, and manage adopted authority. This flexibility means adopted authority can be useful in just about any situation developers may encounter.  As we’ll see below, adopted authority isn’t the only mechanism developers can use to ensure their programs don’t encounter authority failures.

Changing the User and Group Profiles For a Job

Adopted authority is just one of the many mechanisms available to programmers to ensure their program will not fail due to an authority failure.  There are also numerous APIs that can be used to manipulate the user profile and/or groups under which a job is currently executing.  These APIs provide more focused and sometimes subtle changes to the authority under which a program executes. These APIs typically affect the entire job; the job attributes don’t automatically change back when the program that makes those changes ends and its job stack entry is removed.

One set of programming interfaces specific to IBM i OS are the “profile swap” APIs.  The profile swap APIs allow a program to change the user profile and groups under which the program is executing.

Although the “user” part of the job name doesn’t change, the job runs under the authority of the profile to which the job was “swapped.”  No authority is attained from the user profile and associated groups under which the job was started while the job remains swapped to the new profile.

That last paragraph is extremely important to understand.

The average IBM i OS programmer assumes that user profile name that is part of the job name is the profile under which the job was running when their program executes. This is an invalid assumption!  Relying on this assumption eliminates much of the programmer’s flexibility to design and develop their applications with the appropriate security management. This has been true since the very early days of the AS/400, but a great many shops still believe that the user name part of the job name is the profile under which a the job is executing.

It should also be noted that this set of APIs also includes APIs to retrieve and save the current profile under which the job is running.  This allows the programmer to make sure that their programs swap back to the user profile under which the job was running before returning to its caller.

Associated with the profile swap APIs are the “seteuid()” and “qsyseteid()” APIs.  Instead of taking the user profile name to change to, these APIs take the UID attribute of a user profile as input.  These APIs change only the user profile under which the job is executing.  The list of groups under which the job was executing at the time the API is issued remain the same! This can be thought of as a sort of “half-a-swap” operation that affects only the current user profile.  These also have a mechanism that can be used to swap back to the original user profile under which the job was running.

The swap APIs are very effective; but they come with a downside.  Since the swap operation removes the user profile and groups (and the seteuid() APIs remove just the user profile) under which a job is executing, the audit journal entries will not indicate the original user profile.  There are other audit journal entries you can check to determine if a profile swap occurred and then use that information to look for additional entries for the same job under a different user profile.  This process can be cumbersome and take more time; especially for forensic investigations.

Fear not, though.  There are still other APIs you can use that don’t remove the current user profile or its authorities, or affect the user profile under which audit entries are written.  These APIs are used to manage the group profiles under which a job is executing.  The job structure contains an attribute for a profile’s “first group” and a different attribute for the list of supplemental groups.  The group and group list APIs are used to change only these attributes.  The setegid() and qsysetgid() APIs change the job’s “group” profile attribute.  The qsysetgroups() API manipulates the supplemental groups associated with a job.  They work much the same as the job user profile APIs do except they change only the job’s group-related information; not the job’s user profile.  By changing the job’s group or adding a group to the job’s supplemental group list, you can ensure your program will have the authority to manipulate specific objects at the time the program needs it without requiring the user running the application to be explicitly authorized.

Using Multiple Mechanisms

Of course, in order to use APIs that can manipulate such security-sensitive attributes as the user and group(s) under which a job is running, the job must be authorized to manipulate those attributes! This requires that the job have the authority of the profile (user or group) that is being changed or added to the job’s authority.

Adopted authority comes in very handy for ensuring that your program has the authority to  use the APIs that change the user or group(s) under which the job is executing.  Your program can adopt a user profile that has authority to the user and/or group profile(s) being swapped, changed or added to the job by your program.  The adopted profile can be a service user profile that has *ALLOBJ (although this is way more authority than is needed.) Or, the program can adopt the authority of the user profile to which the job will be switched, or the profile that owns the programs that make up the application can be given *USE authority to any profiles that the program may swap, change, or add to the job.

Starting a New Job

One other important aspect to remember is this:  since authority checking is job based, any time a program causes a new job to start, changes to the original job’s list of users and groups from which it gets authority are lost in the new job.  The new job will always start with the authority of the user profile (and its groups) under which the job was submitted; not under the user profile, groups, and adopted authority current at the time the original job creates the new job.

There are also many ways to handle this problem. The most obvious way is to make sure that every program that is submitted by another program adopts the same profile(s) as those in effect when the program in the original job performed the submit operation.  This is a brute force solution and other potential solutions exist, but are way outside the scope of this article.

Summary

Most developers think of access control as the sole responsibility of the system or security administrator.  This is not a valid assumption.

We typically think about the authority checking process as determining if the user that started the job (and any associated groups to which that user belongs) has the appropriate authority to the objects being accessed by a program in the job.  This is also an invalid assumption. In reality, the system checks the authority of the job at the time a program accesses an object.

Everything about the authority available to a job at any given point in time can be manipulated by developers.  There are numerous mechanisms specifically for use by application architects and developers so that access control can be managed in more efficient and effective ways than on a user by user basis.

By learning about and exploiting these mechanisms, developers can change existing applications over time and provide new ones that work perfectly even on a system where the default authority to the vast majority of objects on the system is “no access” and the average user is not specifically authorized (by the user profile or any of its associated groups) to any data objects, and authorized only to a few program objects.

If this is your first exposure to these mechanisms, they might sound very complicated and convoluted. The primary reason for this is that the system provides so much flexibility that, when you try to describe them and how they might be used, it can seem complex. In reality, you’ll normally need to use only a couple of these options in any application.  In addition, if you understand your application well enough, you will only have to change a small number of existing programs to use any of these options.

This article focuses on describing what happens when the system checks authority to an object. A future article will build on this foundation to discuss the role and responsibilities of application architects and developers in the security management process.

 

facebooktwittergoogle_pluspinterestlinkedinmail
This entry was posted in IBM i Security, Info Security Mgmt, Information Security and tagged , , , , . Bookmark the permalink.

One Response to Access Control: What Most Developers Don’t Know Can Compromise Security

  1. Pingback: Howdy Partner! The Role of Application Developers in IT Security | Botz Security Bytes

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>