4
Dealing with Code That Is Opaque to Sta7c Analysis Barton P. Miller †‡ , James A. Kupsch †‡ , Elisa Heymann †* , Vamshi Basupalli †‡ NIST Workshop on SoEware Measures and Metrics to Reduce Security VulnerabiliJes Gaithersburg, MD July 12, 2016 Computer Sciences Department, University of Wisconsin DHS SoEware Assurance Marketplace (SWAMP) * Autonomous University of Barcelona Recent Experience Reviewed high profile vulnerabiliJes Heartbleed (CVE-2014-010) glibc DNS resolver (CVE-2015-7547) Obtained vulnerable source code Ran staJc code analysis tools on each Tools failed to find the bugs Bug was opaque to the tools 2 Heartbleed At it’s heart (sorry), it’s just a buffer overflow… Failure of the OpenSSL library to validate the heartbeat packet length field (as compared to the size of the actual message). Heartbeat packets are contained within TLS packets. The heartbeat protocol is supposed to echo back the data sent in the request where the amount is given by the payload length. Since the length field is not checked, memcpy can read up to 64KB of memory. memcpy(bp, pl, payload); Length field. Supplied by an untrusted source. Source. Buffer with the heartbeat record. Improperly used. DesJnaJon. Allocated, used, and freed. OK. 3 TLS Heartbeat Protocol 4 type version len message type len payload padding Record buffer (allocated by malloc) ~16KB TLS record Heartbeat message Illegally large message len allows reading ~64KB Len is the number of bytes of the payload. Should be constrained by the total message length, header (3), and minimal padding (16) Len is the total message length in bytes Valid read 5 Heartbleed Added length check to remediate: if (1+2+payload+16 > s->s3->rrec.length) return 0 // silently discard And none of the current tools could fine the problem…why? 2556 unsigned char *p = &s->s3->rrec.data[0], *pl; 2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r; 2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer; 2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload); Here’s the offending code, slightly redacted 6

Heartbleed TLS Heartbeat Protocol...• Failure of the OpenSSL library to validate the heartbeat packet length field (as compared to the size of the actual message). • Heartbeat

  • Upload
    others

  • View
    37

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Heartbleed TLS Heartbeat Protocol...• Failure of the OpenSSL library to validate the heartbeat packet length field (as compared to the size of the actual message). • Heartbeat

DealingwithCodeThatIsOpaquetoSta7cAnalysis

BartonP.Miller†‡,JamesA.Kupsch†‡,ElisaHeymann†*,VamshiBasupalli†‡

NISTWorkshoponSoEwareMeasuresandMetricstoReduceSecurityVulnerabiliJes

Gaithersburg,MDJuly12,2016

†ComputerSciencesDepartment,UniversityofWisconsin‡DHSSoEwareAssuranceMarketplace(SWAMP)

*AutonomousUniversityofBarcelona

RecentExperience

•  ReviewedhighprofilevulnerabiliJes– Heartbleed(CVE-2014-010)– glibcDNSresolver(CVE-2015-7547)

•  Obtainedvulnerablesourcecode•  RanstaJccodeanalysistoolsoneach•  Toolsfailedtofindthebugs•  Bugwasopaquetothetools

2

HeartbleedAtit’sheart(sorry),it’sjustabufferoverflow…•  FailureoftheOpenSSLlibrarytovalidatetheheartbeatpacket

lengthfield(ascomparedtothesizeoftheactualmessage).•  HeartbeatpacketsarecontainedwithinTLSpackets.•  Theheartbeatprotocolissupposedtoechobackthedatasentinthe

requestwheretheamountisgivenbythepayloadlength.•  Sincethelengthfieldisnotchecked,memcpycanreadupto64KB

ofmemory.

memcpy(bp, pl, payload); Lengthfield.Suppliedbyanuntrustedsource.

Source.Bufferwiththeheartbeatrecord.Improperlyused.

DesJnaJon.Allocated,used,andfreed.OK.

3

TLSHeartbeatProtocol

4

type version len message

type len payload padding

Recordbuffer(allocatedbymalloc) ~16KB

TLSrecord

Heartbeatmessage

Illegallylargemessagelenallowsreading~64KB

Lenisthenumberofbytesofthepayload.Shouldbeconstrainedbythetotal

messagelength,header(3),andminimalpadding(16)

Lenisthetotalmessagelengthinbytes

Validread

5

Heartbleed

Addedlengthchecktoremediate:

if (1+2+payload+16 > s->s3->rrec.length) return 0 // silently discard

Andnoneofthecurrenttoolscouldfinetheproblem…why?

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

6

Page 2: Heartbleed TLS Heartbeat Protocol...• Failure of the OpenSSL library to validate the heartbeat packet length field (as compared to the size of the actual message). • Heartbeat

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

1.Findtheheartbeatpacketinthe(untrusted)userrequest

7

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

2.Extractuser-statedpayloadlengthoftheheartbeatpacket

8

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

3.plisanaliastotheheartbeatpayloadstartaddress.

9

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

4.LengthofTLSpacketthatcontainsheartbeatpacket

10

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

5.payloadlengthshouldbe≤TLSrecordlength-19

11

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

6.allocateenoughmemoryforechopacket(accordinguserpayload)

12

Page 3: Heartbleed TLS Heartbeat Protocol...• Failure of the OpenSSL library to validate the heartbeat packet length field (as compared to the size of the actual message). • Heartbeat

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

7.Copyheartbeatdatabasedonthelengththeyclaimed.Canalsograb

othernearbydata.

13

2556 unsigned char *p = &s->s3->rrec.data[0], *pl;

2563 n2s(p, payload); 2564 pl = p; 2565 2566 if (s->msg_callback) 2567 s->msg_callback(0, s->version, TLS1_RT_HEARTBEAT, 2568 &s->s3->rrec.data[0], s->s3->rrec.length, 2569 s, s->msg_callback_arg); 2570 2571 if (hbtype == TLS1_HB_REQUEST) { 2573 unsigned char *buffer, *bp; 2574 int r;

2580 buffer = OPENSSL_malloc(1+2+payload+padding); 2581 bp = buffer;

2584 *bp++ = TLS1_HB_RESPONSE; 2585 s2n(payload, bp); 2586 memcpy(bp, pl, payload);

Here’stheoffendingcode,slightlyredacted

Needtoactuallyknowthatpayloadlengthisnottrusted(tainted)data.

14

HeartbleedConceptually,thisisjustanexerciseintaintanalysis.WeneedtofollowingtheoriginalenclosingTLSpacketfromasocket,markingitastainted.Beforedisclosure:–  Notoolswetriedfoundthebug–  Notoolsweknowoffoundthebug

Coverity“fixed”theirtoolbynoJngthatextracJngtheintegerpayloadlengthfromanetworkbyte-orderusesabyte-swapinstrucJononaliqleendianmachine,andsuchaswapinstrucJonisrareenoughthatthisisasignthatthedatacomesfromthenetwork.

GrammaTechcoulddothetaintanalysisstarJngatsocketbuffers,butdidn’tdoitbecauseitwastooslowinpracJce.Whentheyturneditonfortherightsec.onofcode,itfoundtheproblem.

15

Difficul7esforSCATools

•  Legacylanguagesinherentfeatures– Rawmemoryaccess– Lackoftypesafety– Manualresourcemanagement– PointersandpointerarithmeJc

•  Codecomplexity–  IndirecJon– Largeprogramstate– Complexcontrolflow

16

WhySCAToolFailtoReport

•  NotdeducingaccuratesetofvaluesorproperJes(tainted,iniJalized,notnull,…)forvariables

•  NotdeducingcorrelaJonbetweenvariables•  UsingheurisJcstodeterminelikelyvaluesorproperJes

•  UncertainresultsnotreportedtoreducefalseposiJves

•  Confidencescoremaypointtoopaquecode,ifthereisareport

•  Fornon-reports,nowaytoconveyconfidence17

DynamicAnalysisTools

•  DynamicanalysisdidfindHeartbleed(singlefuzzedpacketcouldexposethevulnerability)

•  WedonotknowofanydynamicanalysistoolsthatfoundfoundglibcDNSvulnerability

•  DifficulJes:– GeneraJngcorrectbadinputsequence–  Inputdataspaceislarge–  Inputdatasequenceiscomplex

18

Page 4: Heartbleed TLS Heartbeat Protocol...• Failure of the OpenSSL library to validate the heartbeat packet length field (as compared to the size of the actual message). • Heartbeat

Goal:LessOpaqueCodeforSCA

•  Twoapproaches– Newcode:

•  Usemodernlanguagestopreventssomedefects–  D,Rust,modernC++

•  Use(more)analyzablesubsetoflanguage– MISRA–  CheckedC–  C++CoreGuidelines,GSL(guidelinesupportlibrary),andSCA

– Legacycode(andtoalesserextentnewcode):•  IdenJfypartsthatareopaque•  CurrentmetricsdonotidenJfyopaquecode

19

CommonMetrics

•  MetricTypes–  Simplecounts:

•  Lexicalelements:linesofcode,comments,…•  SyntacJcelements:parameters,types,operators,…•  PerfuncJon,file,orcodebase

–  Calculatedmetrics:•  Examples:CyclomaJc,Halsted•  PerfuncJon

–  RelaJonshipsbetweenfuncJons,classes,…•  Examples:Coupling,Cohesion,Connascence•  PerpairoffuncJons,classes,…

•  Inourexperience,thesemetricsdidnotcorrelatewithweaknessesorstaJcanalyzability

•  Focus:costtodevelop,maintain,test,enhance,…

20

Proposal:OpaquenessMetric

•  DeveloptoolsthatidenJfyprogramcomplexityintermsofopaquenesstoanalyzabilitybySCAtools–  SemanJccomplexityofcodethatreachesatool'sabilitytoreportduetoreachinglimitsoftheanalysisalgorithm's

•  Decidability•  ImplementaJon

–  Scoreregionsofthesourcecodewithanopaquenessscore– AlsoincluderaJonaleforpoorlyscoringregions

•  ProvideprescripJveadvicetotransformthecodetobelessopaquetoSCA(moreeasilyandcorrectlyanalyzable)

21

SCAToolProvidersPathForward

•  BestsemanJccodeanalysisisincommercialtools•  SCAtoolsalreadyhavemuchoftheinformaJon

– KnowwhereassumpJonsaremade– LocaJonofassumpJonsareaccurate– Shouldbeaccurateforusersofthetool

•  LimitaJons–  Inherentlynotintheirinterest,reporJnglimitaJonsisbadformarkeJng

– Specifictothetypesofproblemsthetoolfindsandthepowerofthetool

22

BroaderPathForward:DevelopTool

– StartwithexisJngopensourceanalysisframework•  ClangStaJcAnalyzer•  Gcc

– FundopensourcetoolbasedonframeworktoscorethesourcecodebasedonitsopaquenesstostaJcanalysis

– DevelopprescripJveguidanceontransformingsourcetomakecodelessopaque

23

Ques7ons

24