Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this...

13
Constraint-based Testing for Buffer Overflows Loui Al Sardy () , Francesca Saglietti () , Tong Tang, Heiko Sonnenberg University of Erlangen-Nuremberg Software Engineering (Informatik 11) Martensstr. 3, 91058 Erlangen, Germany {loui.alsardy, francesca.saglietti, tong.tang, heiko.sonnenberg}@fau.de Abstract. This article proposes two heuristic approaches targeted at the optimized generation of test cases capable of triggering buffer overflows resp. underflows. Both testing techniques are based on guiding conditions statically derived by Integer Constraint Analysis. First experimental evaluations confirmed the superiority of local optimization algorithms over global ones. Keywords: software vulnerability, buffer overflow, integer constraint analysis, testing technique, global optimization, local optimization. 1 Introduction It is well-known that the safe behaviour of critical cyber-physical systems may be severely jeopardized by the intentional activation of system vulnerabilities, typically software weaknesses known to the attacker and exploited during operation to trigger unwarranted effects. A major part of such attacks relies on redirection techniques [1, 2, 15] aimed at shifting the instruction pointer to an illegal memory cell such as to enforce the execution of an illegal piece of hidden code. For example, the attack described in [12] and further analysed in [1] assumes a machine code allowing for overlapping instructions such that shifting the instruction pointer to a cell inside an instruction may cause the execution of malicious code hidden within a correct binary code. A still widespread redirection technique consists of provoking buffer overflows resp. underflows by writing data intended for a buffer into memory space lying outside of this buffer [9]. Although buffer overflows resp. underflows may be constructively avoided during development, e.g. by forbidding the use of widespread programming languages [18], for a considerable part of already operating cyber-physical systems their occurrence could not be systematically excluded a priori so far. The relevance of these vulnerabilities is confirmed by a recent report [5] ranking stack-based resp. heap- based buffer overflows among the four most frequent software vulnerabilities. In addition, successful attacks on power plants based on buffer overflows were recently reported [19]. Original source of publication: Computer Safety, Reliability, and Security - SAFECOMP 2018 Workshops B. Gallina et al. (Eds.) Lecture Notes in Computer Science, Volume 11094 © Springer International Publishing Switzerland 2018 The final publication is available at link.springer.com

Transcript of Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this...

Page 1: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

Constraint-based Testing for Buffer Overflows

Loui Al Sardy (✉), Francesca Saglietti (✉), Tong Tang, Heiko Sonnenberg

University of Erlangen-Nuremberg

Software Engineering (Informatik 11)

Martensstr. 3, 91058 Erlangen, Germany {loui.alsardy, francesca.saglietti, tong.tang,

heiko.sonnenberg}@fau.de

Abstract. This article proposes two heuristic approaches targeted at the

optimized generation of test cases capable of triggering buffer overflows resp.

underflows. Both testing techniques are based on guiding conditions statically

derived by Integer Constraint Analysis. First experimental evaluations

confirmed the superiority of local optimization algorithms over global ones.

Keywords: software vulnerability, buffer overflow, integer constraint analysis,

testing technique, global optimization, local optimization.

1 Introduction

It is well-known that the safe behaviour of critical cyber-physical systems may be

severely jeopardized by the intentional activation of system vulnerabilities, typically

software weaknesses known to the attacker and exploited during operation to trigger

unwarranted effects. A major part of such attacks relies on redirection techniques [1,

2, 15] aimed at shifting the instruction pointer to an illegal memory cell such as to

enforce the execution of an illegal piece of hidden code. For example, the attack

described in [12] and further analysed in [1] assumes a machine code allowing for

overlapping instructions such that shifting the instruction pointer to a cell inside an

instruction may cause the execution of malicious code hidden within a correct binary

code. A still widespread redirection technique consists of provoking buffer overflows

resp. underflows by writing data intended for a buffer into memory space lying

outside of this buffer [9].

Although buffer overflows resp. underflows may be constructively avoided during

development, e.g. by forbidding the use of widespread programming languages [18],

for a considerable part of already operating cyber-physical systems their occurrence

could not be systematically excluded a priori so far. The relevance of these

vulnerabilities is confirmed by a recent report [5] ranking stack-based resp. heap-

based buffer overflows among the four most frequent software vulnerabilities. In

addition, successful attacks on power plants based on buffer overflows were recently

reported [19].

Original source of publication:Computer Safety, Reliability, and Security - SAFECOMP 2018 WorkshopsB. Gallina et al. (Eds.)Lecture Notes in Computer Science, Volume 11094© Springer International Publishing Switzerland 2018The final publication is available at link.springer.com

Page 2: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

On the whole, this confirms the need for systematic approaches capable of detecting

the potential of buffer overflows resp. underflows before allowing critical systems to

become operational. The design, development and evaluation of such approaches

build the goal of the present article which is structured as follows: after an overview

on existing related approaches and their limitations (section 2), classical theoretical

foundations of Integer Constraint Analysis (ICA) are introduced in section 3. The

outcome of such a preliminary static analysis is then exploited to provide systematic

guidance during a successive dynamic analysis. Heuristic test techniques are

subsequently designed in section 4 to take advantage of the insight gained by ICA

such as to optimize the chances to trigger potential overflows or underflow before

operation. Section 5 presents a comparative evaluation of two testing approaches on

the base of two different examples before the final section 6 summarizes the work

proposed and draws some conclusions.

2 Related Work

State-of-the-art approaches address the problem of detecting exploitable buffer

overflows in different ways.

Static analyses examine source code listings without requiring code execution. They

range from mere search of source code for buffer accesses in order to derive a list of

potentially vulnerable instructions to more sophisticated code analyses in order to

derive numerical constraints for variable values proven to be necessary and / or

sufficient for buffer overflow occurrence. Evidently, for well-known theoretical

reasons involving undecidability of program behaviour, in general static analysis

alone cannot grant the detection or the exclusion of buffer overflows resp.

underflows. In other words, in general the outcome of static analysis is doomed to

incompleteness. Among these static approaches are [3, 6, 7, 13, 14, 23].

Dynamic analyses, on the other hand, aim at detecting the occurrence of buffer

overflows by executing the program during testing. Hereby, the main challenge

concerns the intelligent generation of test data capable of triggering – if possible – a

buffer overflow during execution. For this purpose, test data generation may be based

on assumptions restricting the search to program patterns reported or experienced to

be affected by illegal buffering effects, e.g. [10, 21].

Hybrid approaches combining static and dynamic analyses [4, 17] let dynamic

analysis take advantage of the insight preliminarily gained during static analysis. This

insight may allow for a justified restriction of the testing scope by targeting only those

buffer accesses preliminarily identified as potentially vulnerable while ignoring those

already statically verified as being secure with respect to overflow or underflow.

The approach proposed in this article belongs to the latter class of hybrid approaches.

Its novelty lies in the implementation of intelligent testing strategies targeted at the

fulfilment of predicates derived from existing integer constraint analysis techniques.

In more detail, the intention of the suggested testing strategy is to make full use of the

static analysis outcome to guide the search for suitable test cases capable of fulfilling

conditions guaranteeing the triggering of a buffer overflow.

Page 3: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

3 Integer Constraint Analysis (ICA)

In the following, classical Integer Constraint Analysis is illustrated based on [8, 20].

As already mentioned, it aims at extracting information as complete as possible, in

particular necessary and sufficient constraints, such as to provide a valuable guide in

the search for exploitable vulnerabilities.

3.1 Potential Overflow Statements

Initially, only those program instructions allowing for a modification of buffer

variables are selected for further consideration, as only their execution may trigger a

buffer over- or underflow. Any such instruction is denoted as Potential Overflow

Statement (in the following abbreviated by POS). More precisely, a POS denoted by

<instr(k), V>, is a pair consisting of an instruction instr(k) located at code line k with

writing access to buffer variables building a variable set V, where the access may be

of different type:

type 1: data may be directly written into buffer elements, e.g. by the assignment

list[i-1] = 1 the integer 1 is written into the i-th element of a buffer variable list;

type 2: alternatively, instr(k) may invoke a function parameterized by a buffer

and writing data into this buffer, e.g. the function call strcpy(des, src) reading

data from string src and writing them into the array referenced by des.

For any POS = <instr(k),V>, a subprogram results from the original program by

slicing, i.e. by deleting all instructions which do not influence the variables from V

[25]. By doing so, the search for test cases triggering buffer over- resp. underflows

can be reduced to the program slice derived.

3.2 Necessary and Sufficient Constraint Excluding Buffer Overflows

In the following, let C(NBO) (abbreviating “Constraint for No Buffer Overflow”)

represents a necessary and sufficient condition for buffer accesses at POS causing

neither overflows nor underflows.

In other words, fulfillment of C(NBO) upon execution of the POS instruction allows

to exclude buffer overflows and underflows, while, on the contrary, violation of

C(NBO) guarantees the occurrence of at least one overflow or underflow.

Depending on the type of writing data into buffer elements (s. above), the

determination of C(NBO) may vary:

type 1 (direct writing): absence of buffer overflowing or underflowing requires

the index of overwritten elements to lie in the range between 0 and the allocated

buffer memory size (in the following denoted as buf.aSize); for example, if the

POS instruction assigns a new value to the element buf[i] of a buffer buf, then

C(NBO) reads 0 i < buf.aSize.

type 2 (indirect writing by call): if buffer variable(s) are parameter(s) of a

function, constraint C(NBO) can be analogously derived, in particular for the C

Page 4: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

standard functions modifying buffer variables, as listed in [7, 11]; for example,

for a function call gets(str) reading a string input from stdin and writing this

string into the buffer str, the C(NBO) reads str.aSize stdin.len.

3.3 Necessary Condition C(POS) upon Reaching a POS

In the following, let C(POS) (abbreviating “Constraint for reaching POS”) represent a

predicate on program variables and buffer parameters always fulfilled upon reaching

POS, but before executing the given POS instruction. The determination of a C(POS)

requires an accurate analysis of the control and data flow of the corresponding

program slice. More precisely, analysis of data flow along all control flow paths

reaching the POS results in path-specific constraints whose logical disjunction may be

taken to provide C(POS).

3.4 Logical Relations between C(POS) and C(NBO)

Since C(POS) holds upon reaching POS and C(NBO) is sufficient and necessary for

the exclusion of buffer overflows and underflows, the ICA focuses on examining

whether C(POS) may imply C(NBO) or not (s. Fig. 1), where the outcome can be

classified as follows:

if C(POS) implies C(NBO), absence of buffer overflows at POS is proven;

if C(POS) implies ¬C(NBO), a buffer over- or underflow is guaranteed to occur

whenever POS is reached;

if C(POS) neither implies C(NBO) nor ¬C(NBO), by executing the POS

instruction a buffer over- or underflow might occur. In order to provoke it, test

cases must be generated such as to reach POS and to violate C(NBO).

These three possibilities are summarized in Table 1.

Fig. 1. Overview of integer constraint analysis

Program slice execution

reaching POS

Execution of POS instruction

does not cause any over-/underflow

C(POS) C(NBO) ?

Page 5: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

Table 1. Possible outcomes of Integer Constraint Analysis

Implications Buffer over-/underflow

occurrence

Test

need

Test goal

I1: C(POS) C(NBO) never no need ---

I2: C(POS) C(NBO) whenever

POS executed

need reach POS

neither I1 nor I2 if POS executed such that

C(NBO) violated

need reach POS such that

C(NBO)

4 ICA-Guided Dynamic Analysis

4.1 Test Case Generation based on Guided Evolution

The test goal is to generate test cases triggering a buffer over- or underflow at a given

POS, i.e. test cases which upon reaching POS fulfill ¬C(NBO). Evidently, upon

reaching POS, C(POS) is fulfilled. In order to enforce coincidentally the validity of

¬C(NBO), the conjunction C(POS) ¬C(NBO), can provide guidance for the

optimization of variables contained both in C(POS) and in ¬C(NBO).

The heuristic test generation technique considered in the following is based on genetic

algorithms [16]: in general, it starts with an initial random population which

successively evolves into new generations by making use of the classical genetic

operators selection, mutation and crossover. The evolution is controlled via fitness

evaluation. The process is repeated until one of the following termination conditions

is fulfilled:

a given maximal number of iterations is reached;

an individual with a given maximum fitness is generated.

4.2 Heuristic Test Case Generation based on Global Optimization

The first approach developed is based on global optimization. In this case, the fitness

of a test case should reflect the degree of fulfilment of the target constraint C(POS)

¬C(NBO) upon reaching POS. Therefore, for individuals reaching POS the fitness is

maximized by minimizing the degree of violation of the same guidance condition

which can be captured by a distance metric P as proposed in [22]. Such a metric

depends on the type of the underlying predicate P, as summarized in Table 2 for some

typical predicates, where K denotes a positive constant intended to reflect a

penalization in case of a predicate violation.

Page 6: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

Table 2. Atomic predicates and distance metrics as proposed in [22]

atomic predicate P distance metric P

integer a, b

a = b if abs(a – b) = 0 then 0 else abs(a – b) + K

a ≠ b if abs(a – b) ≠ 0 then 0 else K

a < b if a – b < 0 then 0 else (a – b) + K

a ≤ b if a – b ≤ 0 then 0 else (a – b) + K

a > b if b a < 0 then 0 else (b – a) + K

a ≥ b if b – a ≤ 0 then 0 else (b – a) + K

boolean A, B

A if A = TRUE then 0 else K

A B min (A, B)

A B (A + B)

A conjunction AA k

n

1k of predicates Ak (1 k n) has the distance metric

n

1iA Ai

(1)

If the POS instruction is executed more than one time, upon reaching POS the

variables may have different values depending on the number of times POS has

already been reached in advance. As buffer overflowing resp. underflowing can be

critical as soon as it happens, fulfilling the guidance conditions once at any time

during execution is enough to trigger a buffer overflow. Therefore, in such cases the

distance metric is taken as the minimum distance metric evaluated during execution.

Formally, let t denote a test case that reaches POS m times during the whole

execution and let A(t, j) denote the distance metric w.r.t. a guidance condition A

upon reaching POS for the j-th time. The metric capturing the distance of test case t is

then evaluated by:

)j,t(min)t( A

mj1A

(2)

Page 7: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

4.3 Heuristic Test Case Generation based on Local Optimization

Although the aforementioned approach based on global optimization revealed as

successful in some cases (s. section 5 for an example), it failed to detect a buffer

overflow for a particularly complex program. Therefore, this approach was modified

by refining the original overall test goal “reach POS while fulfilling the guidance

condition” via two different sub-goals addressing control flow and predicate

fulfilment separately. To do so, the original program was first transformed into a new

program by insertion of an additional branch, as shown in Fig. 2. As both outgoing

arcs of the new branching node lead to identical copies of the POS instruction, both

programs are behaviourally equivalent.

By this semantics-preserving program transformation the original optimization

problem is transformed into a classical test coverage problem demanding to cover all

nodes, in particular the POS-node highlighted by a thick border on the right of Fig. 2.

Fig. 2. Original program slice (left); transformed program slice (right).

According to previous work carried out in local optimization [16, 24], the following

distance metric can be used to reflect the quality of test progress:

distance = sub-path distance + branch distance (3)

where

the sub-path distance captures the number of branching nodes separating the

closest node already reached from the target node annotated by C(NBO); by its

nature, this metric is a natural number;

the branch distance captures the degree of violation of the branching condition

C(NBO) in terms of the distance metric for the predicate ¬C(NBO); in order to

enforce the dominance of the sub-path distance over the branch distance, this

metric can be normalized to enforce a range between 0 and 1.

Start

End

C(NBO)

POS-

instruction

false

true POS-

instruction

Start

End

POS-

instruction Transformation

Page 8: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

With respect to the examples analyzed, this locally optimized refinement revealed to

be superior both in performance and in detection capability, as reported in the next

section.

5 Examples

Both testing approaches proposed in section 4 were evaluated by means of different

examples. The applicability of ICA is first demonstrated via Example 1 (s. Appendix,

Fig. 3) which contains two global variables, namely an integer array buffer for 100

integers and an integer variable nE indicating the number of elements already inserted

in the buffer; function is the program under test, invoked by the integer array values

and its size valuesNumber. All instructions of function lie within a for loop such that

any of them might influence any of the buffer variables. Therefore, slicing the

program does not help reducing the original program.

Five alternative Potential Overflow Statements were identified; only two of them

require further testing. In the following, due to its nesting depth and complexity, the

analysis presented focuses on the POS located at code line 10 for the purpose of

demonstrating the application of ICA to testing. The corresponding instruction reads:

buffer[i+1] = buffer[i]. Evidently, regular buffer access at this code position requires

to fulfil the inequalities:

0 i+1 < buffer.aSize (4)

Conversely, a buffer overflow would occur if and only if i+1 buffer.aSize;

therefore, ¬C(NBO) reads:

99 i (5)

On the other hand, a buffer underflow would assume i+1 < 0 which is evidently

untrue. For this reason, in the following only the option of a potential buffer overflow

will be further investigated taking into account that upon reaching POS variable i is

constrained to assume a value over 98. Based on this insight, the control and data flow

of the program under test, i.e. function is analysed for further variable values on

which i depends: among them is evidently nE which provides the initial value of i

before i is successively decremented within the internal loop (s. LOC #8); in

particular this implies:

i nE (6)

On the other hand, nE is subject to changes within the external loop (s. LOC #4);

more precisely, during each iteration of the external loop nE may remain unchanged

or increase by a maximum of 1 (s. LOC #13 and LOC #23); in particular, upon

reaching POS in the course of the (v+1)-th iteration, nE can have incremented at most

by v, i.e.

Page 9: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

nE v (7)

On the whole, the guidance provided by the overall constraint C(POS) ¬C(NBO)

reads:

99 i nE v (8)

As the inequality chain i nE v always holds by semantic analysis for the

aforementioned reasons, the guiding constraint A was captured by the conjunction of

three atomic conditions with distance metric:

)j,t(min)t( A

mj1A

(9)

where

)j,t()j,t()j,t()j,t( i99nE99v99A (10)

and j denotes the case where execution of t by function has just reached POS for the j-

th time. Each test cases t = (values, valuesNumber) consists of an integer array values

and an integer valuesNumber providing its size which in this case is 300 in view of

the call in main.

In order to evaluate the fitness for any test case t, function is instrumented to return

the minimum distance value (t) of t upon reaching POS. For example, when

executing a test case with values = {150, 151, 149, 152, 148, 153, 147, 154, 146} and

valuesNumber = 9, POS is accessed 3 times. Table 3 shows the variable values and

the distance metric each time POS is reached. Evidently, the minimum distance for

this test case is 283.

Table 3. Variable values and distances upon reaching POS

i-th access

of POS

instruction

Variable values

v nE i

distance

1st 6 2 2 287

2nd 8 3 3 283

3rd 8 3 2 284

Similar procedures can be applied to the other four POS alternatives. On the whole,

only those located at lines 10 and 20 require further testing (s. Table 4).

Page 10: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

Both global and local algorithms were subsequently applied 10 times each with

different initial random populations of size 70, where distance metrics were evaluated

with a penalty constant K = 1; the minimum distance over all individuals within a

population was taken as the fitness value of that population.

All 20 test optimizations were successful in detecting an exploitable buffer overflow.

Performance was evaluated by comparing the number of iterations required to trigger

the vulnerability; this allows to exclude the influence of the underlying computer

hardware as would be the case if running time was measured instead. Local

optimization hereby performed considerably better, the slowest local optimization

requiring only ca. 53% of the effort needed by the fastest global one.

Table 4. Results of Integer Constraint Analysis for POS alternatives of Example 1

POS = <instr(k), {buffer}>

C(NBO)

testing required? k instr(k)

10 buffer[i+1] = buffer[i] i+1 < buffer.aSize Yes

15 buffer[1] = value 1 < buffer.aSize No

16 buffer[0] = 0 0 < buffer.aSize No

19 buffer[0] = 1 0 < buffer.aSize No

20 buffer[nE] = value nE < buffer.aSize Yes

The superiority of local optimization was revealed also in the context of a further,

more complex example involving higher execution times and including non-

monotonic jumps in buffer accesses. For this Example 2, all global approach variants

failed to exploit the existing buffer overflow within the affordable time, while the

vulnerability was easily detected by all locally optimizing instances, the slowest one

demanding only an effort of ca. 12% of the maximum affordable.

A comparison of the experimental results obtained is shown in Table 5.

Table 5. Comparison of global and local optimization techniques for both examples

Examples

Global Optimization

(10 executions)

Local Optimization

(10 executions)

fastest slowest fastest slowest

Example 1 55869 196389 3846 29781

Example 2 no buffer overflow detection after

10000 iterations

199 1197

Page 11: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

6 Conclusions and Future Work

This article presented two testing approaches targeted at the triggering of potential

buffer overflows resp. underflows before deployment. Both approaches combine

existing static analyses based on Integer Constraints with heuristics guided by the

constraints derived.

The applicability was illustrated by an example; a comparative evaluation of this and

of a further example showed that the local optimization techniques were superior both

in detection capability and in performance.

In view of the promising results it is planned to apply similar guided test concepts to

further classes of software vulnerability.

Acknowledgement. The authors gratefully acknowledge that a major part of the work

presented was supported by the German Federal Ministry for Economic Affairs and

Energy (BMWi), project no. 1501502C (SMARTEST). They also thank Marc

Spisländer for his support in providing the code examples considered in this article.

Appendix

Fig. 3. Code of Example 1

1: int buffer[100];

int nE = 0;

3: void function(int *values, int valuesNumber) {

for (int v = 0; v < valuesNumber; v++) {

5: int value = values[v];

if (value < buffer[1]) {

7: if (buffer[0] == 1) {

for (int i = nE; i > 1; i--) {

9: if (buffer[i+1] > buffer[i]){

buffer[i+1] = buffer[i];

11: }

}

13: nE++;

}

15: buffer[1] = value;

buffer[0] = 0;

17: } else {

if (buffer[nE] < value)

19: buffer[0] = 1;

buffer[nE] = value;

21: } if (nE == 0)

23: nE++;

}

25: } int main(void) {

27: for (int i = 0; i < 100; i++)

buffer[i] = (i+1)∗1000;

29: int values[300];

...

31: function(values, 300); return EXIT_SUCCESS; 33: }

Page 12: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

References

1. Al Sardy, L., Tang, T., Spisländer, M., Saglietti, F.: Analysis of Potential Code Vulnerabilities Involving Overlapping Instructions. In: Computer Safety, Reliability, and Security (SAFECOMP Workshops). LNCS, vol. 10489, pp. 103-113. Springer, (2017). doi: 10.1007/978-3-319-66284-8_10

2. Andriesse, D., Bos, H.: Instruction-Level Steganography for Covert Trigger-Based Malware. In: Detection of Intrusions and Malware, and Vulnerability Assessment (DIMVA 2014). LNCS, vol. 8550, pp. 41-50. Springer (2014). doi:

10.1007/978-3-319-08509-8_3

3. Chess, B., McGraw, G.: Static Analysis for Security. In: IEEE Security & Privacy, vol. 2, pp. 76–79. IEEE (2004). doi: 10.1109/MSP.2004.111

4. Del Grosso, C., Antoniol, G., Merlo, E., Galinier, P.: Detecting Buffer Overflow via Automatic Test Input Data Generation. In: Computers & Operations Research, vol. 35, pp. 3125–3143. Elsevier (2008)

5. Department of Homeland Security (U.S.): Annual Vulnerability Coordination Report. National Cybersecurity and Communications Integration Center / Industrial Control Systems Cyber Emergency Response Team (2016)

6. Dor, N., Rodeh, M., Sagiv, M.: Cleanness Checking of String Manipulations in C Programs via Integer Analysis. In: Static Analysis (SAS). LNCS, vol. 2126, pp. 194–212. Springer (2001). doi: 10.1007/3-540-47764-0_12

7. Dor, N., Rodeh, M., Sagiv, M.: CSSV: Towards a Realistic Tool for Statically Detecting all Buffer Overflows. In: Programming Language Design and Implementation (PLDI), vol. 38, pp. 155-167. ACM (2003). doi: 10.1145/780822.781149

8. Evans, D., Larochelle, D.: Improving Security Using Extensible Lightweight Static Analysis. In: IEEE Software, vol. 19, pp. 42–51, (2002). doi: 10.1109/52.976940

9. Foster, J.C., Osipov, V., Bhalla, N., Heinen, N.: Buffer Overflow Attacks: Detect, Exploit, Prevent. Syngress, Rockland (2005)

10. Haugh, E., Bishop, M.: Testing C Programs for Buffer Overflow Vulnerabilities. In: Network and Distributed System Security Symposium (2003)

11. International Organization for Standardization (ISO): Programming Languages ─ C, International Standard ISO / IEC 9899:TC3 (E). ISO (2007). http://www.open-std.org

12. Jämthagen, C., Lantz, P., Hell, M.: Exploiting Trust in Deterministic Builds. In: Computer Safety, Reliability, and Security (SAFECOMP 2016). LNCS, vol. 9922, pp. 238–249. Springer (2016). doi:10.1007/978-3-319-45477-1_19

13. Larochelle, D., Evans D.: Statically Detecting Likely Buffer Overflow Vulnerabilities. In: 10th conference on USENIX Security Symposium, vol. 10, pp. 177-190. ACM (2001)

14. Le. W., Soffa, M.L.: Marple: a Demand-driven Path-sensitive Buffer Overflow Detector. In: 16th ACM SIGSOFT Int. Sym. on Foundations of Software Engineering. ACM (2008). doi: 10.1145/1453101.1453137

15. Lhee, K., Chapin, S.: Buffer Overflow and Format String Overflow Vulnerabilities. Journal of Software: Practice and Experience, vol. 33, pp. 423-460 Wiley (2003). doi: 10.1002/spe.515

16. Oster N., Saglietti, F.: Automatic Test Data Generation by Multi-objective Optimisation. In: Computer Safety, Reliability, and Security (SAFECOMP). LNCS, vol. 4166, pp.426-

438. Springer (2006). doi: 10.1007/11875567_32

17. Padmanabhuni, B.M., Tan, H.B.K.: Auditing Buffer Overflow Vulnerabilities using Hybrid Static–Dynamic Analysis. In: 38th Annual Int. Computers, Software and Applications Conf., vol. 10, pp. 54–61, 2014. doi: 10.1109/COMPSAC.2014.62

Page 13: Constraint-based Testing for Buffer Overflows · buffer overflow during execution. For this purpose, test data generation may be based on assumptions restricting the search to program

18. Saglietti, F., Meitner, M., v. Wardenburg, L., Richthammer, V.: Analysis of Informed

Attacks and Appropriate Countermeasures for Cyber-Physical Systems. In: SAFECOMP

Workshops 2016. LNCS, vol. 9923, pp. 222-233 Springer (2016). doi: 10.1007/978-3-

319-45480-1_18

19. Schneider Electric Software Security Response Center: InduSoft Web Studio and InTouch

Machine Edition – Remote Code Execution Vulnerability, Security Bulletin

LFSEC00000125 (2018)

20. Shahriar, H., Zulkernine, M.: Classification of Static Analysis-Based Buffer Overflow

Detectors. In: 4th International Conference on Secure Software Integration and Reliability

Improvement Companion (SSIRI-C). IEEE (2010). doi: 10.1109/SSIRI-C.2010.28

21. Shahriar, H., Zulkernine, M.: Mutation-based Testing of Buffer Overflow Vulnerabilities.

In: Computer Software and Applications (COMPSAC’08), pp. 979–984. IEEE (2008)

22. Tracey, N., Clark, J., Mander, K., McDermid, J.: An Automated Framework for Structural

Test-data Generation. In: 13th IEEE Int. Conf. on Automated Software Engineering, pp.

285–288. IEEE (1998). doi: 10.1109/ASE.1998.732680

23. Wagner, D., Foster, J.S., Brewer, E.A., Aiken, A.: A First Step Towards Automated

Detection of Buffer Overrun Vulnerabilities. In: Network and Distributed System Security

Symposium (NDSS), pp. 3–17. (2000)

24. Wegener, J., Baresel, A., Sthamer, H.: Evolutionary Test Environment for Automatic

Structural Testing. In: Information and Software Technology, vol. 43, pp. 841-854.

Elsevier (2001). doi: 10.1016/S0950-5849(01)00190-2

25. Weiser, M.: Program Slicing. In: 5th International Conference on Software Engineering.

pp. 439–449, IEEE Press (1981)