start	end	text
820	3820	Hi everyone, welcome to our talk, Hacking the Supply Chain,
3820	8320	about the Ripple 20 vulnerabilities that haunt hundreds of millions of critical devices.
8440	10720	A little bit about us, JSOF.
10720	12880	So JSOF is a software security consultancy,
12880	16220	we do a lot of security research, penetration testing,
16220	19140	we help companies with their secure development processes,
19140	20640	as well as some training.
21220	24200	My name is Shlomi Overman, I'm a co-founder at JSOF.
24200	26580	Together with me today, we'll be speaking Moshe Kohl,
26780	28160	a security researcher at JSOF,
28160	30580	and the finder of the Ripple 20 vulnerabilities.
30720	33940	And Ariel Schon, a security researcher at JSOF,
33940	36580	that was also heavily involved in the research.
37100	39760	We'll be talking about Ripple 20 in general today,
39760	42640	explaining what it is and how it evolved.
42640	45480	Then we'll be going into detail about one of the vulnerabilities,
45480	48260	the vulnerability that we find the most interesting
48260	50600	out of the Ripple 20 vulnerabilities.
50740	52920	Short spoiler here, it's one CVE,
52920	55120	but we'll actually be talking about several vulnerabilities
55120	58420	hiding behind this one CVE.
58560	60820	And then we'll be going in-depth into exploitation
60820	63060	on a specific vulnerable device,
63060	65580	with a specific configuration.
66220	68220	So, what is Ripple 20?
68220	70980	Ripple 20 is a series of 19 zero-day vulnerabilities
70980	74340	in a TCPIP stack called TREC-TCPIP.
74440	76740	We say 19 zero-day vulnerabilities,
76740	78780	but it sort of depends how you count.
78780	81820	There are quite a few more discrete bugs
81820	84060	in these 19 vulnerabilities,
84060	86420	and two of the vulnerabilities were reported anonymously
86420	88720	at the same time as we reported,
88720	90320	so it depends how you count.
90320	92820	These vulnerabilities were amplified by the supply chain
92820	94680	to affect hundreds of millions of devices
94680	97200	in all kinds of verticals.
97280	99980	Medical, a lot of critical devices,
99980	103280	industrial control, enterprise, and a bunch of others.
103280	105500	We'll explain how this came to happen.
106180	108460	Out of the Ripple 20 vulnerabilities,
108460	112280	four of the vulnerabilities are critical remote code execution vulnerabilities,
112280	116220	and in addition, eight vulnerabilities, or eight CVEs,
116220	118460	are medium to high-severity vulnerabilities,
118460	122520	some of which could also potentially lead to remote code execution,
122520	127500	pending further research, if anyone wants to go into that.
128560	131760	The vulnerabilities affect hundreds of different sub-medium devices.
131760	134340	From brand names, you all know.
134820	138940	We currently have over 100 different vendors
138940	141360	with suspected affected devices,
141360	144680	meaning different vendors are looking into these devices
144680	147100	to see whether they're affected or not.
147100	150620	These include Fortune 500, Global 500 companies,
150620	152980	such as those you see on the slide,
152980	156300	as well as one-person specialty shops,
156300	161220	and quite a large range and diverse range of vendors.
162240	165860	You can see the Ripple 20 vulnerabilities in medical devices
165860	170340	when you go to the hospital, in your home, in your company,
170340	173540	when you turn on the light, when you turn on the water.
174060	176740	Transportation devices are affected by Ripple 20.
176740	181320	Pretty much everywhere you go, you'll see IoT devices in general,
181320	185060	as well as specifically devices affected by the Ripple 20 vulnerabilities.
186160	188760	Our current assumption, based on what we know,
188760	191800	the suspected devices, as well as the confirmed devices,
191800	196120	meaning the different vendors confirmed the devices are affected,
196120	199340	we assume every medium to large organization in the US
199340	201880	has at least one vulnerable device.
201880	205640	Of course, some networks have many more devices,
205640	208260	such as data centers or utility companies,
208260	213760	but even any other kind of organization might have an affected printer,
214260	217760	a hospital might have affected IV pumps, etc.
218060	219700	How did this come to happen?
219700	221520	So this happened because of the supply chain
222140	224000	and security in the supply chain.
224000	225980	Not in the sense that somebody put a backdoor
225980	229580	into a component built in another country,
229580	232740	but in the sense that a piece of code, a library,
232740	235660	had a vulnerability, like any software has a vulnerability.
235720	238020	And this piece of code was sold to an operating system.
238020	241360	It was then sold onwards to a system on module,
241360	243600	and the system on module embedded the operating system
243600	246200	with our vulnerable library.
246260	250180	And from this point, nobody even knows they're using this piece of code,
250180	252360	this piece of TREC TCP IP stack.
252360	254920	This system on module is then used in different devices,
254920	259520	such as IV pumps, and the whole chain becomes vulnerable.
259520	262600	Just imagine what happens if one of the companies along the way
262600	265240	goes bankrupt or ceases operation,
265240	268580	just how difficult it is to track down the vulnerable devices
268580	272820	and how complex it is to fix and patch.
273120	276380	And so you have a network of devices,
276520	277820	a network of different vendors,
277820	280500	each selling to each other to create final products,
280500	284400	built like Lego from different pieces and different parts.
284400	288700	And then when one part at the very beginning of the supply chain,
288700	291900	strategically located at the beginning of the supply chain,
291900	293680	gets affected by a vulnerability,
293680	296500	different devices along the supply chain get affected.
296680	298500	This is what happened with Ripple20,
298500	300760	and this is why it affects so many devices.
302080	306940	So, why did we choose to do this research on TREC TCP IP,
306940	309840	and why do we think it's important for the security industry as a whole?
310120	313620	Well, for starters, this aspect of the supply chain,
313620	316800	of vulnerabilities existing in the supply chain,
316800	319520	not as backdoors, but just as regular vulnerabilities,
319520	324740	and traveling, rippling from device to device in this ripple effect,
324740	326660	this is something that is mostly unexplored.
326660	329780	It's been discussed, we've seen some examples,
329780	332460	but Ripple20 is really a prime example of what happens
333260	336280	when a vulnerability is located this deep in the supply chain
336280	338280	and exists for so many years.
338280	341580	So, there's one vulnerability, multiple products,
341580	346640	huge impact, and this is quite the beginning of a discussion
346640	350140	of what should be done to fix these types of vulnerabilities.
350920	355480	Another interesting thing is, for us, it was, of course, a good attack surface,
355480	360000	and going forward, there's the potential for zombie vulnerabilities.
360060	364240	Zombie vulnerabilities, these type of, it's complicated vulnerabilities,
364240	366720	we don't know if they're one days, we don't know if they're zero days,
366720	369160	quite a few of the vendors we believe won't be patching.
370840	374700	Either they don't know they have TREC, the devices can't be patched,
374700	378500	companies went bankrupt, and so you have these walking dead vulnerabilities
378500	382360	that are supposed to be patched, they've already been reported,
382360	384580	but they still exist in the wild.
384580	387800	So, this is quite an interesting phenomenon, both for us,
387800	389300	as well as for the industry.
390260	396120	TREC specifically was chosen because it's an extremely successful TCP IP stack,
396120	401400	used widely in the embedded device world, in the IoT world,
401400	403020	and it's been available for over 20 years.
403020	405920	So, during those 20 years, or 20-something years,
405920	409420	it spread throughout the supply chain from device to device,
409420	414620	from vendor to vendor, and reached its current scope, current impact.
414740	418820	One thing that's very interesting about TREC TCP IP,
418820	421440	made our life quite challenging,
421440	424100	and made the lives of network operators challenging,
424100	426880	is that the TREC stack is extremely configurable.
427140	429760	So, every instance of TREC is slightly different.
429760	433280	It depends when the vendor stopped support of TREC,
433280	434660	what version of TREC they're using.
434660	436760	It also depends how they compiled TREC.
438040	442260	Specific configuration options, specific features they bought or did not buy,
442260	445280	how they're using, what memory manager they're using, etc.
445540	449940	And so, every version of the TREC stack looks different,
449940	451800	and the vulnerabilities change.
451800	454640	So, some vulnerabilities affect different devices differently,
454640	457020	some devices are affected by some of the vulnerabilities,
457020	461940	some devices are affected by more extreme versions of the vulnerabilities,
461940	464660	while the others are affected by lesser versions.
464660	468160	So, very complex, very complex to understand.
468180	472240	And, of course, at the very, very beginning of a long supply chain.
472240	474740	So, TREC doesn't incorporate any other components,
474740	478700	which is not something that we can say about any of the other devices affected,
478700	481640	which all incorporate different components, including TREC.
482640	485860	The research itself, because TREC is so configurable,
485860	488260	we had to take a few data points.
488260	489980	We used six different devices.
489980	494720	We spent a different amount of time on each device
494720	497400	in order to understand what we're dealing with,
497400	499820	in order to find variations of the vulnerabilities,
500400	504500	in order to understand whether certain vendors made changes of their own
504500	506980	to the stack or to the compilation.
506980	510940	And so we used six different devices with differing architectures
511700	515460	in order to understand what's going on,
515460	519520	where this stack is, how this stack is used.
519520	522260	The research took approximately nine months,
522260	525100	with changing, differing intensities throughout this time.
525100	529260	Started September 19th, we reported the vulnerabilities June 20th,
529580	531740	June 2020, of course.
532360	536320	And then we discovered some things after the fact as well.
536320	541060	For example, while trying to bypass our company firewall
541060	544420	in order to see if the vulnerabilities route over the Internet,
544420	550100	we discovered that because TREC TCPIP stack allows for encapsulation,
550100	553200	you could also encapsulate these vulnerabilities
553200	555280	attempting to bypass firewalls.
555280	558100	So we were able to bypass our firewalls,
558100	563220	and at least some of these vulnerabilities will route over the Internet.
564180	567800	As with any research involved in IoT,
567800	569540	especially with so many different devices,
569540	571360	we saw some pretty strange architectures,
571360	576700	pretty strange firmwares and firmware structures.
577100	582240	The device we'll be talking about today has one of these unique architectures.
582240	585400	We can't talk about everything in the scope of 45 minutes.
585400	590820	Of course, these are very complex, detailed things.
590820	593820	The exploitation of all the vulnerabilities is something
593820	596120	that we won't be able to go into in depth.
596540	600340	We did release two white papers with full details,
600340	604080	as well as pseudocode and specific references
604080	608680	to the devices and the memory configurations that we exploited.
608700	610820	Feel free to look them up on our site
610820	613320	if you want to go into further technical detail.
614440	616860	A little bit about the vulnerability, or the CV,
616860	618440	that we'll be talking about today.
618440	622580	CV-2020-11901 is a critical vulnerability
622580	625160	in the TREC DNS resolver component,
625160	627280	so client-side DNS vulnerability.
627280	630920	Once successfully exploited, it allows remote code execution,
631440	634320	as we've demonstrated and as you'll see today.
634320	635780	The reason we think it's so interesting
635780	637700	and the reason we chose to talk about it,
637700	639980	besides being remote code execution,
639980	642780	is the fact that DNS traverses NAT boundaries.
643160	647760	A device within your network will issue a DNS request
647760	650440	which will potentially travel over the internet,
650440	652300	allowing sophisticated high-end attackers
652300	655540	to perform an attack from outside the network
655540	657740	into the network itself,
657740	661560	which is different from most vulnerabilities we see in TCP-IP stacks.
661560	664440	Behind the scenes, four vulnerabilities.
664460	666200	One, what we call an artifact.
666200	668920	That's a bug that made it easier for us to exploit.
669080	672600	And these vulnerabilities vary over time.
672600	677020	So, along the years, TREC changed the stack
677020	678280	and the vulnerabilities changed,
678280	679960	so we see different versions of the vulnerabilities
679960	683460	in different devices, depending on when they stopped using TREC.
683460	686520	They also change between vendor configuration.
686680	688660	One of the interesting things that we realized
688660	694640	during this research, as well as during the disclosure process,
694640	697420	we realized that the supply chain complexities
697420	699680	are a real problem for information security,
699680	700900	they're a real problem for the vendors,
700900	702920	they're a real problem for the network operators,
702920	705980	and they create a challenge for the whole industry.
705980	709580	And we realized this is bound to happen again.
709580	711680	We didn't research the whole TCP-IP stacks,
711680	713000	there are other TCP-IP stacks,
713000	716200	there are other pieces of code, libraries,
716200	717680	that exist in the supply chains
717680	719920	that have been lurking around for years.
719920	723220	And so, this would also be the beginning of a conversation
723220	726060	about what the vendors and what the network operators can do
726060	730420	to both reduce the impact of vulnerabilities like this
730420	733800	when they happen, using things like exploit mitigations,
733800	738180	as well as how we perform such complex disclosures
738180	741120	and how we make sure that, as vendors,
741120	743840	how the vendors make sure that their suppliers
743840	746600	are performing secure development,
746600	748940	pen testing their code, etc.
748940	751620	So, this is sort of a wake-up call to some of the vendors
751620	752840	and some of the network operators
753360	757000	that this will happen probably again and again,
757000	758680	and this can be prevented,
758680	760340	or at least the impact can be reduced,
760340	762380	using the right techniques.
763200	766280	Now, I'm going to hand over the microphone to Moshe Kol.
766280	768800	We'll be talking about the different vulnerabilities,
768800	771860	where they are in the code, and what they look like.
772480	773720	Thanks, Shlomi.
773740	778220	Hi, I'm Moshe. I'm a security researcher at JSOF,
778220	780900	and I will talk about the vulnerabilities
780900	783780	that comprise CVE-2020-11901,
783780	785620	also known as the DNS bugs.
786240	787960	So, first, we need to refresh our memory
787960	790060	about the DNS protocol.
790060	792160	So, DNS is a core internet protocol
793000	796480	designed to map between domain names and IP addresses.
796620	798160	It's a query-response protocol,
798160	800420	client-server architecture.
800560	802180	So, the client resolves the name
802180	804700	by issuing a query to a DNS server.
805080	809900	So, for example, if you browse to www.example.com,
809900	813240	your browser issues a DNS query of type A
813240	816300	to one of the configured DNS servers,
816300	818040	and the servers look up the name
818040	819820	and returns a response.
819820	821500	In this case of type A,
821500	825300	the value of the response is an IPv4 address.
825580	828080	So, a little bit about the record types.
828080	830960	So, DNS servers can return multiple answers
830960	833060	in the same DNS response.
833060	835920	An answer is specified as a resource record.
835920	838600	Each resource record is associated with a name.
838600	841700	We'll talk about the type and class fields shortly.
842020	845500	The TTL field specifies the number of seconds.
845500	847380	This record is valid.
847380	851920	The value of the record is specified in the rdata field,
851920	855540	whose length is specified in the rdlength field.
855660	860680	So, both questions and answers have a type in the DNS protocol.
860940	863580	Some of the common types include type A,
863580	866780	which specifies an IPv4 address for the query domain.
866780	869040	Type CNAME, which defines an alias,
869220	872320	a canonical name for the query domain.
872400	875160	This provides a level of indirection.
875160	878640	And type MX, which defines the domain name
878640	881180	of a mail server for the query domain.
881180	885520	So, if, for example, you send an email for gmail.com,
885520	890300	your mail client issues a DNS query for gmail.com,
890300	894400	it gets back a domain name of a mail server for gmail.com.
894400	896640	And because this is a name and not an IP address,
896640	900600	this name needs to be resolved further into an IP address.
900600	905220	So, the resolver issues a DNS query of type A in this case,
905220	908620	in order to resolve the domain name of a mail server.
908840	913000	In practice, most DNS servers simply hand in the IP address
913000	915100	along with the name, but nonetheless,
915100	919340	this functionality needs to be supported by the DNS resolvers.
920180	924040	So, a little bit about the domain names encoding,
924040	925860	the binary format.
926200	930020	So, domain names are encoded as a sequence of labels.
930020	934240	So, www is a label, example is a label.
934280	937080	Each label is preceded by a length byte,
937080	940680	specifying the number of characters this label occupies.
940680	944480	And the domain name is terminated by a zero length byte.
944600	949460	And according to the RFC, the maximum label length is 63.
949460	951020	This will come up later.
951520	955200	So, what the designers of the DNS protocols notice
955200	960680	is that there is a lot of repetition inside the DNS packet itself.
960920	965040	So, in an effort to reduce the size of the DNS messages,
965040	967380	they employ a simple compression scheme.
967380	969240	In this scheme, compression is achieved
969240	972000	by replacing a sequence of labels with a pointer
972000	974800	to prior occurrence of the same sequence.
974800	977580	So, here you can see a sample DNS response packet.
977580	981200	You can see gmail.com is specified as an offset 0xc
981720	983880	from the start of the packet.
983880	986680	And it so happens that gmail.com needs to be specified
986680	990000	multiple times inside the packet.
990000	993240	So, instead of specifying gmail.com literally in the packet,
993240	996960	again, we simply use the compression feature.
996960	1002280	We point to the previous occurrence of gmail.com.
1002280	1006140	So, if we want to write smtp.gmail.com,
1006140	1010200	we need to write only the first label literally,
1010200	1011440	smtp in this case,
1011440	1013120	and the next two labels are specified
1013120	1015280	using the compression offset.
1015820	1018060	So, in the compression schemes,
1018060	1020620	compression pointers are encoded in two bytes.
1020620	1024600	The first byte begins with 11 as the most significant bit,
1024600	1027140	and the other 14 bits specify an offset
1027140	1028900	from the start of the header.
1030320	1033200	So, as Slomi said, the vulnerabilities reside
1033200	1036740	in the DNS resolver of TrackTCPAP,
1036740	1040860	and we find them in the DNS parsing logic in the stack,
1040860	1043700	specifically in a function called tf.dns.callback.
1043700	1048100	Here you can see a snippet of pseudocode from this function,
1048100	1053440	specifically the parsing logic handling MX resource records.
1053440	1057080	So, what we can see here is that the function computes
1057520	1059880	the length of the MX hostname.
1059880	1062960	Based on that length, a buffer on the heap is allocated,
1062960	1066460	and then the MX hostname is copied as ASCII
1066460	1069920	into the just-allocated buffer.
1069920	1072980	So, what we can see from this snippet is that
1072980	1075800	tf.dns.label.to.ascii, the function that is responsible
1075800	1078920	for the copy, is not aware of the length
1078920	1080880	of the buffer being allocated.
1080940	1084640	What it does is simply copies bytes from the encoded name
1084640	1086560	until a null byte is reached.
1086800	1089720	So, this means that if, for some reason,
1089720	1093920	expand.label.length returns a length value which is too small,
1093920	1097160	we will have a heap-based buffer overflow vulnerability.
1097160	1100400	So, this motivates us to look further into expand.label.length
1100400	1102380	and examine its operation.
1102760	1105680	So, you can see a pseudocode of expand.label.length.
1105680	1108900	What this function is basically doing is sums up all the length bytes
1108900	1110880	while honoring compression.
1110880	1115120	So, in more detail, it reads the current label length,
1115120	1117660	then checks to see if there is compression or not.
1117660	1120740	If there is no compression, which is the common case,
1120740	1124420	it adds the current label length plus one to the total length variable,
1124420	1127980	which is later returned from this function, and advance the input add.
1128320	1131660	And if there is compression, it reads the compression offset,
1131660	1134960	it computes a new label pointer based on that offset,
1134960	1137300	and then it checks to see that the new label pointer
1137300	1140200	points before the initial label pointer.
1140200	1142020	So, this means we can only jump backwards
1142660	1145760	from where we were, and the process
1145760	1149520	continues from this new label pointer.
1150320	1152140	So, as you can see,
1152140	1154860	there is no bound checks on the packet buffer here,
1154860	1158840	so this led us to the first vulnerability, a read-out-of-bounds vulnerability.
1159140	1161600	This could result in a denial of service
1161600	1164720	if, for example, while iterating over the length byte,
1164720	1167040	we read from an unmapped page.
1167240	1170240	But more interestingly, we can cause
1170240	1172400	an information leakage vulnerability.
1172620	1176660	So, tf.dns.label.to.ascii, the function that does the copies,
1176660	1178700	has no bound checks either.
1178700	1182640	This means that data from the heap could be interpreted as an MX hostname.
1182640	1185480	This MX hostname is later resolved by the client
1185480	1188380	in an attempt to get an IP address.
1188420	1191040	So, this means that we can leak data from the heap
1191040	1193920	inside the MX hostname itself in the query.
1194320	1198480	This vulnerability affects track version at least 4.7,
1198480	1200520	and it was fixed in later versions,
1200520	1201820	as we will see.
1202200	1204840	We don't know the exact version of the fix,
1204840	1209600	but nonetheless, the vulnerability still affects devices in the wild
1210340	1212980	due to the complex supply chain effect
1212980	1216240	and the nature of the embedded devices,
1216240	1219040	so some don't receive updates.
1219560	1221100	So, this is nice and all,
1221100	1222840	but we are looking for an RCE,
1222840	1225780	so let's go back to the function that computes the length
1225780	1228100	and examine its operator further.
1228100	1230780	So, there are more issues with expandLabelLength.
1230780	1233900	So, per the RFC,
1233900	1238680	there is a limitation on the maximum domain name length.
1238680	1241280	The limitation is 255 characters,
1241280	1244860	and this limitation is not enforced in expandLabelLength.
1244860	1246400	Further, it does not validate
1246400	1248780	the characters of the domain name.
1248780	1251840	They should be all alphanumeric and hyphen,
1251840	1253600	but it doesn't validate it,
1253600	1257600	so we can embed bytes within the name itself.
1257600	1259380	And, last but not least,
1259380	1262740	the totalLength variable is stored as an unsigned short,
1262740	1264320	16 bits width,
1264320	1269000	and recall that the totalLength is the variable that is returned
1269420	1271980	from the expandLabelLength.
1271980	1274000	So, what we try to do is
1274000	1279080	we try to get our RCE by overflowing the totalLength variable.
1279600	1281840	So, what we need in order to pull this thing off
1281840	1283680	is to construct a name
1283680	1287020	whose length is larger than 64k.
1287020	1290160	So, we ask ourselves, is it really possible?
1290160	1291960	This is not trivial,
1291960	1294660	this is possible over UDP.
1294740	1297840	So, can we overflow the totalLength variable
1297840	1300940	within a single DNS response packet?
1301000	1304260	The answer is yes, and we use the DNS compression feature
1304260	1306240	to achieve this.
1306440	1310100	The idea was to nest compression pointers within themselves,
1310100	1313480	so recall that expandLabelLength does not validate the bytes
1313480	1316440	of the domain name itself.
1316440	1318880	This means we can embed there any bytes we want,
1318880	1322020	and in this case we chose to embed compression pointers.
1322020	1324480	You will see in the example shortly.
1324480	1328320	Keep in mind during the example that we have two challenges to overcome.
1328620	1332140	First, there is a limitation on the DNS response packet size.
1332140	1334360	The maximum size allowed over UDP
1334360	1339480	by the network stack is 1460 bytes.
1339480	1342360	And keep in mind that we can only jump backwards
1342360	1344100	from a current label pointer,
1344100	1347040	so we will need to overcome this challenge also.
1348600	1352040	Here you can see on the slide the basic construction we used.
1352040	1355000	This is a name, arranged in a matrix-like form.
1355000	1358120	Each row in this matrix has length 16.
1358360	1362260	The bluish cells represent compression pointers,
1362260	1364740	and the pink cells represent branch bytes.
1364740	1366960	We will talk about those shortly.
1368100	1371540	Let's assume we start expanding the name from this offset,
1371540	1374500	offset 0xf in the first row.
1374640	1376520	We can actually achieve this in practice
1376520	1378220	by using another compression pointer
1378220	1381220	that will land us exactly in that spot,
1381220	1383160	but for now take it as a given.
1383300	1385920	If we start expanding from this offset,
1385920	1388800	this byte is interpreted as a length byte.
1389000	1390740	In this case there is no compression,
1390740	1394840	so the function skips 0xf plus 1 bytes
1394840	1397160	and moves to the next row,
1397160	1402220	as well as adding 16 to the total length variable.
1402220	1403700	The process continues.
1403700	1405600	Notice that we stay in the same column
1405600	1411840	because of the special matrix shape
1411840	1414660	until we reach branch bytes.
1414660	1416520	The purpose of the branch byte
1416520	1419480	is simply to lead us to the next compression pointer.
1419480	1422060	In this case the branch byte is 0e,
1422060	1424440	so we land in this compression pointer.
1424620	1427080	We know that this is a compression pointer
1427080	1429100	because the high nibble is c.
1429100	1434200	What the function does is reads the compression offset.
1434480	1437320	The compression offset in this case is 0e.
1437320	1439560	It then checks to see that we point backwards
1439560	1441460	from our initial position.
1441460	1446060	Our initial position was 0xf, so 0xe is less than 0xf.
1446060	1448600	We continue expanding the name from here.
1448620	1450160	The process continues.
1450620	1454260	We reach a branch byte and another compression pointer.
1454500	1457720	You can see that with this compression trick
1457720	1460920	the total length variable nearly doubled itself.
1461040	1464020	If we continue until we reach a null byte,
1464020	1466840	in this toy example we reach a total length value
1466840	1470580	of 1500 bytes, which is pretty neat
1470580	1472160	if you consider that the name itself
1472160	1475920	only occupies 128 bytes.
1476160	1478270	Of course, this doesn't overflow
1479980	1482960	the total length variable yet,
1482960	1484600	but in order to overflow it
1484600	1486600	we use the maximum label length allowed,
1488340	1491920	63x3f, instead of xf shown in the example.
1491920	1493500	Using exactly this construction
1493500	1497200	we reach a name of length 64k
1497980	1500240	greater than 64k, thus overflowing
1500240	1502580	the total length variable itself.
1502580	1505580	And remember that if expandLabelLength returns a value
1505580	1508560	which is too small, we have an heap-based buffer overflow
1508930	1511640	which is a good RCE candidate.
1512500	1515340	Also know that this vulnerability can be triggered
1515340	1518500	in response to every query type supported by the network stack
1518500	1521060	by using CNAME resource records
1521060	1524140	which must be parsed regardless of the
1524140	1526200	original query type.
1526200	1528840	So this vulnerability affects the latest track version
1528840	1532000	at the time of disclosure, and that's considered
1532000	1535040	dangerous from our point of view.
1535040	1538600	So at this point, we decide to purchase
1538600	1540920	another device that runs track
1540920	1544260	in this case Schneider UPS device, and we want to
1544260	1547520	know if the vulnerability affects him or not.
1547520	1550180	And what we found is that track fixes the read-out-of-bank
1550180	1552700	vulnerability, but they fix it badly.
1552700	1554360	So you can see that the RDLength
1555420	1558340	value from the resource record itself checks again
1558340	1560980	the remaining size of the packet.
1560980	1564280	And now after the fix, expandLabelLength accepts
1564560	1566500	a third argument, labelEndPtr
1566500	1571640	which is computed based on the RDLength value.
1571640	1573780	And what expandLabelLength does when it reaches
1573780	1577000	this endpoint, it simply stops processing
1577000	1580920	without any error and returns the current total length.
1580920	1583540	So this is perfect from an attacker's standpoint
1583540	1586600	because RDLength is attacker-controlled.
1586600	1589660	So if, for example, we specify an RDLength value which is
1589660	1593080	too small than the actual value, we will have
1593080	1595280	an AWS buffer overflow.
1595580	1598680	So here you can see a resource record, and instead of specifying
1598680	1602180	an RDLength value of 20, we will specify 7.
1602440	1605160	So the labelEndPtr will point here
1605980	1607940	expandLabelLength returns 5 in this case
1607940	1611460	but tf.dnsLabelToAraski will copy the entire
1611460	1614160	MXSourceName, thus overflowing our buffer.
1614940	1617920	So this is the second heap-based
1617920	1620300	buffer overflow vulnerability we found.
1620300	1623440	And we also found during the MXParsing logic
1624200	1625900	a memory leak. We found that we can leak
1625900	1628600	another infrastructure. So here you can see
1628600	1631760	another infrastructure is allocated and
1631760	1635280	in these two error flows, the other info is not
1635280	1638220	freed. So this means we can leak another
1638220	1641140	infrastructure by specifying an RDLength value which is
1641140	1644260	strictly less than 2, like 1, or by causing
1644260	1647480	expandLabelLength to return a 0 length
1647480	1651000	for example by using a bad compression pointer.
1651360	1653180	So the size of the leak is
1653180	1655900	0x3c and these
1656620	1659360	artifacts come in handy when exploiting vulnerabilities
1659360	1662520	and in fact we use the exact same memory
1662520	1665960	leak in our exploit, as you will see later.
1666900	1668380	So to summarize, we saw
1668380	1671100	three vulnerabilities that comprise CVE
1671100	1675540	2020.11.9.1 and an artifact.
1675540	1677880	So the first vulnerability, the read-out-of-bounds
1677880	1680640	affects other versions of the network stack
1680640	1683500	and was fixed in later versions. The integer overflow
1683500	1686040	vulnerabilities, as far as we've seen, affects
1686040	1689900	both old and versions of the TrackTCP IP stack
1689900	1692460	and the bad RDLength vulnerability is
1693080	1695980	a result of a bad fix for the read-out-of-bounds vulnerability
1695980	1698940	and thus affects only newer versions of the stack.
1698940	1701880	The artifact is present in both old and
1701880	1704720	newer versions of the stack. And the main
1704720	1707820	takeaway from this part is that a device can be affected by
1707820	1710940	one or more vulnerabilities depending on the exact version
1710940	1713460	of the track they're using and this
1713460	1716820	fragmentation makes the life of the IT security
1716820	1719800	personnel more challenging to know whether the devices are
1719800	1723340	affected or not. So now I'll hand over the
1723340	1725880	mic to Ariel Schon. He will talk about
1725880	1727080	exploitation.
1728040	1731540	Thanks, Moshe. Hi, I'm Ariel. I'm also a security researcher
1731540	1734340	at JSOF and today I'm going to talk about exploiting
1734340	1738220	the vulnerability, the CVE, on a Schneider
1738220	1739980	Electric UPS device.
1741880	1744480	So a UPS device
1745220	1747380	is basically a big battery.
1747380	1749460	UPS stands for uninterruptible power supply
1750300	1753340	and you connect devices to it
1753340	1755860	instead of directly to the wall, to the outlet
1756480	1759100	to protect them from power outages or
1759100	1761380	power fluctuations of any sort.
1762220	1765340	So we're going to exploit on a UPS made by Schneider Electric
1765340	1767580	specifically on the network card.
1768240	1771520	This network card houses a Turbo 186
1771520	1774200	processor. It's an x86 based processor.
1774320	1776440	All code runs in 16-bit real mode
1777580	1780440	meaning also there are no modern mitigations at all
1780440	1782280	so no depth, no SLR.
1782580	1786040	This processor is x86 based. It's not strictly
1787060	1789160	x86 as seen in this processor
1789160	1792280	as a weird segmentation scheme. Instead of shifting
1792280	1795240	the segment register by 4 bits like
1795240	1798160	on x86, it does it by 8 bits and we'll see this
1798160	1800480	feature come into play later.
1801560	1804260	During this research, we had essentially
1804260	1805640	no debugging capabilities
1807080	1810420	so no JTAG, no GDB, nothing of the sort
1810420	1813260	so we relied mainly on static analysis
1813260	1816400	and reverse engineering using only limited
1816400	1819380	crash dumps as assistance.
1819400	1821460	These crash dumps as visible feature
1822120	1826000	a basic stack trace and some registers but nothing much.
1826000	1828300	So just to recap the vulnerability
1828800	1832140	our primitive is a heap overflow through DNS response parsing
1832140	1834940	and this is a rather new track
1834940	1838080	implementation so we can only overflow
1838080	1840500	with alphanumeric characters and hyphens
1840500	1842460	and periods.
1843140	1846600	And we're going to use the bad rdelect vulnerability
1846600	1850500	variant that Moshe talked about earlier.
1851260	1853100	So when exploiting heap
1853100	1855380	overflows, generally there are two methods
1855380	1857320	either through metadata corruption
1857320	1861420	so overflowing free list pointers, block sizes
1862100	1863220	stuff of the sort
1863220	1866800	or by overflowing application specific data structures
1866800	1869140	allocated on the heap.
1869140	1873100	Generally metadata is considered a more generic exploitation method
1873100	1875140	as it doesn't rely on extensive shaping
1875140	1878580	and this is the exploitation method we used
1879380	1882440	in the earlier CVE on the DigiConnect device
1883240	1886000	that we have a white paper about this
1886000	1887660	and you can find on our website
1888700	1891180	and we wondered if we can use the same
1891180	1893480	technique on this device as well.
1894460	1897440	So the track heap as implemented on the Schneider Electric QPS
1897440	1899640	is slightly different.
1899660	1902060	We have a free list that looks like this
1902060	1905820	it has a size field, next pointer to the next free list block
1905820	1909340	some free data usually containing garbage
1909340	1910620	if it's a free block
1910620	1913400	and another post size field.
1914340	1917020	So this heap features a tight fit preference
1917020	1920980	it will always allocate the smallest free block available for the allocation size requested
1920980	1923440	it also features free block coalescing
1923440	1926260	so there are never two adjacent free list blocks
1927040	1929960	and it has all sorts of verifications
1929960	1932620	and asserts that we didn't have in the previous
1932620	1934940	implementation on the Digi device
1935420	1939020	so for example on every heap operation the entire free list is checked
1939820	1941560	one of the checks is that the
1941560	1944600	first size field and the last size field
1944600	1946040	really do match
1947480	1949920	allocated blocks however are only checked when free
1950400	1951600	so this is a bit easier
1953860	1957460	corrupting the heap in a way that will not cause a premature crash
1957460	1959800	due to these checks on heap operations
1959800	1963200	Using only alphanumeric characters is rather hard,
1963200	1965180	so we chose to go in a different way
1965180	1968340	by overflowing data structures this time.
1970980	1975120	So we know we can overflow through all DNS response types,
1975120	1978660	however we chose to overflow through MX requests specifically
1978660	1980880	because when the device boots up,
1980880	1983280	it will send out three MX requests.
1984660	1988800	So that is a good exploitation primitive.
1989800	1992460	Also, three requests is very good for us
1992460	1994580	for the heap exploit,
1994580	1997600	since interactivity is always advantageous.
1997600	1999320	It allows us a bit more flexibility
1999320	2002340	in shaping our heap exactly the way we want.
2002860	2004500	And we don't really mind
2004500	2006720	that this happens only on device boot,
2006720	2009920	as we probably would have to crash the device anyway.
2009920	2012760	As said, we had limited debugging capabilities
2012760	2014040	during this research,
2014040	2017440	so not much insight into the heap and how it is shaped.
2017440	2019560	So we would like to get the heap into a state
2020070	2022820	that is as deterministic as possible.
2023600	2026180	So crashing is good in this manner.
2026260	2031400	And crashing the UPS network card has a very low penalty,
2031400	2034640	as it doesn't affect the actual UPS operation in any way.
2034640	2037760	It doesn't affect the power supply.
2037760	2040300	And the network card will automatically boot right up
2040300	2044240	after a few seconds, so the penalty is very low.
2045360	2047680	So overflowing data structures.
2047680	2051420	We chose to overflow a structure called tsDNSCacheEntry.
2051420	2053660	This structure holds information
2053660	2056620	about the DNS request-response pair.
2056780	2059760	It has all sorts of interesting fields.
2059760	2062480	For example, the dnseAdderInfoPtr field
2062480	2065180	that holds a list of AdderInfo structs.
2065180	2069540	These structs hold information about a certain DNS response.
2069560	2071620	So for example, if you resolve the name,
2071620	2073460	this structure has a field that will hold a pointer
2073860	2075820	to the name that was resolved.
2077220	2079720	Other than that, it has other pointers
2079720	2081720	and interesting fields, such as,
2081720	2083960	it's a doubly-linked list, as you can see,
2083960	2085900	so it has an X and previous entry pointers.
2086000	2087240	And these are always interesting
2087240	2089020	from an exploiter point of view.
2089900	2091420	And this structure is referenced often
2091420	2093040	in DNS response parsing,
2093040	2094980	which is a logic we can easily trigger.
2095060	2097460	So this was a natural candidate for us.
2097760	2100100	So assuming we can overflow this structure,
2100100	2101460	what can we do with it?
2102170	2107440	This is a pseudocode snippet from the parsing logic.
2107820	2111540	It specifically shows how CNAME records are parsed.
2111680	2114080	So we can see that, first thing,
2114200	2116740	a pointer is taken from the DNS cache entry
2117460	2119400	into a stack variable.
2119400	2122180	Then the CNAME is allocated on the heap
2122180	2123580	and the data is copied.
2123580	2125040	This is, of course, data we control
2125040	2127320	as we provide the DNS response.
2127480	2130620	And subsequently, the pointer to the new CNAME
2130620	2132280	allocated on the heap is placed
2134140	2137560	into what the stack variable points to.
2137600	2142420	Again, this pointer was taken from the DNS cache entry.
2142540	2144420	So if we overflow the cache entry,
2144420	2146560	we can control to where this heap pointer
2146560	2149400	to our CNAME is written to memory.
2149680	2151920	This is a control pointer, right, essentially?
2151920	2153440	We can write a four-byte pointer
2153440	2155580	to data we control on the heap.
2155580	2158200	In x86 16-bit, this is a two-byte offset
2158200	2159440	and two-byte segment.
2159920	2161940	We can write this to any alphanumeric address
2161940	2164320	as our overflow is alphanumeric.
2164380	2166980	This is a relatively strong exploitation primitive.
2166980	2169300	Writing data into places you're not supposed to write into
2169800	2172240	is always good when you try to exploit.
2172260	2175720	So this is the primitive we chose to continue with.
2176720	2179480	Our overflow is a simple heap overflow,
2179480	2181740	meaning it is from the end of our buffer
2182540	2186020	with no offset into the next,
2186020	2188620	what lies in the heap next.
2188620	2191280	So we would like, naturally,
2191280	2194540	the cache entry to be placed after the MXNAME buffer.
2194640	2196620	Because of the heap structure
2196620	2199660	in this specific trick implementation,
2199660	2201140	we have all sorts of limitations.
2201140	2204260	For example, the cache entry is allocated
2204260	2206400	on request creation.
2206420	2208060	However, the MXNAME buffer is allocated
2208060	2210080	on DNS response parsing.
2210080	2212060	So chronologically, it is allocated later
2212060	2214520	when we want it on the heap to be allocated before
2214520	2216980	so we can overflow into the cache entry.
2216980	2220460	Also, because free blocks are checked very often
2220460	2223360	in this heap implementation for corruption,
2223360	2225880	we cannot write free data.
2225880	2228400	We must overwrite only allocated data.
2228400	2230400	It will be best if we can overflow directly
2230400	2232020	into the structure without corrupting
2232020	2233760	any heap data in the way.
2234440	2236700	So we need to shape the heap in some way
2236700	2238380	to get this to happen.
2239260	2243140	A specific call pattern is preferable
2243140	2246400	as we would like to overcome the chronological problem.
2246400	2248840	We can do this because of type fit preference.
2248840	2251880	So if we create, for example, hole two,
2251880	2253820	as seen in this diagram,
2253820	2257220	this is the size of the DNS cache entry structure.
2257800	2259640	And before it, we have another hole
2259640	2262320	the size of the MXNAME buffer we're going to allocate.
2262580	2264700	We can overflow from the MXNAME buffer
2264700	2265980	into the cache entry.
2266220	2269120	We do need to separate them with some allocated separator
2269820	2271740	to prevent the two free blocks
2271740	2274760	from being coalesced together and ruining our shape.
2275280	2277840	So we need some allocation primitives to create this.
2277840	2279840	We need an allocation to create holes
2279840	2281900	and an allocation to create the separator.
2282940	2283980	So to create the holes,
2283980	2286960	we can use a temporary allocation primitive.
2287580	2289480	And this is relatively easy to achieve
2289480	2294320	as every DNS answer has all sorts of names in it
2294320	2296260	or we can cause it to have names in it.
2296260	2298360	So either MX or PDR or CNAMES,
2298360	2299460	they all have name fields.
2299460	2301740	And these names cause allocation on the heap.
2301740	2304440	So the allocation is the size of the name we provide
2304940	2307880	and its data is, of course, alphanumeric and controlled.
2308600	2310620	This allocation will also cause
2310960	2313420	a small other infrastructure to be allocated as well.
2313420	2315600	We need to take this into account when shaping.
2316460	2318960	This allocation is freed when DNS parsing fails
2318960	2322320	or when the record TTL expires.
2322900	2324980	So this allocation is perfect
2324980	2327740	for creating free regions of arbitrary size,
2327740	2329180	which is what we need.
2329180	2331640	However, we need to separate our free regions
2331640	2335560	and we can do this using the AdderInfo memory leak,
2335560	2338460	the memory leak artifact Moshe talked about earlier.
2338760	2340960	And just to recap shortly,
2340960	2344200	we can see that an AdderInfo structure is allocated
2344200	2348300	and only then the record validity is checked.
2348300	2349340	And if it's not valid,
2349340	2351480	we will exit through an error flow
2352010	2354000	and that will not free the allocation.
2354000	2356880	So we basically have a memory leak of a known size
2356880	2358560	and we can use this as a separator
2358560	2360800	between our two free buffers.
2361780	2363420	So we managed to shape the heap
2363960	2366080	into the specific shape we want.
2366080	2368140	And this allows us to reliably overflow
2368140	2371260	the DNS cache entry every time.
2372360	2374420	So assuming we can do this,
2374420	2376040	and we just showed we can,
2376040	2380120	what can we do with the CNAME pointer override primitive?
2380460	2381880	What can we override?
2382380	2385900	So this pointer write has all sorts of limitations.
2386100	2388500	It's written to an address we overflowed
2388500	2389780	into the cache entry,
2389780	2392600	so naturally only alphanumeric addresses are allowed.
2392660	2395500	However, this is a string overflow vulnerability.
2395500	2397440	After all, we're overflowing with a name,
2397440	2399200	so we do have a trailing null byte.
2399400	2403000	In x86, little-endian architecture,
2403000	2403760	this trailing null byte
2403760	2406420	can be the most significant byte of the segment,
2406420	2407940	allowing us a bit more flexibility
2407940	2409840	in the addresses we can reach.
2411160	2414860	However, nothing in this specific firmware
2414860	2418120	is placed in a strictly alphanumeric memory address,
2418120	2421480	so no code, no heap, no stack, no globals,
2421480	2423520	nothing interesting we can override.
2424460	2427460	Luckily, due to the weird segmentation
2427460	2430140	of this Turbo 186 processor,
2430140	2431960	we can use a little trick
2431960	2434860	and easily combine two alphanumeric bytes
2434860	2437500	to reach a non-alphanumeric byte
2437500	2438840	or a non-alphanumeric segment,
2438840	2440360	and this will look something like this.
2440360	2443260	For example, we choose the segment to be null byte 4b,
2443260	2444500	which is allowed.
2444800	2446400	It will then be shifted by eight bytes
2446400	2449700	and an alphanumeric offset will be added to it,
2449700	2452040	resulting in a linear address
2452040	2454700	containing a non-alphanumeric byte,
2454700	2458080	which corresponds directly to a non-alphanumeric segment.
2458160	2459920	So using this technique
2459920	2462280	due to the weird segmentation feature,
2462680	2466060	we can reach the heap utility code section,
2466060	2467700	which has all sorts of functions,
2467700	2471000	such as free and malloc, which we can overflow.
2471000	2473320	Again, this is a 16-bit real mode,
2473320	2475720	so we don't have DEP or ASLR,
2475720	2478140	allowing us to overwrite code with our primitive.
2479080	2483580	So when overwriting code in x86,
2483580	2484760	one of the interesting destinations
2484760	2487240	to overwrite with a pointer is a far call opcode,
2487240	2489220	as a far call has an absolute address
2489220	2491420	encoded directly in it.
2491480	2494220	So if we can overwrite this destination address
2494220	2498580	with our pointer, we can cause the execution flow
2498580	2500980	to move into our CNAME buffer.
2501100	2503720	So we can patch the far call using our primitive
2503720	2506840	and execute our controlled payload.
2507560	2510300	So we do this exactly, we patch a far call
2510300	2512720	in the free air flow, which is called
2512720	2514840	when metadata corruption is detected.
2514880	2517720	Naturally, we do corrupt the heap when overflowing,
2517720	2519280	so this air flow will take place
2519280	2521700	when our allocated blocks are freed.
2522960	2526040	So let's shortly recap what we did here.
2526040	2528060	First, we shaped the heap in order to get
2528060	2530040	the MXNAME buffer to be directly before
2530040	2532720	the DNS cache entry with a separator in between
2532720	2534160	that's not shown here.
2534380	2537540	We then overflow to write the DNAC other info PTR
2537540	2541800	to point into a far call in the free function.
2542560	2545480	We then process a CNAME record,
2545480	2547540	the parsing logic will process a CNAME record
2547540	2551020	containing some evil alphanumeric payload,
2551020	2553380	which will be allocated on the heap
2553380	2556040	and a pointer to this payload will be placed
2556040	2560400	into the address we put in the DNAC other info PTR,
2560400	2562320	overwriting a far call destination,
2562320	2564260	directing it to our evil payload,
2564260	2566660	which can be, for example, some alphanumeric shellcode.
2567760	2571840	Triggering this payload is rather easy,
2571840	2573100	the free air flow will be triggered
2573580	2578120	when the MXNAME record we overflowed from is free.
2578860	2582660	And the CNAME buffer, specifically what we overflowed with,
2582660	2585720	contains a two-stage alphanumeric shellcode,
2585720	2589420	which will decode itself and allow us
2589420	2592480	to run essentially arbitrary payloads,
2592480	2595040	achieving arbitrary payload execution.
2595400	2597760	Specifically, our payload just turns off power
2597760	2601000	to all UPS outlets, turning off any critical device
2601000	2602840	that was supposed to stay on.
2603000	2606840	And we will now see a short demo of this payload execution.
2642930	2645590	Thanks for listening and tuning into our presentation.
2645590	2647950	We'll be glad if you join us in the Q&A.
