SDLC (SECURE DEVELOPMENT LIFE CYCLE)

The Microsoft Security Development Lifecycle (Microsoft SDL) is a software development process based on the spiral model, which has been proposed by Microsoft to help developers create applications or software while reducing security issues, resolving security vulnerabilities and even reducing development and maintenance costs. The process is divided into seven phases: training, requirements, design, implementation, verification, release and response.

The training phase is essential because practice is considered a requirement for the implementation of SDL. Concepts found in this phase include secure design, threat modeling, secure coding, security testing and practices regarding privacy. The requirements phase, on the other hand, includes the establishment of security and privacy that end-users require. Creating good quality gates/bug bars, and performing security and privacy risk assessments is part of the second phase.

TRAINING Core Security Training
REQUIREMENTS Establish Security Requirements Create Quality Gates / Bug Bars Perform security and Privacy Risk Assessments
 DESIGN Establish Design Requirement Perform Attack Surface Analysis / Reduction Use Threat Modeling
IMPLEMENTATION Use Approved Tools Deprecate Unsafe Functions Perform Static Analysis
VERIFICATION Perform Dynamic Analysis Perform Fuzz Testing Conduct Attack Surface Review
RELEASE Create an Incident Response Plan Conduct Final Security Review Certify Release and Archive
RESPONSE Execute Incident Response Plan

Table 1. SDLC

The third phase, design, considers security and privacy concerns, which helps decrease the risk of repercussions from the public. Attack surface analysis or reduction and the use of threat modelling will help apply an organised approach to dealing with threat scenarios during the design phase. Implementation of the design should employ approved tools and include the analysis of dynamic run-time performance to check an application’s functional limitations.

The release phase includes the final review of all the security activities that will help ensure the software’s security capacity. After the release phase comes the response phase to implement the incident response plan that was prepared during the release phase. This is crucial because it guards end-users from software vulnerabilities that can emerge and harm the software and/or the user.

Creating a secure Software Development Life Cycle (sSDLC) is starting to become one of the most comprehensive ways of ensuring safe web and mobile application development. But the three fundamentally different patterns implemented in today’s leading application development organisations are posing a huge challenge on the security front.

  • Waterfall (Sequential Design Process)
  • Agile/DevOps (Iterative Development)
  • Continuous Integration Continuous Development (CICD)

 The following tracks are integral to SDL implementation and each is explained in greater detail in focused sections further in this online artifact.

  • Developer Security Training – Ongoing courses provided to developers to improve their understanding of techniques for identifying and mitigating security vulnerabilities. Training focuses on topics including threat modelling, DAST testing, and coding techniques to prevent common defects such as SQL injection.
  • Design/Architecture Review – A collaborative effort between the ISV Customer Development/Engineering teams and their own product security group to assess and develop application or service design patterns that mitigate risk to the platform and associated applications and services.
  • Threat Modeling – A structured approach for analyzing the security of an application, with special consideration for boundaries between logical system components which often communicate across one or more networks.
  • Security User Stories / Security Requirements – A description of functional and non-functional attributes of a software product and its environment which must be in place to prevent security vulnerabilities. Security user stories/requirements are written in the style of a functional user story/requirement.
  • Automated Dynamic Application Security Testing (DAST) – A process of testing an application or software product in an operating state, implemented by a web application security scanner.
  • Automated Static Application Security Testing (SAST) – A process of testing an application or software product in a non-operating state, analyzing the source code for common security vulnerabilities.
  • Penetration Testing – Hands-on security testing of a runtime system. This sort of testing uncovers more complex security flaws that may not be caught by DAST or SAST tools.

Integration of security code review into the System Development Life Cycle (SDLC) can yield dramatic results to the overall quality of the code developed. Security code review is not a silver bullet, but is part of a healthy application development diet. Consider it as one of the layers in a defence-in-depth approach to application security. Security code review is also a cornerstone of the approach to developing secure software.

The idea of integrating a phase into your SLDC may sound daunting, yet another layer of complexity or an additional cost, but in the long term and in today’s cyber landscape it is cost effective, reputation building, and in the best interest of any business to do so.

Big organizations often have more than one of these being used simultaneously, as per the needs of the different development teams working on the project.

The testing phase requires the following steps:

  1. Fuzz testing
  2. Penetration testing
  3. Run-time verification
  4. Re-reviewing threat models
  5. Reevaluating the attack surface

Let’s look at each task in detail.

  • Fuzzing:

Fuzzing means creating malformed data and having the application under test consume the data to see how the application reacts. If the application fails unexpectedly, a bug has been found. The bug is a reliability bug and, possibly, also a security bug. Fuzzing is aimed at exercising code that analyzes data structures, loosely referred to as parsers.

There are three broad classes of parser:

  1. File format parsers Examples include code that manipulates graphic images (JPEG, BMP, WMF, TIFF) or document and executable files (DOC, PDF, ELF, PE, SWF).
  2. Network protocol parsers Examples include SMB, TCP/IP, NFS, SSL/TLS, RPC, and AppleTalk. You can also fuzz the order of network operations—for example, by performing a response before a request.
  3. APIs and miscellaneous parsers Examples include browser-pluggable protocol handlers (such as callto:).
  • Run-Time Verification

The final testing method is run-time verification testing using tools such as AppVerif to detect certain kinds of bugs in the code as it executes. AppVerif has been discussed earlier in the chapter as part of the fuzz-testing process. However, its usefulness extends beyond fuzz testing; it can also be used to find serious security flaws during normal testing or analysis. Hence, you should run the application regularly by using AppVerif, and you should review the log files to make sure there are no issues that require fixing. Microsoft Windows includes a tool called Driver Verifier (Verifier.exe) to perform similar tests on device drivers (Microsoft 2005).

  • Reviewing and Updating Threat Models

if Needed Threat models are invaluable documents to use during security testing. Sometimes functionality and implementation change after the design phase of a project. Threat models should be reviewed to ensure that they are still accurate and comprehensively cover all functionality delivered by the software. Threat models should be used to drive and inform security testing plans. Also, the riskiest portions of an application—usually those with the largest attack surface and the threats that are the highest risks—must be tested the most thoroughly.

  • Reevaluating the attack surface

 Software development teams should carefully reevaluate the attack surface of their product during the testing stage of the SDL. Measuring the attack surface will allow teams to understand which components have direct exposure to attack and, hence, have the highest risk of damage if a vulnerability occurs in those components. Assessing the attack surface will enable the team to focus testing and code-review efforts on high-risk areas and to take appropriate corrective actions. Such actions might include deciding not to ship a component until it is corrected, disabling a component by default, or modifying development practices to reduce the likelihood that vulnerabilities will be introduced by future modifications or new developments. After the attack surface has been reevaluated, the attack surface should be documented to reflect the rationale for the attack surface.

  • Static Application Security Testing (SAST):

SAST (Static Application Security Testing) is a white-box testing methodology which tests the application from the inside out by examining its source code for conditions that indicate a security vulnerability might be present. SAST solutions such as Source Code Analysis (SCA) have the flexibility needed to perform in all types of SDLC methodologies.

SAST solutions can be integrated directly into the development environment. This enables the developers to monitor their code constantly. Scrum Masters and Product Owners can also regulate security standards within their development teams and organizations. This leads to quick mitigation of vulnerabilities and enhanced code integrity.

#include “stdafx.h”
/* (O) STATIC VIOLATION     : 243 S : CERT-C++:2016 PRE06-CPP: Included file not protected with #define. :      6F/* OPEN FILE C:\Users\LDRA_new1\source\repos\vulneravilityserver\vulneravilityserver\stdafx.h */ */
#include “winsock.h”
/* (O) STATIC VIOLATION     : 243 S : CERT-C++:2016 PRE06-CPP: Included file not protected with #define. :     23F/* OPEN FILE C:\Program Files (x86)\Windows Kits\10\Include\10.0.15063.0\um\winsock.h */ */
#include “windows.h”//load windows socket
#pragma comment(lib, “wsock32.lib”)
/* (O) STATIC VIOLATION     : 69 S : CERT-C++:2016 MSC14-CPP: #pragma used. :     44F#pragma comment(lib, “wsock32.lib”) *///Define Return Messages
#define SS_ERROR 1
#define SS_OK 0
/*
void pr(char *str)
{
/* (O) STATIC VIOLATION     : 302 S : CERT-C++:2016 MSC04-CPP: Comment possibly contains code. :     50F{ */
char buf[500] = ” “;
/* (O) STATIC VIOLATION     : 302 S : CERT-C++:2016 MSC04-CPP: Comment possibly contains code. :     51Fchar buf[500] = ” “; */
strcpy(buf, str);
/* (O) STATIC VIOLATION     : 302 S : CERT-C++:2016 MSC04-CPP: Comment possibly contains code. :     52Fstrcpy(buf, str); */
}
/* (O) STATIC VIOLATION     : 302 S : CERT-C++:2016 MSC04-CPP: Comment possibly contains code. :     53F} */
*/

void sError(char * str)
{
printf(“Error %s”, str);
WSACleanup();
}

char str[5000];
/* (O) STATIC VIOLATION     : 604 S : CERT-C++:2016 DCL06-CPP: Use of numeric literal as array bound/subscript. : str: 5000 :     65F  str [ 5000 ] ; */

int  main(int argc, char * argv[])
{
WORD sockVersion;
/* (O) STATIC VIOLATION     : 560 S : CERT-C++:2016 DCL07-CPP: Scope of variable could be reduced.          : sockVersion :     73F      sockVersion ; */
WSADATA wsaData;
int rVal;
/* (O) STATIC VIOLATION     : 560 S : CERT-C++:2016 DCL07-CPP: Scope of variable could be reduced.          : rVal :     78F      rVal ; */
int bytesRecv;
/* (O) STATIC VIOLATION     : 560 S : CERT-C++:2016 DCL07-CPP: Scope of variable could be reduced.          : bytesRecv :     80F      bytesRecv ; */
u_short LocalPort = 1200;
SOCKET clientSocket;

SOCKADDR_IN sin;
SOCKET serverSocket;
/* (O) STATIC VIOLATION     : 560 S : CERT-C++:2016 DCL07-CPP: Scope of variable could be reduced.          : serverSocket :     91F      serverSocket ; */
HINSTANCE hDLL = LoadLibrary(_T(“C:\\ConsoleApplication4\\Debug\\dll.dll”));
char message[100] = “”;
/* (O) STATIC VIOLATION     : 604 S : CERT-C++:2016 DCL06-CPP: Use of numeric literal as array bound/subscript. : message: 100 :     98F      message [ 100 ] = “” ; */
/* (O) STATIC VIOLATION     : 397 S : CERT-C++:2016 CTR02-CPP: Array initialisation has insufficient items. : message[*]; given=1, expected=100 : 98 */

if (argv[1] == ‘\0’)
/* (O) STATIC VIOLATION     : 604 S : CERT-C++:2016 DCL06-CPP: Use of numeric literal as array bound/subscript. : argv: 1 :    101T      argv [ 1 ] == ‘\0’ */
{
//wsock32 initialized for usage
sockVersion = MAKEWORD(1, 1);
/* (O) STATIC VIOLATION     : 201 S : CERT-C++:2016 DCL06-CPP,EXP07-CPP,EXP09-CPP: Use of numeric literal in expression.        : 1 :    106T        MAKEWORD ( 1 , 1 ) ; */
/* (O) STATIC VIOLATION     : 201 S : CERT-C++:2016 DCL06-CPP,EXP07-CPP,EXP09-CPP: Use of numeric literal in expression.        : 1 : 106 */
WSAStartup(sockVersion, &wsaData);

//create server socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
/* (O) STATIC VIOLATION     : 201 S : CERT-C++:2016 DCL06-CPP,EXP07-CPP,EXP09-CPP: Use of numeric literal in expression.        : 0 :    110T        socket ( AF_INET , SOCK_STREAM , 0 ) ; */

if (serverSocket == INVALID_SOCKET)
{
sError(“Failed socket()”);
/* (M) STATIC VIOLATION     : 623 S : CERT-C++:2016 STR05-CPP,STR30-C: String assigned to non const object. :    117T            sError ( */
return SS_ERROR;
}

sin.sin_family = AF_INET;
sin.sin_port = htons(LocalPort);
sin.sin_addr.s_addr = htonl(INADDR_ANY);

//bind the socket
rVal = bind(serverSocket, (LPSOCKADDR)&sin, sizeof(sin));
/* (O) STATIC VIOLATION     : 120 S : CERT-C++:2016 INT13-CPP,INT16-CPP: Use of bit operator on signed type. : & used with int: ( LPSOCKADDR ) :    129T        bind ( serverSocket , ( LPSOCKADDR ) & sin , sizeof ( sin ) */
if (rVal == SOCKET_ERROR)
{
sError(“Failed bind()”);
/* (M) STATIC VIOLATION     : 623 S : CERT-C++:2016 STR05-CPP,STR30-C: String assigned to non const object. :    137T            sError ( */
WSACleanup();
return SS_ERROR;
}

//get socket to listen
rVal = listen(serverSocket, 10);
/* (O) STATIC VIOLATION     : 201 S : CERT-C++:2016 DCL06-CPP,EXP07-CPP,EXP09-CPP: Use of numeric literal in expression.        : 10 :    145T        listen ( serverSocket , 10 ) ; */
if (rVal == SOCKET_ERROR)
{
sError(“Failed listen()”);
/* (M) STATIC VIOLATION     : 623 S : CERT-C++:2016 STR05-CPP,STR30-C: String assigned to non const object. :    152T            sError ( */
WSACleanup();
return SS_ERROR;
}
else
{
printf(“Listening”);
}

//wait for a client to connect

clientSocket = accept(serverSocket, NULL, NULL);
if (clientSocket == INVALID_SOCKET)
{
sError(“Failed accept()”);
/* (M) STATIC VIOLATION     : 623 S : CERT-C++:2016 STR05-CPP,STR30-C: String assigned to non const object. :    171T            sError ( */
WSACleanup();
return SS_ERROR;
}
else { printf(“\nConnected”); }
bytesRecv = SOCKET_ERROR;

printf(“%d”, bytesRecv);

while (bytesRecv == SOCKET_ERROR)
{

//receive the data that is being sent by the client max limit to 5000 bytes.
bytesRecv = recv(clientSocket, str, 5000, 0);
/* (O) STATIC VIOLATION     : 201 S : CERT-C++:2016 DCL06-CPP,EXP07-CPP,EXP09-CPP: Use of numeric literal in expression.        : 5000 :    190T            recv ( clientSocket , str , 5000 , 0 ) ; */
/* (O) STATIC VIOLATION     : 201 S : CERT-C++:2016 DCL06-CPP,EXP07-CPP,EXP09-CPP: Use of numeric literal in expression.        : 0 : 190 */
printf(str);
/* (M) STATIC VIOLATION     : 486 S : CERT-C++:2016 FIO00-CPP,FIO47-C: Incorrect number of formats in output function. : 0 formats, 1 output :    191T            printf ( str ) ; */
strcpy(message, str);
/* (O) STATIC VIOLATION     : 382 S : CERT-C++:2016 ERR10-CPP,EXP12-CPP,FIO04-CPP: (void) missing for discarded return value. :    192T            strcpy ( message , str ) ; */
/* (M) STATIC VIOLATION     : 489 S : CERT-C++:2016 ARR30-C,ARR39-C,CTR50-CPP,STR31-C,STR50-CPP: Insufficient space for operation.            : required = 5000, available = 100 : 192 */

if (bytesRecv == 0 || bytesRecv == WSAECONNRESET)
/* (O) STATIC VIOLATION     : 201 S : CERT-C++:2016 DCL06-CPP,EXP07-CPP,EXP09-CPP: Use of numeric literal in expression.        : 0 :    195T              bytesRecv == 0 */
/* (O) STATIC VIOLATION     : 49 S : CERT-C++:2016 EXP00-CPP: Logical conjunctions need brackets. : 195 */
/* (O) STATIC VIOLATION     : 49 S : CERT-C++:2016 EXP00-CPP: Logical conjunctions need brackets. :    197T              bytesRecv == WSAECONNRESET */
{
printf(“\nConnection Closed.\n”);
break;
}
}

//Pass the data received to the function pr
//pr(Message);
/* (O) STATIC VIOLATION     : 302 S : CERT-C++:2016 MSC04-CPP: Comment possibly contains code. :    205F         //pr(Message); */

//close client socketr
closesocket(clientSocket);
//close server socket
closesocket(serverSocket);

WSACleanup();

return SS_OK;
}
else
{
printf(“argument :%s”, argv[1]);
/* (O) STATIC VIOLATION     : 604 S : CERT-C++:2016 DCL06-CPP: Use of numeric literal as array bound/subscript. : argv: 1 :    216T        printf ( “argument :%s” , argv [ 1 ] ) ; */
strcpy(message, argv[1]);
/* (O) STATIC VIOLATION     : 382 S : CERT-C++:2016 ERR10-CPP,EXP12-CPP,FIO04-CPP: (void) missing for discarded return value. :    217T        strcpy ( message , argv [ 1 ] ) ; */
/* (O) STATIC VIOLATION     : 604 S : CERT-C++:2016 DCL06-CPP: Use of numeric literal as array bound/subscript. : argv: 1 : 217 */
}
WSACleanup();

}
/* (M) STATIC VIOLATION     : 527 S : CERT-C++:2016 ERR51-CPP,ERR56-CPP: No master exception handler. :    220T  } */
/* (O) VIOLATION            :  5 Q : CERT-C++:2016 MSC15-CPP: File does not end with new line. : C:\Users\LDRA_new1\source\repos\vulneravilityserver\vulneravilityserver\vulneravilityserver.cpp :    221F  */

  • Dynamic Application Security Testing (DAST):

Black Box testing is ideally suited for Waterfall environments, but falls short in the more progressive development methods due to its inherited limitations. DAST tools can’t be used on source code or uncomplied application codes, delaying the security deployment till the latter stages of development. DAST (Dynamic Application Security Testing) is a black-box security testing methodology in which an application is tested from the outside in by examining an application in its running state and trying to attack it just like an attacker would.

  • Interactive Application Security Testing (IAST):

IAST is designed to address the shortcomings of SAST and DAST by combining elements of both approaches. IAST places an agent within an application and performs all its analysis in the app in real-time and anywhere in the development process ­­ IDE, continuous integrated environment, QA or even in production. Because both SAST and DAST are older technologies, there are those who argue they lack what it takes to secure modern web and mobile apps. For example, SAST has a difficult time dealing with libraries and frameworks found in modern apps. That’s because static tools only see code they can follow. What’s more, libraries and third ­party components often cause static tools to choke, producing “lost sources” and “lost sinks” messages. The same is true for frameworks. Run a static tool on an API, web service or REST endpoint, and it won’t find anything wrong in them because it can’t understand the framework.

Riha Maheshwari

Riha Maheshwari

Riha Maheshwari is a college student who is passionate working towards the field of Cyber Security and will be graduating with her MCA-ISMS in June of 2018. She has done her CEH certification from EC-Council and CISE certification from Innobuzz Knowledge Solution. Riha has spent many hours exploring ways to penetrate windows machine, android devices, servers so she could get better idea of what she could be looking forward to in her field of Cyber Security. She also found vulnerabilities in her college’s website which she reported. Riha enjoys spending her time writing about the practical experiments that she performed. She also spends a great deal of time learning Guitar and watching TV Series.

Email: rihazz13@gmail.com
LinkedIn: https://www.linkedin.com/in/riha-maheshwari/

Leave a comment