https://crocs.fi.muni.cz @CRoCS_MUNI Łukasz Chmielewski chmiel@fi.muni.cz (based on the lecture by P. Svenda) (email me with your questions/feedback) Centre for Research on Cryptography and Security, Masaryk University PV286 - Secure coding principles and practices Static analysis of source code https://crocs.fi.muni.cz @CRoCS_MUNI This Lecture • Today we cover static analysis of source code • Some hard topics were covered too fast last time, so I will finish the lecture. • Split version (wrt. animations) of the lecture one is also uploaded. • Resources: – Recording should be available around Wednesday (but we will see). – An old version of the lecture (slightly shorter but well-recorded, from 2021): • https://is.muni.cz/auth/el/fi/jaro2022/PA193/um/video/PA193_03_StaticChecking_2022.video5 – Last year (worse quality): • https://is.muni.cz/auth/el/fi/jaro2023/PV286/um/vi/136775435/ – Materials: • https://is.muni.cz/auth/el/fi/jaro2024/PV286/um/ 2 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI PROBLEM Static analysis of source code 3 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI What is wrong with this code? 4 | PV286 - Static analysis of software network_receive(uchar* in_packet, short &in_packet_len); // TLV uchar* in = in_packet + 3; short length = make_short(in_packet + 1); uchar* out_packet = malloc(1 + 2 + length); uchar* out = out_packet + 3; memcpy(out, in, length); network_transmit(out_packet); https://crocs.fi.muni.cz @CRoCS_MUNI network_receive(uchar* in_packet, short &in_packet_len); // TLV uchar* in = in_packet + 3; short length = make_short(inpacket + 1); uchar* out_packet = malloc(1 + 2 + length); uchar* out = out_packet + 3; memcpy(out, in, length); network_transmit(out_packet); OpenSSL Heartbleed – “packet repeater” | PV286 - Static analysis of software Payload [length B]length [2B]Type [1B] unsigned char* in Payload (length B)length [2B]Type [1B] unsigned char* out Payload [length B] 5 https://crocs.fi.muni.cz @CRoCS_MUNI network_receive(uchar* in_packet, short &in_packet_len); // TLV uchar* in = in_packet + 3; uchar* out_packet = malloc(1 + 2 + length); uchar* out = out_packet + 3; memcpy(out, in, length); network_transmit(out_packet); Problem? | PV286 - Static analysis of software Payload [1B]Type [1B] unsigned char* in Payload (65535B)0xFFFF [2B]Type [1B] unsigned char* out … Heap memory … Payload [1B] Heap memory (keys, passwords…) 0x0001 [2B]0xFFFF [2B] Problem! https://heartbleed.com in_packet_len != length + 3 6 https://crocs.fi.muni.cz @CRoCS_MUNI How serious the bug was? • \ • http://news.netcraft.com/archives/2014/04/08/half-a-million-widely- trusted-websites-vulnerable-to-heartbleed-bug.html | PV286 - Static analysis of software 17% SSL web servers (OpenSSL 1.0.1) Twitter, GitHub, Yahoo, Tumblr, Steam, DropBox, DuckDuckGo… https://seznam.cz, https://fi.muni.cz … 7 https://crocs.fi.muni.cz @CRoCS_MUNI Defensive programming • Term coined by Kernighan and Plauger, 1981 – “writing the program so it can cope with small disasters” – talked about in introductory programming courses • Practice of coding with the mind-set that errors are inevitable, and something will always go wrong – prepare program for unexpected behavior – prepare program for easier bug diagnostics • Defensive programming targets mainly unintentional errors (not intentional attacks) – But increasingly given security connotation 8 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI “Security features != Secure features” • “Security features != Secure features” – Howard and LeBlanc, 2002 • “Writing security features, although important, is only 10% of the workload of creating secure code. The other 90% of the coding work is meant to ensure that all non-security codebase is secure.” – Sullivan, Balinsky, 2012 • “Reliable software does what it is supposed to do. Secure software does what it is supposed to do, and nothing else.” – Ivan Arce 9 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI STATIC AND DYNAMIC ANALYSIS 10 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI How to find bugs in code? • Manual analysis of code – code review, security code review • Manual “dynamic” testing – running program, observe expected output • Automated analysis of code without execution – static analysis (pattern matching, symbolic execution) • Automated analysis of code with execution – dynamic analysis (running code) • Automated testing of inputs (fuzzing) 11 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Approaches for automated code review • Formal methods (mathematical verification) – requires mathematical model and assertions – often requires modeling the system as finite state machine • verification of every state and transition • (outside the scope of this course, consider IA169) • Code metrics – help to identify potential hotspots (complex code) – e.g., Cyclomatic complexity (number of linearly indep. paths) • Review and inspection – tries to find suspicious patterns – automated version of human code review 12 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Microsoft’s Secure Development Lifecycle 13 | PV286 - Static analysis of software Taken from https://learn.microsoft.com/en-us/windows/security/threat-protection/msft-security-dev-lifecycle https://crocs.fi.muni.cz @CRoCS_MUNI Seven Touchpoints for Software Security (by Cigital) 14 | PV286 - Static analysis of software http://www.swsec.com/resources/touchpoints/ https://crocs.fi.muni.cz @CRoCS_MUNI Static vs. dynamic analysis • Static analysis – examine program’s code without executing it – can examine both source code and compiled code • source code is easier to understand (more metadata) – can be applied on unfinished code – manual code audit is kind of static analysis • Dynamic analysis – code is executed (compiled or interpreted) – input values are supplied, internal memory is examined… 15 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Example of output produced by analyzer 16 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Types of static analysis • Type checking – performed by compiler • Style checking – performed by automated tools • Program formal verification – annotations & verification of specified properties • Bug finding / hunting – between style checking and verification – more advanced static analysis – aim to infer real problem, not only pattern match • Security Review – previous possibilities with additional support for review 17 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Type checking • Type checking – performed by compiler – errors against language rules prevents compilation – warnings usually issued when problematic type manipulation occur – false positives possible (short=int=short), but don’t ignore! • Security problems due to wrong types – string format vulnerabilities – type overflow → buffer overflow – data loss (bigger type to smaller type) • More on type checking later with compiler warnings 19 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Style checking • Style checking – performed by automated tools – set of required code rules • Separate tools – MS style checker – Unix: lint tool (http://www.unix.com/man-page/FreeBSD/1/lint) – Checkstyle – PMD (http://pmd.sourceforge.net/) – Google C++ style checker: C++lint • https://github.com/darcyliu/google-styleguide/blob/master/cppguide.xml • https://github.com/google/styleguide/blob/gh-pages/cpplint/cpplint.py • Compiler warnings gcc –Wall gcc -Wextra 20 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Program formal verification • Prove particular program property – e.g., all dynamically allocated memory is always freed • Requires mathematical model and assertions • Often requires modeling the system as finite state machine – verification of every state and transition • (Outside the scope of this course, consider IA169) 21 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Bug finding • No language errors != secure program – finding bugs, even when language permits it • Examples: – Buffer overflow possible? – User input formatted into system() call? – Hard-coded secrets? • Tool must keep false positives low – do not report as a bug something which isn’t – there is simply too many potential problems • Tools: FindBugs, PREfast, Coverity... 22 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Security analysis and review • Usage of analysis tool to perform security review – Usually multiple tools are used during the process • Difference between compiler (e.g., gcc) and additional tool (e.g., cppcheck): – Compiler must never report error that isn’t (lang. standard) – Compiler must report low # of false warning (as heavily used by normal “uneducated” developers) – Tool executed for automatic reporting should have low # of false warnings (otherwise untrusted) – Tool executed during manual code review / pentest can have higher # of false warnings (as filtered by expert) 23 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI BEFORE DIGGING TO CONCRETE TOOLS… 24 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Static analysis limitations • Overall program architecture is not understood – sensitivity of program path – impact of errors on other parts • Application semantics is not understood – Is string returned to the user? Can string also contain passwords? • Social context is not understood – Who is using the system? High entropy keys encrypted under short guessable password? 25 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Problem of false positives/negatives • False positives – errors reported by a tool that are not real errors – too conservative analysis – inaccurate model used for analysis – annoying, more code needs to be checked, less readable output, developers tend to have as an excuse (for not fixing other problems reported by tool) • False negatives – real errors NOT reported by a tool – missed problems, e.g., missing rules for detection 26 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI False positives – limits of static analysis • When foo() is called, always writes outside buffer • Should you fix it even when foo() is not called? 27 | PV286 - Static analysis of software void foo() { char a[10]; a[20] = 0; } d:\StaticAnalysis>cppcheck example.cpp Checking example.cpp... [example.cpp:4]: (error) Array 'a[10]' accessed at index 20, which is out of bounds. https://crocs.fi.muni.cz @CRoCS_MUNI False positives – limits of static analysis • For x + y != 2 false positive • But analyzer cannot be sure about x & y values 28 | PV286 - Static analysis of software int x = 0; int y = 3; void foo() { char a[10]; if (x + y == 2) { a[20] = 0; } } d:\StaticAnalysis>cppcheck example.cpp Checking example.cpp... [example.cpp:7]: (error) Array 'a[10]' accessed at index 20, which is out of bounds. problematic assignment put inside condition https://crocs.fi.muni.cz @CRoCS_MUNI False positives – limits of static analysis • No problem detected – constants are evaluated in compile time and condition is now completely removed 29 | PV286 - Static analysis of software const int x = 0; const int y = 3; void foo() { char a[10]; if (x + y == 2) { a[20] = 0; } } const added (same as for #define) d:\StaticAnalysis>cppcheck --debug example.cpp Checking example.cpp... ##file example.cpp 1: 2: 3: 4: void foo ( ) 5: { 6: char a@3 [ 10 ] ; 7: 8: 9: 10: } d:\StaticAnalysis>cppcheck example.cpp Checking example.cpp... https://crocs.fi.muni.cz @CRoCS_MUNI False positives – limits of static analysis • Whole program is not executed and evaluated 30 | PV286 - Static analysis of software void foo2(int x, int y) { char a[10]; if (x + y == 2) { a[20] = 0; } } int main() { foo2(0, 3); return 0; } d:\StaticAnalysis>cppcheck --debug example.cpp Checking example.cpp... ##file example.cpp 1: void foo2 ( int x@1 , int y@2 ) { 2: char a@3 [ 10 ] ; 3: if ( x@1 + y@2 == 2 ) { 4: a@3 [ 20 ] = 0 ; 5: } 6: } 7: int main ( ) { 8: foo2 ( 0 , 3 ) ; 9: return 0 ; 10:} [example.cpp:4]: (error) Array 'a[10]' accessed at index 20, which is out of bounds. https://crocs.fi.muni.cz @CRoCS_MUNI Always design for testability • “Code that isn't tested doesn't work - this seems to be the safe assumption.” Kent Beck • Code written in a way that is easier to test – proper decomposition, unit tests, mock objects – source code annotations (with subsequent analysis) • References – https://en.wikipedia.org/wiki/Design_For_Test – http://www.agiledata.org/essays/tdd.html 31 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI BUILD-IN COMPILER ANALYSIS 32 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Example (MSVC flags) • warning C4018: '>=' : signed/unsigned mismatch 33 | PV286 - Static analysis of software #include using namespace std; int main(void) { int low_limit = 0; for (unsigned int i = 10; i >= low_limit; i--) { cout << "."; } return 0; } https://crocs.fi.muni.cz @CRoCS_MUNI Warnings – how compiler signals potential troubles • MSVC /W n – /W 0 disables all warnings – /W 1 & /W 2 basic warnings – /W 3 recommended for production purposes for legacy code (default) – /W 4 recommended for all new compilations – /Wall == /W4 + extra • GCC -Wall, -Wextra • Treat warnings as errors – GCC –Werror, MSVC /WX – forces you to fix all warnings, but slightly obscure nature of problem 34 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI warning C4018: '>=' : signed/unsigned mismatch • What will be the output of following code? – string "x > y" – but also compiler warning C4018 35 | PV286 - Static analysis of software #include using namespace std; int main(void) { int x = -100; unsigned int y = 100; if (x > y) { cout << "x > y"; } else { cout << "y >= x"; } return 0; } int → unsigned int -100 → 0xffffff9c https://crocs.fi.muni.cz @CRoCS_MUNI warning C4018: '>=' : signed/unsigned mismatch cont’d But why? Rules: • … The usual arithmetic conversions are rules that provide a mechanism to yield a common type when both operands of a binary operator are balanced to a common type or the second and third operands of the conditional operator ( ? : ) are balanced to a common type. • Conversions involve two operands of different types, and one or both operands may be converted. Many operators that accept arithmetic operands perform conversions using the usual arithmetic conversions. After integer promotions are performed on both operands, the following rules are applied to the promoted operands: 1. If both operands have the same type, no further conversion is needed. 2. If both operands are of the same integer type (signed or unsigned), the operand with the type of lesser integer conversion rank is converted to the type of the operand with greater rank. 3. If the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type is converted to the type of the operand with unsigned integer type. 4. … 36 | PV286 - Static analysis of software More here: https://wiki.sei.cmu.edu/confluence/display/c/INT02- C.+Understand+integer+conversion+rules#:~:text=The%20usual%20arithmetic%20conversions%20are,balanced%20to%20a%20common%20type. https://crocs.fi.muni.cz @CRoCS_MUNI Recommendations for MSVC CL • Compile with higher warnings /W4 • Control and fix especially integer-related warnings – warning C4018: '>=' : signed/unsigned mismatch • comparing signed and unsigned values, signed value must be converted to unsigned – Beware of also C4244, C4389! • possible loss of data because of truncation or signed & unsigned variables operation • If existing code is inspected, look for – #pragma warning (disable, Cxxxx) where xxxx is above – (developers may disable to suppress false warnings, missing all real ones) • Use compiler /RTC flag 37 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Recommendations for GCC • GCC –Wconversion – warn about potentially problematic conversions – fixed → floating point, signed → unsigned, ... • GCC –Wsign-compare – signed → unsigned producing incorrect result – warning: comparison between signed and unsigned integer expressions [- Wsign-compare] – http://stackoverflow.com/questions/16834588/wsign-compare-warning-in-g provides example of real problem • Runtime integer error checks using –ftrapv – trap function called when signed overflow in addition, subs, mult. occur – but significant performance penalty (continuous overflow checking)  38 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Compatibility issues? – This listing provides an example of a real problem. – g++: Something is wrong. Additional check went fine. – MSVC: Everything is fine. – Why? • unsigned long long (for g++) vs long long (for MSVC) • Compatibility reasons for MSVC? 39 | PV286 - Static analysis of software For more see http://stackoverflow.com/questions/16834588/wsign- compare-warning-in-g https://crocs.fi.muni.cz @CRoCS_MUNI GCC -ftrapv 40 | PV286 - Static analysis of software /* compile with gcc -ftrapv */ #include #include #include void signalHandler(int sig) { printf("Type overflow detected\n"); } int main() { signal(SIGABRT, &signalHandler); int largeInt = INT_MAX; int normalInt = 42; int overflowInt = largeInt + normalInt; /* should cause overflow */ /* if compiling with -ftrapv, we shouldn't get here */ return 0; } http://stackoverflow.com/questions/5005379/c-avoiding-overflows-when-working-with-big-numbers Try this at hom e! https://crocs.fi.muni.cz @CRoCS_MUNI STATIC ANALYSIS TOOLS 41 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Both free and commercial tools • Commercial tools – Coverity (now under Synopsys), Veracode (CA Technologies) – Microsoft PREfast (included in Visual Studio) – PC-Lint (Gimpel Software), Klocwork Insight (Perforce) • Free tools – CppCheck http://cppcheck.sourceforge.net/ – Clang static analyzer https://clang-analyzer.llvm.org/ – csmock (multiple static analyzers including clang, gcc, cppcheck, shellcheck, pylint, Bandit, Smatch, Coverity) – SpotBugs https://github.com/spotbugs/spotbugs (for Java programs, originally named FindBugs) – PMD https://pmd.github.io/ – ShellCheck https://www.shellcheck.net/ – Flawfinder https://www.dwheeler.com/flawfinder/, Splint http://www.splint.org/ – Rough Auditing Tool for Security (RATS) http://code.google.com/p/rough-auditing-tool-for-security/ – ... 43 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Cppcheck • A tool for static C/C++ code analysis – Open-source freeware, https://cppcheck.sourceforge.net/ – Online demo https://cppcheck.sourceforge.net/demo/ • Last version 2.13 (2023-12-23) • Used to find bugs in open-source projects (Linux kernel... ) • Command line & GUI version • Standalone version, plugin into IDEs, version control... – Code::Blocks, Codelite, Eclipse, Jenkins... – Tortoise SVN, Visual Studio … • Cross platform (Windows, Linux) – sudo apt-get install cppcheck 46 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Cppcheck – what is checked? • Bound checking for array overruns • Suspicious patterns for class • Exceptions safety • Memory leaks • Obsolete functions • sizeof() related problems • String format problems... • See full list: https://sourceforge.net/p/cppcheck/wiki/ListOfChecks/ 47 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Cppcheck – categories of problems • error – when bugs are found • warning - suggestions about defensive programming to prevent bugs • style - stylistic issues related to code cleanup (unused functions, redundant code, constness...) • performance - suggestions for making the code faster. • portability - portability warnings. 64-bit portability. code might work different on different compilers. etc. • information - Informational messages about checking problems 48 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Cppcheck | PV286 - Static analysis of software49 https://crocs.fi.muni.cz @CRoCS_MUNI cppcheck.exe --rule="pass[word]*" file.cpp • cppcheck.exe --rule="if \( p \) { free \( p \) ; }" file.cpp – will match only pointer with name ‘p’ 52 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Cppcheck – complex custom rules • Simple rules: regular expressions • Based on execution of user-supplied C++ code – possible more complex analysis 1. Use cppcheck.exe --debug file.cpp – outputs simplified code including Cppcheck’s internal variable unique ID 2. Write C++ code fragment performing analysis 3. Recompile Cppcheck with new rule and execute • Read more details – http://sourceforge.net/projects/cppcheck/files/Articles/ – http://www.cs.kent.edu/~rothstei/fall_14/sec_notes/writing-rules-3.pdf 53 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI PREfast - Microsoft static analysis tool 56 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI PREfast – example bufferOverflow 58 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI PREfast – what can be detected • Potential buffer overflows • Memory leaks, uninitialized variables • Excessive stack usage • Resources – release of locks... • Incorrect usage of selected functions • List of all code analysis warnings http://msdn.microsoft.com/en- us/library/a5b9aa09.aspx 59 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI PREfast settings • http://msdn.microsoft.com/en-us/library/ms182025.aspx | PV286 - Static analysis of software60 https://crocs.fi.muni.cz @CRoCS_MUNI| PV286 - Static analysis of software Flawfinder • Last version 2.0.19 (2021-08-29) • Download at http://www.dwheeler.com/flawfinder/ • Build by setup.py build • Install by setup.py install • /build/scripts***/flawfinder.py • flawfinder.py --context --html source_dir 62 https://crocs.fi.muni.cz @CRoCS_MUNI| PV286 - Static analysis of software Flawfinder - example 63 https://crocs.fi.muni.cz @CRoCS_MUNI Coverity (free for open-source) • Commercial static & dynamic analyzer • Free for C/C++ & Java open-source projects • https://scan.coverity.com/ • Process – Register at scan.coverity.com (GitHub account usage possible) – Download Coverity build tool for your platform • Quality and Security Advisor – Build your project with cov-build • cov-build --dir cov-int – Zip and submit build for analysis (works on binary, not source) • Can be integrated with Travis CI (continuous integration) – https://scan.coverity.com/travis_ci 64 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI65 | PV286 - Static analysis of software ++ https://crocs.fi.muni.cz @CRoCS_MUNI Code scanning with GitHub + Actions + Codacy 66 | PV286 - Static analysis of software + + https://crocs.fi.muni.cz @CRoCS_MUNI SpotBugs • Static analysis of Java programs (continuation of FindBugs) • Extended coverage for OWASP Top 10 and CWE • Current version 4.8.3 (2023-12-1) – https://github.com/spotbugs/spotbugs – Command-line, GUI, plugins into variety of tools – Support for custom rules • FindSecurityBugs 1.12.0. (2022-04-06) – Additional detection rules for SpotBugs – https://h3xstream.github.io/find-sec-bugs/bugs.htm 67 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI PMD Source Code Analyzer • https://pmd.github.io/ • Static analyser, mainly focused on Java, but other languages as well • Current version 7.0.0-rc4 (30-September-2023) • Additional features like copy-paste detector 69 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI How to reason about available tooling • Understand problems – Previous ones, likely to repeat, patterns…, read bug dissection reports • Understand principles of solution – What tool is used to detect problem, how was tool configured… • Find suitable tooling for your environment – Language, operating system… • Integrate, automate (CI) – Run tests and analysis tools frequently and automatically • Understand limitations (what is not detected) 70 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI How many false positives are too many? • “Because its analysis is sometimes imprecise, FindBugs can report false warnings, which are warnings that do not indicate real errors. In practice, the rate of false warnings reported by FindBugs is less than 50%.” FindBugs Fact Sheet 71 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI STATIC ANALYSIS IS NOT PANACEA 72 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI73 | PV286 - Static analysis of software // Note: GCC and MSVC uses different memory alignment // Try "12345678DevilEvecosia" as a password for gcc build // Try "1234567812345678Devil I am. Ha Ha" as a password for MSVC debug build void demoBufferOverflowData() { int unused_variable = 30; #define NORMAL_USER 'n' #define ADMIN_USER 'a' int userRights = NORMAL_USER; #define USER_INPUT_MAX_LENGTH 8 char userName[USER_INPUT_MAX_LENGTH]; char passwd[USER_INPUT_MAX_LENGTH]; // print some info about variables printf("%-20s: %p\n", "userName", userName); printf("%-20s: %p\n", "passwd", passwd); printf("%-20s: %p\n", "unused_variable", &unused_variable); printf("%-20s: %p\n", "userRights", &userRights); printf("\n"); // Get user name memset(userName, 1, USER_INPUT_MAX_LENGTH); memset(passwd, 2, USER_INPUT_MAX_LENGTH); printf("login as: "); fflush(stdout); gets(userName); // Get password printf("%s@vulnerable.machine.com: ", userName); fflush(stdout); gets(passwd); // Check user rights (set to NORMAL_USER and not changed in code) if (userRights == NORMAL_USER) { printf("\nWelcome, normal user '%s', your rights are limited.\n\n", userName); fflush(stdout); } if (userRights == ADMIN_USER) { printf("\nWelcome, all mighty admin user '%s'!\n", userName); fflush(stdout); } // How to FIX: //memset(userName, 0, USER_INPUT_MAX_LENGTH); //fgets(userName, USER_INPUT_MAX_LENGTH - 1, stdin); //memset(passwd, 0, USER_INPUT_MAX_LENGTH); //fgets(passwd, USER_INPUT_MAX_LENGTH - 1, stdin); } From 1. lecture Cppcheck --enable=all d:\StaticAnalysis>cppcheck --enable=all bufferOverflow.cpp Checking bufferOverflow.cpp... [bufferOverflow.cpp:26]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead. [bufferOverflow.cpp:31]: (style) Obsolete function 'gets' called. It is recommended to use the function 'fgets' instead. MSVC /W4 1> BufferOverflow.cpp 1>bufferoverflow.cpp(32): warning C4996: 'gets': This function or variable may be unsafe. Consider using gets_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h(261) : see declaration of 'gets' 1>bufferoverflow.cpp(37): warning C4996: 'gets': This function or variable may be unsafe. Consider using gets_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h(261) : see declaration of 'gets' 1>bufferoverflow.cpp(78): warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\string.h(191) : see declaration of 'strncpy' 1>bufferoverflow.cpp(81): warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. 1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\stdio.h(357) : see declaration of 'sprintf' MSVC /analyze (PREfast) 1> BufferOverflow.cpp bufferoverflow.cpp(32): warning : C6386: Buffer overrun while writing to 'userName': the writable size is '8' bytes, but '4294967295' bytes might be written. bufferoverflow.cpp(37): warning : C6386: Buffer overrun while writing to 'passwd': the writable size is '8' bytes, but '4294967295' bytes might be written. https://crocs.fi.muni.cz @CRoCS_MUNI Type overflow – example with dynalloc 74 | PV286 - Static analysis of software typedef struct _some_structure { float someData[1000]; } some_structure; void demoDataTypeOverflow(int totalItemsCount, some_structure* pItem, int itemPosition) { // See http://blogs.msdn.com/oldnewthing/archive/2004/01/29/64389.aspx some_structure* data_copy = NULL; int bytesToAllocation = totalItemsCount * sizeof(some_structure); printf("Bytes to allocation: %d\n", bytesToAllocation); data_copy = (some_structure*) malloc(bytesToAllocation); if (itemPosition >= 0 && itemPosition < totalItemsCount) { memcpy(&(data_copy[itemPosition]), pItem, sizeof(some_structure)); } else { printf("Out of bound assignment"); return; } free(data_copy); } From 1. lecture Cppcheck --enable=all d:\StaticAnalysis>cppcheck --enable=all typeOverflow.cpp Checking typeOverflow.cpp... [typeOverflow.cpp:17]: (error) Memory leak: data_copy MSVC /W4 1> typeOverflow.cpp nothing ☺ MSVC /analyze (PREfast) 1> typeOverflow.cpp bufferoverflow.cpp(13): warning : C6011: Dereferencing NULL pointer 'data_copy'. https://crocs.fi.muni.cz @CRoCS_MUNI What potential bug was not found? 75 | PV286 - Static analysis of software typedef struct _some_structure { float someData[1000]; } some_structure; void demoDataTypeOverflow(int totalItemsCount, some_structure* pItem, int itemPosition) { // See http://blogs.msdn.com/oldnewthing/archive/2004/01/29/64389.aspx some_structure* data_copy = NULL; int bytesToAllocation = totalItemsCount * sizeof(some_structure); printf("Bytes to allocation: %d\n", bytesToAllocation); data_copy = (some_structure*) malloc(bytesToAllocation); if (itemPosition >= 0 && itemPosition < totalItemsCount) { memcpy(&(data_copy[itemPosition]), pItem, sizeof(some_structure)); } else { printf("Out of bound assignment"); return; } free(data_copy); } From 1. lecture https://crocs.fi.muni.cz @CRoCS_MUNI Test suites – vulnerable code, benchmark • SAMATE Juliet Test Suite – huge test suite which contains at least 45000 C/C++ test cases – http://samate.nist.gov/SRD/testsuite.php • Static analysis test suite for C programs – https://ieeexplore.ieee.org/document/6032220 • Suitable for testing new methods, but NOT for comparison of existing commercial products – Public suites, products already optimized for it 76 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI SUMMARY 77 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI Summary • Static analysis is VERY important tool for writing secure software – Significant portion of analysis done already by compiler (errors, warnings) – Can run on unfinished code • Multiple tools exist (both free and commercial) – Predefined set of rules, custom rules can be also written – Differ in capability, supported languages, target audience, maturity… – Experiment with available tools and find the right for your scenario • Static analysis cannot find all problems – Problem of false positives/negatives – No substitution for extensive testing and defensive programming 78 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI (Mandatory) reading • Coverity open-source reports 2013/2014/2017/2020/2021 – Report of analysis for open-source projects – https://web.archive.org/web/20200320234505/https://www.synopsys.com/content/dam/synopsys/sig-assets/reports/SCAN-Report- 2017.pdf – https://ttpsc.com/wp3/wp-content/uploads/2020/10/2020-ossra-report.pdf – https://web.archive.org/web/20220315064102/https://www.synopsys.com/content/dam/synopsys/sig-assets/reports/rep-ossra- 2021.pdf – https://www.synopsys.com/content/dam/synopsys/sig-assets/reports/rep-ossra-2022.pdf – https://www.synopsys.com/content/dam/synopsys/sig-assets/reports/rep-ossra-2023.pdf • How open-source and closed-source compare w.r.t. number of defects? • How does open-source vs. closed-source address OWASP Top 10? • What are typical issues in C/C++ code? • How has the situation changed from 2017 onward? • Optional reading: https://www.cl.cam.ac.uk/~rja14/Papers/wcf.pdf 79 | PV286 - Static analysis of software https://crocs.fi.muni.cz @CRoCS_MUNI80 | PV286 - Static analysis of software Questions