SCW Icons
hero bg no divider
Blog

不適切なコーディングパターンは大きなセキュリティ問題につながる可能性があります... では、なぜ私たちはそれらを奨励するのでしょうか?

マティアス・マドゥ博士
Published Nov 03, 2022
Last updated on Mar 10, 2026

A version of this article appeared in DZone. It has been updated and syndicated here.

For what feels like an eternity at this point, we’ve discussed “shifting left” in the SDLC, taking into account security best practices from the start of software development. DevSecOps was a great leap forward, in no small part because of the emphasis on shared responsibility for security, and the power of a security-aware developer to thwart common vulnerabilities as they write code. 

We have also known - again, for eons - that the type of secure code training chosen to engage and upskill developers makes all the difference. Low-effort solutions motivated solely by regulatory compliance do not build up the bright security minds of the future, and most security awareness professionals have worked that out. Dynamic, contextually relevant learning is best, but it’s critical that the nuances within are understood. 

If we’re going to have a fighting chance against threat actors - and they always have a head start on an organization - developers need a holistic training environment, with layered learning that continually builds skills steeped in best practices.

Developer-driven defensive security measures are not an automatic win.

Our ethos revolves around the developer being central to a preventative security strategy, right there at the code level upwards. That’s a given, and security-skilled developers provide the easiest path to thwarting the types of common security bugs that are apparent in poor coding patterns (like Log4Shell, as one recent, devastating example).

However, the defensive techniques that we can engage to upskill developers do vary, even if they can rightly exist in the same training bucket. 

For example, imagine you were told how to bake a cake, using only directions based on what not to do. “Don’t overbake it”, and “don’t forget the eggs” leaves it open for interpretation, and a huge potential for mistakes that will have an end result fit for Nailed It!. The same is true for defensive security education; what not to do is a very limited part of the conversation, and offers no practical advice to truly act with a defensive mindset. You can tell developers, “don’t misconfigure that API”, but with no understanding of what constitutes correct and secure configuration, there is a lot of room for error.

Developers won’t have a positive impact on vulnerability reduction without a foundational understanding of how the vulnerabilities work, why they are dangerous, what patterns cause them, and what design or coding patterns fix them in a context that makes sense in their world. A scaffolded approach allows layers of knowledge to give a full picture of what it means to code securely, defend a codebase, and stand up as a security-aware developer. And yes, part of that layered learning should be dedicated to offense, and understanding the mindset of an attacker; this is critical to hone lateral thinking skills, which are invaluable in threat modeling and defensive strategy. 

Reinforcing poor coding patterns is a pitfall we can’t ignore.

An unfortunate reality with some methods of developer learning is that the “defensive” part - even when the training is structured with offensive techniques - can reinforce bad habits, even if they are technically validating code security. 

Production of high-quality code should be the baseline in all software development, but the definition of “quality” still appears to be up for debate. The reality is that insecure code cannot be viewed as quality code, even if it is otherwise functional and beautiful. The kicker is that secure code isn’t inherently high quality, either. In other words, poor coding patterns can fix a security problem, but in doing so, introduce another one, or potentially break the software entirely. 

Let’s take a look at an example of poor quality code in the form of a fix for broken authentication, as well as the most secure version for best practice:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace BadFixesAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AlertsController : ControllerBase
    {
        private DatabaseContext context = new DatabaseContext();
        [HttpGet(Name = "GetAlerts")]
        // Does not ensure that the user is authenticated 
        public IEnumerable<Alert> Get()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, but does not check any roles
        [Authorize()]
        public IEnumerable<Alert> GetBadFix()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, AND that they have the "Administrator" role
        [Authorize(Roles = "Administrator")]
        public IEnumerable<Alert> GetGoodFix()
        {
            return context.GetAlerts();
        }
    }
}

In the first snippet, there is no check to verify that the user is authenticated, which is about as unsafe as it gets. The second, while better in terms of it performing an authentication check, fails to investigate assigned roles and whether permissions are high enough for the information requested. The third checks both user authentication and that they are assigned the “Administrator” role. In an era where least privilege access control should be the norm in most instances, it is critical that roles are set up and checked to ensure that information is only accessible on a need-to-know basis. 

The highest priority for developers is to build features, and while security is not intentionally on the back burner, they don’t necessarily have the skills to avoid poor coding patterns that lead to security bugs, and the benchmark of a good engineer rarely includes secure coding prowess. We indirectly encourage those bad habits if the features are awesome enough, and it’s this mindset that has to change. The problem is, the way some learning pathways encourage hands-on code remediation also potentially reinforces code that is secure, but of substandard quality. By applying a binary “yes this is secure / no this is not secure” assessment, rather than looking deeper into whether it is truly the best approach to resolve the bug and maintain the integrity of the software, there are devils in the detail that go unnoticed. 

Without taking developers through the entire process for a complete view of secure coding, this approach perpetuates the same issues it’s trying to solve. Imagine if we all got our licenses based solely on our ability to drive a vehicle to a destination; a pass mark even though we ran red lights, drove through a hedge, and narrowly missed a pedestrian crossing the street to arrive there. We completed the goal, but the journey we took to get there matters most. 

Developers need to be enabled to care more about creating secure software.

The modern developer has to keep a lot of plates spinning, and it’s no surprise they find security training a bore, especially when it’s not implemented with their workday in mind, and takes them away from their deadlines and priorities. It’s also completely unfair to change their KPIs to include an emphasis on secure coding, when they don’t have the skills built up from regular, right-fit learning opportunities and supplementary tooling. However, the importance of secure software development cannot be overstated, and getting developers on-side with this is crucial. 

As a former developer, generally, we want to do a great job, and being seen as a cut above others in terms of quality output is very motivating. Incentivizing developers to engage with continuous security skill-building is a no-brainer, and they should be rewarded for recognizing the importance of code-level security. Security champion programs, bug bounties and hackathons can be great opportunities to build a positive security culture, and those who roll their sleeves up and get involved should get the loot.

リソースを表示
リソースを表示

開発者は、脆弱性の仕組み、なぜ危険なのか、どのようなパターンが脆弱性を引き起こすのか、どのような設計やコーディングパターンが脆弱性を修正するのかを理解していなければ、脆弱性の軽減にプラスの影響を与えることはできません。足場型のアプローチにより、知識を重ねることで、安全にコーディングすることの意味の全体像を把握し、コードベースを守り、セキュリティを意識した開発者として立ち上がることができます。

もっと興味がありますか?

マティアス・マドゥ博士は、セキュリティ専門家、研究者、CTO、セキュア・コード・ウォリアーの共同創設者です。Matias はゲント大学で静的分析ソリューションを中心にアプリケーションセキュリティの博士号を取得しました。その後、米国のFortifyに入社し、開発者が安全なコードを書くのを手伝わずに、コードの問題を検出するだけでは不十分であることに気づきました。これがきっかけで、開発者を支援し、セキュリティの負担を軽減し、顧客の期待を超える製品を開発するようになりました。Team Awesome の一員としてデスクにいないときは、RSA カンファレンス、BlackHat、DefCon などのカンファレンスでプレゼンテーションを行うステージでのプレゼンテーションを楽しんでいます。

learn more

Secure Code Warriorは、ソフトウェア開発ライフサイクル全体にわたってコードを保護し、サイバーセキュリティを最優先とする文化を築くお手伝いをします。アプリケーションセキュリティマネージャ、開発者、CISO、またはセキュリティ関係者のいずれであっても、安全でないコードに関連するリスクを軽減するお手伝いをします。

デモを予約
シェア:
linkedin brandsSocialx logo
著者
マティアス・マドゥ博士
Published Nov 03, 2022

マティアス・マドゥ博士は、セキュリティ専門家、研究者、CTO、セキュア・コード・ウォリアーの共同創設者です。Matias はゲント大学で静的分析ソリューションを中心にアプリケーションセキュリティの博士号を取得しました。その後、米国のFortifyに入社し、開発者が安全なコードを書くのを手伝わずに、コードの問題を検出するだけでは不十分であることに気づきました。これがきっかけで、開発者を支援し、セキュリティの負担を軽減し、顧客の期待を超える製品を開発するようになりました。Team Awesome の一員としてデスクにいないときは、RSA カンファレンス、BlackHat、DefCon などのカンファレンスでプレゼンテーションを行うステージでのプレゼンテーションを楽しんでいます。

Matiasは、15年以上のソフトウェアセキュリティの実務経験を持つ研究者および開発者です。フォーティファイ・ソフトウェアや自身の会社であるセンセイ・セキュリティなどの企業向けにソリューションを開発してきました。マティアスはキャリアを通じて、複数のアプリケーションセキュリティ研究プロジェクトを主導し、それが商用製品につながり、10件以上の特許を取得しています。デスクから離れているときには、マティアスは上級アプリケーション・セキュリティ・トレーニング・コースの講師を務め、RSA Conference、Black Hat、DefCon、BSIMM、OWASP AppSec、BruConなどのグローバルカンファレンスで定期的に講演を行っています。

マティアスはゲント大学でコンピューター工学の博士号を取得し、そこでアプリケーションの内部動作を隠すためのプログラムの難読化によるアプリケーションセキュリティを学びました。

シェア:
linkedin brandsSocialx logo

A version of this article appeared in DZone. It has been updated and syndicated here.

For what feels like an eternity at this point, we’ve discussed “shifting left” in the SDLC, taking into account security best practices from the start of software development. DevSecOps was a great leap forward, in no small part because of the emphasis on shared responsibility for security, and the power of a security-aware developer to thwart common vulnerabilities as they write code. 

We have also known - again, for eons - that the type of secure code training chosen to engage and upskill developers makes all the difference. Low-effort solutions motivated solely by regulatory compliance do not build up the bright security minds of the future, and most security awareness professionals have worked that out. Dynamic, contextually relevant learning is best, but it’s critical that the nuances within are understood. 

If we’re going to have a fighting chance against threat actors - and they always have a head start on an organization - developers need a holistic training environment, with layered learning that continually builds skills steeped in best practices.

Developer-driven defensive security measures are not an automatic win.

Our ethos revolves around the developer being central to a preventative security strategy, right there at the code level upwards. That’s a given, and security-skilled developers provide the easiest path to thwarting the types of common security bugs that are apparent in poor coding patterns (like Log4Shell, as one recent, devastating example).

However, the defensive techniques that we can engage to upskill developers do vary, even if they can rightly exist in the same training bucket. 

For example, imagine you were told how to bake a cake, using only directions based on what not to do. “Don’t overbake it”, and “don’t forget the eggs” leaves it open for interpretation, and a huge potential for mistakes that will have an end result fit for Nailed It!. The same is true for defensive security education; what not to do is a very limited part of the conversation, and offers no practical advice to truly act with a defensive mindset. You can tell developers, “don’t misconfigure that API”, but with no understanding of what constitutes correct and secure configuration, there is a lot of room for error.

Developers won’t have a positive impact on vulnerability reduction without a foundational understanding of how the vulnerabilities work, why they are dangerous, what patterns cause them, and what design or coding patterns fix them in a context that makes sense in their world. A scaffolded approach allows layers of knowledge to give a full picture of what it means to code securely, defend a codebase, and stand up as a security-aware developer. And yes, part of that layered learning should be dedicated to offense, and understanding the mindset of an attacker; this is critical to hone lateral thinking skills, which are invaluable in threat modeling and defensive strategy. 

Reinforcing poor coding patterns is a pitfall we can’t ignore.

An unfortunate reality with some methods of developer learning is that the “defensive” part - even when the training is structured with offensive techniques - can reinforce bad habits, even if they are technically validating code security. 

Production of high-quality code should be the baseline in all software development, but the definition of “quality” still appears to be up for debate. The reality is that insecure code cannot be viewed as quality code, even if it is otherwise functional and beautiful. The kicker is that secure code isn’t inherently high quality, either. In other words, poor coding patterns can fix a security problem, but in doing so, introduce another one, or potentially break the software entirely. 

Let’s take a look at an example of poor quality code in the form of a fix for broken authentication, as well as the most secure version for best practice:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace BadFixesAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AlertsController : ControllerBase
    {
        private DatabaseContext context = new DatabaseContext();
        [HttpGet(Name = "GetAlerts")]
        // Does not ensure that the user is authenticated 
        public IEnumerable<Alert> Get()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, but does not check any roles
        [Authorize()]
        public IEnumerable<Alert> GetBadFix()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, AND that they have the "Administrator" role
        [Authorize(Roles = "Administrator")]
        public IEnumerable<Alert> GetGoodFix()
        {
            return context.GetAlerts();
        }
    }
}

In the first snippet, there is no check to verify that the user is authenticated, which is about as unsafe as it gets. The second, while better in terms of it performing an authentication check, fails to investigate assigned roles and whether permissions are high enough for the information requested. The third checks both user authentication and that they are assigned the “Administrator” role. In an era where least privilege access control should be the norm in most instances, it is critical that roles are set up and checked to ensure that information is only accessible on a need-to-know basis. 

The highest priority for developers is to build features, and while security is not intentionally on the back burner, they don’t necessarily have the skills to avoid poor coding patterns that lead to security bugs, and the benchmark of a good engineer rarely includes secure coding prowess. We indirectly encourage those bad habits if the features are awesome enough, and it’s this mindset that has to change. The problem is, the way some learning pathways encourage hands-on code remediation also potentially reinforces code that is secure, but of substandard quality. By applying a binary “yes this is secure / no this is not secure” assessment, rather than looking deeper into whether it is truly the best approach to resolve the bug and maintain the integrity of the software, there are devils in the detail that go unnoticed. 

Without taking developers through the entire process for a complete view of secure coding, this approach perpetuates the same issues it’s trying to solve. Imagine if we all got our licenses based solely on our ability to drive a vehicle to a destination; a pass mark even though we ran red lights, drove through a hedge, and narrowly missed a pedestrian crossing the street to arrive there. We completed the goal, but the journey we took to get there matters most. 

Developers need to be enabled to care more about creating secure software.

The modern developer has to keep a lot of plates spinning, and it’s no surprise they find security training a bore, especially when it’s not implemented with their workday in mind, and takes them away from their deadlines and priorities. It’s also completely unfair to change their KPIs to include an emphasis on secure coding, when they don’t have the skills built up from regular, right-fit learning opportunities and supplementary tooling. However, the importance of secure software development cannot be overstated, and getting developers on-side with this is crucial. 

As a former developer, generally, we want to do a great job, and being seen as a cut above others in terms of quality output is very motivating. Incentivizing developers to engage with continuous security skill-building is a no-brainer, and they should be rewarded for recognizing the importance of code-level security. Security champion programs, bug bounties and hackathons can be great opportunities to build a positive security culture, and those who roll their sleeves up and get involved should get the loot.

リソースを表示
リソースを表示

レポートをダウンロードするには、以下のフォームに記入してください

当社の製品および/または関連するセキュアコーディングのトピックに関する情報を送信する許可をお願いします。当社は、お客様の個人情報を常に細心の注意を払って取り扱い、マーケティング目的で他社に販売することは決してありません。

送信
scw success icon
scw error icon
フォームを送信するには、「アナリティクス」クッキーを有効にしてください。設定が完了したら、再度無効にしても構いません。

A version of this article appeared in DZone. It has been updated and syndicated here.

For what feels like an eternity at this point, we’ve discussed “shifting left” in the SDLC, taking into account security best practices from the start of software development. DevSecOps was a great leap forward, in no small part because of the emphasis on shared responsibility for security, and the power of a security-aware developer to thwart common vulnerabilities as they write code. 

We have also known - again, for eons - that the type of secure code training chosen to engage and upskill developers makes all the difference. Low-effort solutions motivated solely by regulatory compliance do not build up the bright security minds of the future, and most security awareness professionals have worked that out. Dynamic, contextually relevant learning is best, but it’s critical that the nuances within are understood. 

If we’re going to have a fighting chance against threat actors - and they always have a head start on an organization - developers need a holistic training environment, with layered learning that continually builds skills steeped in best practices.

Developer-driven defensive security measures are not an automatic win.

Our ethos revolves around the developer being central to a preventative security strategy, right there at the code level upwards. That’s a given, and security-skilled developers provide the easiest path to thwarting the types of common security bugs that are apparent in poor coding patterns (like Log4Shell, as one recent, devastating example).

However, the defensive techniques that we can engage to upskill developers do vary, even if they can rightly exist in the same training bucket. 

For example, imagine you were told how to bake a cake, using only directions based on what not to do. “Don’t overbake it”, and “don’t forget the eggs” leaves it open for interpretation, and a huge potential for mistakes that will have an end result fit for Nailed It!. The same is true for defensive security education; what not to do is a very limited part of the conversation, and offers no practical advice to truly act with a defensive mindset. You can tell developers, “don’t misconfigure that API”, but with no understanding of what constitutes correct and secure configuration, there is a lot of room for error.

Developers won’t have a positive impact on vulnerability reduction without a foundational understanding of how the vulnerabilities work, why they are dangerous, what patterns cause them, and what design or coding patterns fix them in a context that makes sense in their world. A scaffolded approach allows layers of knowledge to give a full picture of what it means to code securely, defend a codebase, and stand up as a security-aware developer. And yes, part of that layered learning should be dedicated to offense, and understanding the mindset of an attacker; this is critical to hone lateral thinking skills, which are invaluable in threat modeling and defensive strategy. 

Reinforcing poor coding patterns is a pitfall we can’t ignore.

An unfortunate reality with some methods of developer learning is that the “defensive” part - even when the training is structured with offensive techniques - can reinforce bad habits, even if they are technically validating code security. 

Production of high-quality code should be the baseline in all software development, but the definition of “quality” still appears to be up for debate. The reality is that insecure code cannot be viewed as quality code, even if it is otherwise functional and beautiful. The kicker is that secure code isn’t inherently high quality, either. In other words, poor coding patterns can fix a security problem, but in doing so, introduce another one, or potentially break the software entirely. 

Let’s take a look at an example of poor quality code in the form of a fix for broken authentication, as well as the most secure version for best practice:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace BadFixesAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AlertsController : ControllerBase
    {
        private DatabaseContext context = new DatabaseContext();
        [HttpGet(Name = "GetAlerts")]
        // Does not ensure that the user is authenticated 
        public IEnumerable<Alert> Get()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, but does not check any roles
        [Authorize()]
        public IEnumerable<Alert> GetBadFix()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, AND that they have the "Administrator" role
        [Authorize(Roles = "Administrator")]
        public IEnumerable<Alert> GetGoodFix()
        {
            return context.GetAlerts();
        }
    }
}

In the first snippet, there is no check to verify that the user is authenticated, which is about as unsafe as it gets. The second, while better in terms of it performing an authentication check, fails to investigate assigned roles and whether permissions are high enough for the information requested. The third checks both user authentication and that they are assigned the “Administrator” role. In an era where least privilege access control should be the norm in most instances, it is critical that roles are set up and checked to ensure that information is only accessible on a need-to-know basis. 

The highest priority for developers is to build features, and while security is not intentionally on the back burner, they don’t necessarily have the skills to avoid poor coding patterns that lead to security bugs, and the benchmark of a good engineer rarely includes secure coding prowess. We indirectly encourage those bad habits if the features are awesome enough, and it’s this mindset that has to change. The problem is, the way some learning pathways encourage hands-on code remediation also potentially reinforces code that is secure, but of substandard quality. By applying a binary “yes this is secure / no this is not secure” assessment, rather than looking deeper into whether it is truly the best approach to resolve the bug and maintain the integrity of the software, there are devils in the detail that go unnoticed. 

Without taking developers through the entire process for a complete view of secure coding, this approach perpetuates the same issues it’s trying to solve. Imagine if we all got our licenses based solely on our ability to drive a vehicle to a destination; a pass mark even though we ran red lights, drove through a hedge, and narrowly missed a pedestrian crossing the street to arrive there. We completed the goal, but the journey we took to get there matters most. 

Developers need to be enabled to care more about creating secure software.

The modern developer has to keep a lot of plates spinning, and it’s no surprise they find security training a bore, especially when it’s not implemented with their workday in mind, and takes them away from their deadlines and priorities. It’s also completely unfair to change their KPIs to include an emphasis on secure coding, when they don’t have the skills built up from regular, right-fit learning opportunities and supplementary tooling. However, the importance of secure software development cannot be overstated, and getting developers on-side with this is crucial. 

As a former developer, generally, we want to do a great job, and being seen as a cut above others in terms of quality output is very motivating. Incentivizing developers to engage with continuous security skill-building is a no-brainer, and they should be rewarded for recognizing the importance of code-level security. Security champion programs, bug bounties and hackathons can be great opportunities to build a positive security culture, and those who roll their sleeves up and get involved should get the loot.

オンラインセミナーを見る
始めよう
learn more

以下のリンクをクリックして、このリソースのPDFをダウンロードしてください。

Secure Code Warriorは、ソフトウェア開発ライフサイクル全体にわたってコードを保護し、サイバーセキュリティを最優先とする文化を築くお手伝いをします。アプリケーションセキュリティマネージャ、開発者、CISO、またはセキュリティ関係者のいずれであっても、安全でないコードに関連するリスクを軽減するお手伝いをします。

レポートを表示デモを予約
PDF をダウンロード
リソースを表示
シェア:
linkedin brandsSocialx logo
もっと興味がありますか?

シェア:
linkedin brandsSocialx logo
著者
マティアス・マドゥ博士
Published Nov 03, 2022

マティアス・マドゥ博士は、セキュリティ専門家、研究者、CTO、セキュア・コード・ウォリアーの共同創設者です。Matias はゲント大学で静的分析ソリューションを中心にアプリケーションセキュリティの博士号を取得しました。その後、米国のFortifyに入社し、開発者が安全なコードを書くのを手伝わずに、コードの問題を検出するだけでは不十分であることに気づきました。これがきっかけで、開発者を支援し、セキュリティの負担を軽減し、顧客の期待を超える製品を開発するようになりました。Team Awesome の一員としてデスクにいないときは、RSA カンファレンス、BlackHat、DefCon などのカンファレンスでプレゼンテーションを行うステージでのプレゼンテーションを楽しんでいます。

Matiasは、15年以上のソフトウェアセキュリティの実務経験を持つ研究者および開発者です。フォーティファイ・ソフトウェアや自身の会社であるセンセイ・セキュリティなどの企業向けにソリューションを開発してきました。マティアスはキャリアを通じて、複数のアプリケーションセキュリティ研究プロジェクトを主導し、それが商用製品につながり、10件以上の特許を取得しています。デスクから離れているときには、マティアスは上級アプリケーション・セキュリティ・トレーニング・コースの講師を務め、RSA Conference、Black Hat、DefCon、BSIMM、OWASP AppSec、BruConなどのグローバルカンファレンスで定期的に講演を行っています。

マティアスはゲント大学でコンピューター工学の博士号を取得し、そこでアプリケーションの内部動作を隠すためのプログラムの難読化によるアプリケーションセキュリティを学びました。

シェア:
linkedin brandsSocialx logo

A version of this article appeared in DZone. It has been updated and syndicated here.

For what feels like an eternity at this point, we’ve discussed “shifting left” in the SDLC, taking into account security best practices from the start of software development. DevSecOps was a great leap forward, in no small part because of the emphasis on shared responsibility for security, and the power of a security-aware developer to thwart common vulnerabilities as they write code. 

We have also known - again, for eons - that the type of secure code training chosen to engage and upskill developers makes all the difference. Low-effort solutions motivated solely by regulatory compliance do not build up the bright security minds of the future, and most security awareness professionals have worked that out. Dynamic, contextually relevant learning is best, but it’s critical that the nuances within are understood. 

If we’re going to have a fighting chance against threat actors - and they always have a head start on an organization - developers need a holistic training environment, with layered learning that continually builds skills steeped in best practices.

Developer-driven defensive security measures are not an automatic win.

Our ethos revolves around the developer being central to a preventative security strategy, right there at the code level upwards. That’s a given, and security-skilled developers provide the easiest path to thwarting the types of common security bugs that are apparent in poor coding patterns (like Log4Shell, as one recent, devastating example).

However, the defensive techniques that we can engage to upskill developers do vary, even if they can rightly exist in the same training bucket. 

For example, imagine you were told how to bake a cake, using only directions based on what not to do. “Don’t overbake it”, and “don’t forget the eggs” leaves it open for interpretation, and a huge potential for mistakes that will have an end result fit for Nailed It!. The same is true for defensive security education; what not to do is a very limited part of the conversation, and offers no practical advice to truly act with a defensive mindset. You can tell developers, “don’t misconfigure that API”, but with no understanding of what constitutes correct and secure configuration, there is a lot of room for error.

Developers won’t have a positive impact on vulnerability reduction without a foundational understanding of how the vulnerabilities work, why they are dangerous, what patterns cause them, and what design or coding patterns fix them in a context that makes sense in their world. A scaffolded approach allows layers of knowledge to give a full picture of what it means to code securely, defend a codebase, and stand up as a security-aware developer. And yes, part of that layered learning should be dedicated to offense, and understanding the mindset of an attacker; this is critical to hone lateral thinking skills, which are invaluable in threat modeling and defensive strategy. 

Reinforcing poor coding patterns is a pitfall we can’t ignore.

An unfortunate reality with some methods of developer learning is that the “defensive” part - even when the training is structured with offensive techniques - can reinforce bad habits, even if they are technically validating code security. 

Production of high-quality code should be the baseline in all software development, but the definition of “quality” still appears to be up for debate. The reality is that insecure code cannot be viewed as quality code, even if it is otherwise functional and beautiful. The kicker is that secure code isn’t inherently high quality, either. In other words, poor coding patterns can fix a security problem, but in doing so, introduce another one, or potentially break the software entirely. 

Let’s take a look at an example of poor quality code in the form of a fix for broken authentication, as well as the most secure version for best practice:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace BadFixesAPI.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class AlertsController : ControllerBase
    {
        private DatabaseContext context = new DatabaseContext();
        [HttpGet(Name = "GetAlerts")]
        // Does not ensure that the user is authenticated 
        public IEnumerable<Alert> Get()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, but does not check any roles
        [Authorize()]
        public IEnumerable<Alert> GetBadFix()
        {
            return context.GetAlerts();
        }
        [HttpGet(Name = "GetAlerts")]
        // Ensures that the user is authenticated, AND that they have the "Administrator" role
        [Authorize(Roles = "Administrator")]
        public IEnumerable<Alert> GetGoodFix()
        {
            return context.GetAlerts();
        }
    }
}

In the first snippet, there is no check to verify that the user is authenticated, which is about as unsafe as it gets. The second, while better in terms of it performing an authentication check, fails to investigate assigned roles and whether permissions are high enough for the information requested. The third checks both user authentication and that they are assigned the “Administrator” role. In an era where least privilege access control should be the norm in most instances, it is critical that roles are set up and checked to ensure that information is only accessible on a need-to-know basis. 

The highest priority for developers is to build features, and while security is not intentionally on the back burner, they don’t necessarily have the skills to avoid poor coding patterns that lead to security bugs, and the benchmark of a good engineer rarely includes secure coding prowess. We indirectly encourage those bad habits if the features are awesome enough, and it’s this mindset that has to change. The problem is, the way some learning pathways encourage hands-on code remediation also potentially reinforces code that is secure, but of substandard quality. By applying a binary “yes this is secure / no this is not secure” assessment, rather than looking deeper into whether it is truly the best approach to resolve the bug and maintain the integrity of the software, there are devils in the detail that go unnoticed. 

Without taking developers through the entire process for a complete view of secure coding, this approach perpetuates the same issues it’s trying to solve. Imagine if we all got our licenses based solely on our ability to drive a vehicle to a destination; a pass mark even though we ran red lights, drove through a hedge, and narrowly missed a pedestrian crossing the street to arrive there. We completed the goal, but the journey we took to get there matters most. 

Developers need to be enabled to care more about creating secure software.

The modern developer has to keep a lot of plates spinning, and it’s no surprise they find security training a bore, especially when it’s not implemented with their workday in mind, and takes them away from their deadlines and priorities. It’s also completely unfair to change their KPIs to include an emphasis on secure coding, when they don’t have the skills built up from regular, right-fit learning opportunities and supplementary tooling. However, the importance of secure software development cannot be overstated, and getting developers on-side with this is crucial. 

As a former developer, generally, we want to do a great job, and being seen as a cut above others in terms of quality output is very motivating. Incentivizing developers to engage with continuous security skill-building is a no-brainer, and they should be rewarded for recognizing the importance of code-level security. Security champion programs, bug bounties and hackathons can be great opportunities to build a positive security culture, and those who roll their sleeves up and get involved should get the loot.

目次

PDF をダウンロード
リソースを表示
もっと興味がありますか?

マティアス・マドゥ博士は、セキュリティ専門家、研究者、CTO、セキュア・コード・ウォリアーの共同創設者です。Matias はゲント大学で静的分析ソリューションを中心にアプリケーションセキュリティの博士号を取得しました。その後、米国のFortifyに入社し、開発者が安全なコードを書くのを手伝わずに、コードの問題を検出するだけでは不十分であることに気づきました。これがきっかけで、開発者を支援し、セキュリティの負担を軽減し、顧客の期待を超える製品を開発するようになりました。Team Awesome の一員としてデスクにいないときは、RSA カンファレンス、BlackHat、DefCon などのカンファレンスでプレゼンテーションを行うステージでのプレゼンテーションを楽しんでいます。

learn more

Secure Code Warriorは、ソフトウェア開発ライフサイクル全体にわたってコードを保護し、サイバーセキュリティを最優先とする文化を築くお手伝いをします。アプリケーションセキュリティマネージャ、開発者、CISO、またはセキュリティ関係者のいずれであっても、安全でないコードに関連するリスクを軽減するお手伝いをします。

デモを予約[ダウンロード]
シェア:
linkedin brandsSocialx logo
リソースハブ

始めるためのリソース

その他の投稿
リソースハブ

始めるためのリソース

その他の投稿