operating system: ubuntu18.04
compile:
Use Google's ASAN(https://github.com/google/sanitizers) for vulnerability detection. Specifically in Makefile, `add -fsanitize=address` to CFLAGS
make
test command: ./run_tests poc
poc:
function ReadCookie(cookieName) {
return '';
var ind1 = theCookie.indexOf(';', ind);
if (ind1 == -1)
ind1 = theCookie.length;
return unescape(theCookie.substring(ind + cookieName.length + 1, ind1));
}
function ReadZagi(zagiName) {
var zagi = ReadCookie('zagi');
var ind = zagi.indexOf(zagiName);
if (ind == -1 || zagiName == '')
return '';
var ind1 = zagi.indexOf('&', ind);
if (ind1 == -1)
ind1 = zagi.length - 1;
return zagi.substring(ind + zagiName.length + 1, ind1);
}
var zip = ReadZagi('zip_code');
var city = ReadZagi('city');
var state = ReadZagi('state');
var gender = Re?dZagi('gender') == 'M' ? 'm' : ReadZagi('gender') == 'F' ? 'f' : '';
var subscribes = String(parseInt(ReadZagi('subscri'18-20';
} else if (years_old < 25) {
return '21-24';
} else if (years_old < 30) {
return '25-29';
} else if (years_old < 35) {
return '30-34';
} else if (years_old < 40) {
return '35-39';
} else if (years_old < 45) {
return '40-44';
} else if (years_old < 50) {
return '45-49';
} else if (years_old < 55) {
return '50-54';
} else if (years_old < 60) {
return '55-59';
} else if (years_old < 65) {
return '60-64';
}
return '65plus';
}
var age_range = AgeToRange(ReadZagi('age'));
function IncToRange(inc) {
var idx = 0;
var numstr = '';
for (idx = 0; idx < inc.length && inc[idx] != '+'; idx++)
if (!isNaN(parseInt(inc[idx])))
numstr += inc[idx];
inc = parseInt(numstr);
if (isNaN(inc)) {
return '';
} else if (inc <= 24999) {
return 'less25000';
} else if (inc <= 34999) {
return '25000-34999';
} else if (inc <= 49999) {
return '35000-49999';
} else if (inc <= 74999) {
return '50000-74999';
} else if (inc <= 99999) {
return '75000-99999';
} else if (inc <= 149999) {
return '100000-149999';
} else if (inc <= 249999) {
return '150000-249999';
} else if (inc >= 250000) {
return '250000plus';
}
}
var inc_range = IncToRange(ReadZagi('income'));
var _ord = _ord || Math.random() * 1000000000000000000;
var _tile_params = ';ord=' + _ord;
var _demo_params = '';
if (age_range)
_demo_params += ';age=' + age_range;
if (gender)
_demo_params += ';gender=' + gender;
if (inc_range)
_demo_params += ';income=' + inc_range;
if (subscribes)
_demo_params += ';sub=' + subscribes;
var yld_mgr = {
place_ad_here: funct
vulnerability description:
It is a use-after-free vulnerability, below is the asan output:
==19716==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000008ed8 at pc 0x00000044221a bp 0x7fffb87ca5f0 sp 0x7fffb87ca5e0
READ of size 1 at 0x606000008ed8 thread T0
0 0x442219 in CTinyJS::ternary(bool&) /home/node/tiny-js/TinyJS.cpp:1867
#1 0x442934 in CTinyJS::base(bool&) /home/node/tiny-js/TinyJS.cpp:1887
#2 0x442634 in CTinyJS::ternary(bool&) /home/node/tiny-js/TinyJS.cpp:1876
#3 0x442934 in CTinyJS::base(bool&) /home/node/tiny-js/TinyJS.cpp:1887
#4 0x4466e4 in CTinyJS::statement(bool&) /home/node/tiny-js/TinyJS.cpp:1974
#5 0x44b23a in CTinyJS::execute(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) /home/node/tiny-js/TinyJS.cpp:1322
#6 0x40718c in run_test(char const*) /home/node/tiny-js/run_tests.cpp:219
#7 0x4068b0 in main /home/node/tiny-js/run_tests.cpp:258
#8 0x7f000c85082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#9 0x406b68 in _start (/home/node/tiny-js/run_tests+0x406b68)
0x606000008ed8 is located 56 bytes inside of 64-byte region [0x606000008ea0,0x606000008ee0)
freed by thread T0 here:
0 0x7f000d534b2a in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99b2a)
#1 0x44256e in CTinyJS::ternary(bool&) /home/node/tiny-js/TinyJS.cpp:1864
previously allocated by thread T0 here:
0 0x7f000d534532 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99532)
#1 0x439204 in CTinyJS::factor(bool&) /home/node/tiny-js/TinyJS.cpp:1568
SUMMARY: AddressSanitizer: heap-use-after-free /home/node/tiny-js/TinyJS.cpp:1867 CTinyJS::ternary(bool&)
Shadow bytes around the buggy address:
0x0c0c7fff9180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0c7fff9190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0c7fff91a0: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
0x0c0c7fff91b0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
0x0c0c7fff91c0: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
=>0x0c0c7fff91d0: fa fa fa fa fd fd fd fd fd fd fd[fd]fa fa fa fa
0x0c0c7fff91e0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd
0x0c0c7fff91f0: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd
0x0c0c7fff9200: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa
0x0c0c7fff9210: fd fd fd fd fd fd fd fd fa fa fa fa 00 00 00 00
0x0c0c7fff9220: 00 00 00 00 fa fa fa fa fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Heap right redzone: fb
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack partial redzone: f4
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
==19716==ABORTING
Enviroment
poc:
vulnerability description:
It is a use-after-free vulnerability, below is the asan output: ==19716==ERROR: AddressSanitizer: heap-use-after-free on address 0x606000008ed8 at pc 0x00000044221a bp 0x7fffb87ca5f0 sp 0x7fffb87ca5e0 READ of size 1 at 0x606000008ed8 thread T0
0 0x442219 in CTinyJS::ternary(bool&) /home/node/tiny-js/TinyJS.cpp:1867
0x606000008ed8 is located 56 bytes inside of 64-byte region [0x606000008ea0,0x606000008ee0) freed by thread T0 here:
0 0x7f000d534b2a in operator delete(void*) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99b2a)
previously allocated by thread T0 here:
0 0x7f000d534532 in operator new(unsigned long) (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x99532)
SUMMARY: AddressSanitizer: heap-use-after-free /home/node/tiny-js/TinyJS.cpp:1867 CTinyJS::ternary(bool&) Shadow bytes around the buggy address: 0x0c0c7fff9180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0c7fff9190: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x0c0c7fff91a0: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa 0x0c0c7fff91b0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd 0x0c0c7fff91c0: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd =>0x0c0c7fff91d0: fa fa fa fa fd fd fd fd fd fd fd[fd]fa fa fa fa 0x0c0c7fff91e0: fd fd fd fd fd fd fd fd fa fa fa fa fd fd fd fd 0x0c0c7fff91f0: fd fd fd fd fa fa fa fa fd fd fd fd fd fd fd fd 0x0c0c7fff9200: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa 0x0c0c7fff9210: fd fd fd fd fd fd fd fd fa fa fa fa 00 00 00 00 0x0c0c7fff9220: 00 00 00 00 fa fa fa fa fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Heap right redzone: fb Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack partial redzone: f4 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe ==19716==ABORTING