What the US National Cybersecurity Guidance Means for Your IBM i

In March 2021, President Joe Biden issued an Executive Order on Improving the Nation’s Cybersecurity. The move was prompted by the convergence of multiple factors that have created an increased threat environment for both government agencies and private sector organizations.

That led the Cybersecurity and Infrastructure Security Agency (CISA) to issue a fact sheet containing guidelines for protecting against cybersecurity attacks. That document is foundational to CISA’s “Shields Up” campaign, which aims to bolster our nation’s defenses in the face of an increasingly intense threat environment.

CISA’s recommendations are limited to government entities. They offer a solid approach to protecting your business from a wide range of cybersecurity threats, including ransomware attacks, data breaches, and computer-related financial crimes.

CISA’s advice is timely and relevant for organizations of all sizes. Cybersecurity threats are intensifying. Attacks are becoming more frequent and more sophisticated. Mounting geopolitical tensions, fueled in large part by the conflict in Ukraine, have increased the efforts that rogue states are making to penetrate systems in the United States and elsewhere, including private sector businesses.

What does this mean for organizations that rely on IBM i systems to store and process their most critical business information? As part of Precisely’s Trust 22 Data Integrity Summit, security expert Bill Hammond provided information on how IBM shops can operationalize CISA’s cybersecurity recommendations. Here’s an overview of the key recommendations presented during that session:

1. Multifactor Authentication

CISA recommends deploying multifactor authentication (MFA) on all systems. This is the number one defense against malware. Usernames and passwords are easily compromised, and they’re frequently offered for sale on the dark web. MFA typically requires a combination of username, password, and a dynamically generated verification code to access internal systems. Users who don’t have access to the physical token device to generate a code will be unable to access the system in question.

IBM shops should look for an MFA solution that protects their IBM i systems, in addition to all other computing platforms. If you have already deployed MFA on non-IBM platforms, look for a vendor whose MFA product for IBM will work seamlessly with your existing environment. Unfortunately, many of the MFA products on the market fail to address this need adequately.

Look for an MFA product that protects more than just usernames and passwords. The best MFA solutions will protect database access and will restrict the execution of command-line procedures to authorized (and fully authenticated) personnel.

Read our eBook

How Malware is Reshaping IBM i Security – The rules have changed

If you would like to learn more about the evolving threat environment surrounding IBM i systems, check out our free e-book.

2. Modern Security Tools

IBM systems have a great reputation for security. That’s well deserved, but it doesn’t necessarily mean that the IBM i platform is secure by default. Administrators should clearly understand IBM security settings, including user permissions, and should implement policies that are as restrictive as possible while still permitting users to do their jobs effectively.

Lax practices often lead to security holes. Modern security tools address this problem by constantly monitoring for potential vulnerabilities such as elevated permissions that may not be warranted. Such tools can help to mitigate threats as soon as they are discovered, limiting your organization’s exposure to cyberattacks.

3. Cybersecurity Expertise

CISA recommends working with cybersecurity professionals to create an elevated defense posture against any potential threats. That means routine testing against all known vulnerabilities, routine cybersecurity audits, and prompt application of software patches and updates. It also means creating and enforcing effective policies throughout your organization, such as requiring users to frequently change their passwords.

4. Data Protection

Routine backups are critical, but many organizations fail to develop and implement procedures for testing and verifying the integrity of those backups. Testing recovery processes is critically important. Hammond also recommends keeping “air-gapped” copies of backed-up data that simply cannot be accessed by malicious actors.

Effective backup procedures are just one part of a broader disaster recovery (DR) plan. To adequately protect against cybersecurity threats, IBM shops should include security as part of their overall DR strategy. Companies should also consider implementing measures to achieve high availability (HA) for their IBM systems. This offers immediate failover recovery for mission-critical systems.

5. Security Testing

CISA recommends running cybersecurity drills so that IT personnel are equipped to respond quickly when a security incident occurs. Rapid response is essential to minimizing the damage in the event that your systems are penetrated. It can be especially useful to coordinate security drills with the testing of backup and DR capabilities.

External experts can be very helpful in ensuring that security testing is robust and free from bias. Despite the best intentions, internal personnel may be inclined to dismiss concerns and take the position that everything will work as expected. By bringing in external security consultants, your organization can benefit from a bias-free assessment.

6. Data Encryption

IBM i systems house some of the most valuable, mission-critical data in the world. That includes personally identifiable information (PII), which if stolen, could lead to fines and penalties, legal action, and reputational damage to your organization. Critical financial data and transactions are also housed and processed on these systems, making them highly attractive to bad actors.

Encryption is a key defense against hackers because it renders your data unusable to them. It’s also an essential element of compliance for many organizations, prompted by government regulations and frequently required by key customers as part of their vendor data security standards.

7. Employee Education

CISA recommends that companies educate their employees about the common tactics used to gain access to internal protected systems, such as phishing emails or malicious websites. IT leaders should put mechanisms in place to make it easy for employees to report suspicious incidents.

Organizations that run IBM i systems should ensure that their employee outreach and education efforts include information that pertains to IBM i system access.

8. Establish Relationships

Finally, CISA recommends that companies proactively engage with CISA and law enforcement agencies to build strong relationships before a cybersecurity incident occurs. A good place to start is the CISA website. Your local FBI field office also has resources that can help in the case that you experience an attack.

An effective cybersecurity strategy for organizations that run IBM systems starts with a clear understanding of potential threats and a comprehensive view of your IT landscape that includes your IBM i systems. Precisely’s IBM i security experts offer a comprehensive range of tools and advice to help organizations like yours stay one step ahead of the bad actors. You can learn more about our Assure Security offering on our website.

If you would like to learn more about the evolving threat environment surrounding IBM i systems, check out our free e-book, How Malware is Reshaping IBM i Security – The rules have changed.

The post What the US National Cybersecurity Guidance Means for Your IBM i appeared first on Precisely.

EBCDIC Code Pages and Square Brackets

Back in the previous millennium, I created a set of simple routines for handling initialization files (section & parameters) that worked all platforms. i.e. Windows, Linux, Unix, IBM i (OS/400) and z/OS (mainframe). And over the years, the routines have worked well on any platform I tested them on.
i.e. Sample initialization file

[MyTestSection]
foo=123
bar = “a test”

The problem comes when you give someone a program that has been compiled on a system using code page 37 but the customer is running their system on code page 273.

Back in the 60s/70s, when IBM was creating EBCDIC code pages, someone was smoking something because the square brackets are randomly using a different HEX values on the various EBCDIC code pages. Note: On distributed platforms, this is not a problem.

For example, on code page 37, ‘[‘ has a HEX value of 0xBA and ‘]’ has a HEX value of 0xBB whereas on code page 273, ‘[‘ has a HEX value of 0x63 and ‘]’ has a HEX value of 0xFC. Hence, in your C code, if you have something like this:

sprintf(sectionMarker, “[%s]”, sectionName);

When the compiler compiles your code, it stores the square brackets in their HEX values. So, when the program uses those routines on a different code page to find a section name (with square brackets), it will fail because the HEX values of those square brackets will not match. It’s a real pain. Years ago, I hard-coded the HEX values for square brackets for the 3 most popular code pages.

Recently, a customer was trying out a program but it was not working. It took a couple of days to realize that they were running their system on a different code page. At first, I thought I would add their code page to the hard-coded list but then I thought that solution was stupid and started hunting for a proper solution.

I decided that what I needed was a lookup table based on the code page (CCSID) and the HEX values for the square brackets. The trick was figuring out how to get the code page from the OS (operating system). After what felt like a millions searches, I can across the nl_langinfo subroutine. It is available on AIX, Linux, IBM i and z/OS. If you call nl_langinfo subroutine with the parameter of CODESET then it will return the code page (aka code set, CCSID) as a string.

Next, I found 101 EBCDIC code pages and created a lookup table of the square brackets in sorted order by code page. Finally, I created a routine to issue the nl_langinfo subroutine and then perform a binary search of the lookup table and set the correct square brackets for the program to use.

So, it in the spirit of the holiday season, I figured, I would share what I created just in case other people have similar cross platform issues.

Here is the square bracket lookup table:

#if defined(MVS) || defined(OS400)
/* Structure for table of square brackets. */
typedef struct SQUARE_BRACKETS_S
{
int codePage;
unsigned char LeftBracket;
unsigned char RightBracket;

} SQUARE_BRACKETS_T;

/*
* EBCDIC code pages and their square bracket HEX values.
*/
static SQUARE_BRACKETS_T SQUARE_BRACKETS_TABLE[] =
{
{ 1, 0x4A, 0x5A},
{ 2, 0x4A, 0x5A},
{ 6, 0x4A, 0x5A},
{ 10, 0x4A, 0x5A},
{ 16, 0xDA, 0xEA},
{ 21, 0xDA, 0xEA},
{ 22, 0xDA, 0xEA},
{ 24, 0x4A, 0x5A},
{ 29, 0xDA, 0xEA},
{ 37, 0xBA, 0xBB}, // 37 / 1140
{ 38, 0x4A, 0x5A},
{ 39, 0x4F, 0x6A},
{ 251, 0x4A, 0x5A},
{ 256, 0x4A, 0x5A},
{ 257, 0x4A, 0x5A},
{ 258, 0x4A, 0x5A},
{ 264, 0xAD, 0xBD},
{ 273, 0x63, 0xFC}, // 273 / 1141
{ 274, 0x4A, 0x5A},
{ 275, 0x71, 0x68},
{ 277, 0x9E, 0x9F}, // 277 / 1142
{ 278, 0xB5, 0x9F}, // 278 / 1143
{ 280, 0x90, 0x51}, // 280 / 1144
{ 281, 0xB1, 0xBB},
{ 282, 0x4A, 0x5A},
{ 283, 0x4A, 0x5A},
{ 284, 0x4A, 0x5A}, // 284 / 1145
{ 285, 0xB1, 0xBB}, // 285 / 1146
{ 290, 0x70, 0x80},
{ 297, 0x90, 0xB5}, // 297 / 1147
{ 330, 0x4A, 0x5A},
{ 352, 0xAD, 0xBD},
{ 361, 0x4A, 0x5A}, // 361 / 389
{ 382, 0x63, 0xFC},
{ 383, 0x4A, 0x5A},
{ 384, 0x71, 0x68},
{ 385, 0x44, 0x79},
{ 386, 0x9E, 0x5A},
{ 387, 0xB5, 0x5A},
{ 388, 0x90, 0xB5},
{ 389, 0x90, 0x51}, // 361 / 389
{ 410, 0x4A, 0x5A},
{ 423, 0x4A, 0x5A}, // 423 / 875 / 4971 / 9067
{ 424, 0xBA, 0xBB}, // 424 / 8616 / 12712
{ 425, 0xAD, 0xBD},
{ 500, 0x4A, 0x5A}, // 500 / 1148
{ 833, 0x70, 0x80},
{ 836, 0xBA, 0xBB},
{ 838, 0x49, 0x59}, // 838 / 1160
{ 870, 0x4A, 0x5A}, // 870 / 1110 / 1153
{ 871, 0xAE, 0x9E}, // 871 / 1149
{ 875, 0x4A, 0x5A}, // 423 / 875 / 4971 / 9067
{ 880, 0x4A, 0x5A},
{ 892, 0x4A, 0x5A},
{ 893, 0x4A, 0x5A},
{ 905, 0x68, 0xB6},
{ 918, 0x4A, 0x5A},
{ 924, 0xAD, 0xBD}, // 1047 / 924
{ 1002, 0xAD, 0xBD},
{ 1025, 0x4A, 0x5A}, // 1025 / 1154
{ 1026, 0x68, 0xAC}, // 1026 / 1155
{ 1027, 0xAD, 0xBD},
{ 1047, 0xAD, 0xBD}, // 1047 / 924
{ 1069, 0x4A, 0x5A},
{ 1070, 0xBA, 0xBB},
{ 1079, 0x4A, 0x5A},
{ 1081, 0x90, 0xB5},
{ 1084, 0x4A, 0x5A},
{ 1097, 0xBA, 0xBB},
{ 1110, 0x4A, 0x5A}, // 870 / 1110 / 1153
{ 1112, 0xBA, 0xBB}, // 1112 / 1156
{ 1113, 0x4A, 0x5A},
{ 1122, 0xB5, 0x9F}, // 1122 / 1157
{ 1123, 0x4A, 0x5A}, // 1123 /
{ 1130, 0x4A, 0x5A}, // 1130 / 1164
{ 1132, 0x49, 0x59},
{ 1137, 0xAD, 0xBD},
{ 1140, 0xBA, 0xBB}, // 37 / 1140
{ 1141, 0x63, 0xFC}, // 273 / 1141
{ 1142, 0x9E, 0x9F}, // 277 / 1142
{ 1143, 0xB5, 0x9F}, // 278 / 1143
{ 1144, 0x90, 0x51}, // 280 / 1144
{ 1145, 0x4A, 0x5A}, // 284 / 1145
{ 1146, 0xB1, 0xBB}, // 285 / 1146
{ 1147, 0x90, 0xB5}, // 297 / 1147
{ 1148, 0x4A, 0x5A}, // 500 / 1148
{ 1149, 0xAE, 0x9E}, // 871 / 1149
{ 1153, 0x4A, 0x5A}, // 870 / 1110 / 1153
{ 1154, 0x4A, 0x5A}, // 1025 / 1154
{ 1155, 0x68, 0xAC} // 1026 / 1155
{ 1156, 0xBA, 0xBB}, // 1112 / 1156
{ 1157, 0xB5, 0x9F}, // 1122 / 1157
{ 1158, 0x4A, 0x5A}, // 1123 / 1158
{ 1160, 0x49, 0x59}, // 838 / 1160
{ 1164, 0x4A, 0x5A}, // 1130 / 1164
{ 1165, 0xAD, 0xBD},
{ 1166, 0x4A, 0x5A},
{ 4971, 0x4A, 0x5A}, // 423 / 875 / 4971 / 9067
{ 8616, 0xBA, 0xBB}, // 424 / 8616 / 12712
{ 9067, 0x4A, 0x5A}, // 423 / 875 / 4971 / 9067
{12712, 0xBA, 0xBB}, // 424 / 8616 / 12712
};

static int SQUARE_BRACKETS_SIZE =
sizeof(SQUARE_BRACKETS_TABLE) / sizeof(SQUARE_BRACKETS_T);

/* Use values from code page 37 for default values. */
static unsigned char LEFT_SQUARE_BRACKET = 0xBA;
static unsigned char RIGHT_SQUARE_BRACKET = 0xBB;
#endif

Note #1: Most code pages have an updated code page because of the addition of the Euro currency symbol. i.e. code page 1140 is a duplicate of 37 but with the addition of the Euro currency symbol.

Note #2: The variables LEFT_SQUARE_BRACKET and RIGHT_SQUARE_BRACKET will be the variables used in the code any time the program needs to read or write information to a file.

Here is the subroutine to lookup and set the correct square brackets. Note: You should call this subroutine at the very beginning of your program’s initialization, so that it is done once before the code ever needs to use square brackets.

#if defined(MVS) || defined(OS400)
/**
* Function Name
* LookupAndSetSquareBrackets
*
* Description
* This function will lookup & set the left & right square brackets.
*
* IBM i code for nl_langinfo(CODESET) from:
* https://www.ibm.com/docs/en/i/7.5?topic=functions-nl-langinfo-retrieve-locale-information
*
* z/OS code for nl_langinfo(CODESET) from:
* https://www.ibm.com/docs/en/zos/2.5.0?topic=functions-nl-langinfo-retrieve-locale-information
*
* Input parameters
* N/A
*
* Output
* N/A
*
* Return Value
* None.
*/
void LookupAndSetSquareBrackets()
{
/* ——————————————–
* Variable declarations.
* ——————————————–
*/
int low = 0;
int mid;
int high = SQUARE_BRACKETS_SIZE – 1;
int currentCodePage = 0;
char *pCodeSet;

/* ——————————————–
* Code section
* ——————————————–
*/
printf(“LookupAndSetSquareBrackets()n” );

pCodeSet = nl_langinfo(CODESET);
currentCodePage = atoi(pCodeSet);

printf(CodeSet=’%s’ : currentCodePage=%dn”,
pCodeSet,
currentCodePage);

/*
* 1. currentCodePage of zero means we didn’t get a valid value from
* nl_langinfo call.
*
* 2. The default HEX values set for LEFT_SQUARE_BRACKET &
* RIGHT_SQUARE_BRACKET variables are from CCSID 37. Hence,
* no point in looking up the values for CCSID 37.
*/
if ( (currentCodePage != 0) && (currentCodePage != 37) )
{
while (low <= high)
{
mid = (low + high) / 2;
if (SQUARE_BRACKETS_TABLE[mid].codePage < currentCodePage)
low = mid + 1;
else if (SQUARE_BRACKETS_TABLE[mid].codePage > currentCodePage)
high = mid – 1;
else
{
/* Found it. */
LEFT_SQUARE_BRACKET = SQUARE_BRACKETS_TABLE[mid].LeftBracket;
RIGHT_SQUARE_BRACKET = SQUARE_BRACKETS_TABLE[mid].RightBracket;
printf(“Found it at index=%dn”, mid);
break;
}
}
}

printf(“Using ‘[‘ with the value of 0x’%0X’ “
“and ‘]’ with the value of 0x’%0X’n”,
LEFT_SQUARE_BRACKET,
RIGHT_SQUARE_BRACKET);
}
#endif

So, there you go. Everything you need to correctly handle reading and writing square brackets on IBM i and/or z/OS systems that use EBCDIC code pages.

Therefore, when you want to use square brackets, you simply do the following:

sprintf(sectionMarker,
“%c%s%c”,
LEFT_SQUARE_BRACKET
sectionName,
RIGHT_SQUARE_BRACKET);

I realize that the number of people requiring this type of code is pretty small but hopefully, in the future, it will save someone a few headaches!

Note: If I missed an EBCDIC code page please let me know and I will add it to the lookup table.

Regards,
Roger Lacroix
Capitalware Inc.

Verified by MonsterInsights