Հարձակում Node.js-ի վրա JavaScript օբյեկտների նախատիպերի մանիպուլյացիայի միջոցով

Հելմհոլցի տեղեկատվական անվտանգության կենտրոնի (CISPA) և Թագավորական տեխնոլոգիաների ինստիտուտի (Շվեդիա) հետազոտողները վերլուծել են JavaScript-ի նախատիպի աղտոտման տեխնիկայի կիրառելիությունը Node.js հարթակի և դրա վրա հիմնված հանրաճանաչ հավելվածների վրա հարձակումներ ստեղծելու համար, ինչը կհանգեցնի կոդի կատարման:

Նախատիպի աղտոտման մեթոդը օգտագործում է JavaScript լեզվի առանձնահատկությունը, որը թույլ է տալիս նոր հատկություններ ավելացնել ցանկացած օբյեկտի արմատային նախատիպին: Հավելվածները կարող են պարունակել կոդային բլոկներ (գործիքներ), որոնց աշխատանքի վրա ազդում է փոխարինված հատկությունը, օրինակ՝ կոդը կարող է պարունակել այնպիսի կառուցվածք, ինչպիսին է «const cmd = options.cmd || «/bin/sh»', որի տրամաբանությունը կփոխվի, եթե հարձակվողին հաջողվի փոխարինել «cmd» հատկությունը արմատային նախատիպում:

Հաջող հարձակումը պահանջում է, որ հավելվածը կարողանա օգտագործել արտաքին տվյալներ՝ օբյեկտի արմատային նախատիպում նոր հատկություն ստեղծելու համար, և որ կատարումը հանդիպի գործիքի, որը կախված է փոփոխված հատկությունից: Նախատիպի փոփոխությունն իրականացվում է Node.js-ում «__proto__» և «կոնստրուկտոր» ծառայության հատկությունների մշակմամբ: «__proto__» հատկությունը վերադարձնում է օբյեկտի դասի նախատիպը, իսկ «կոնստրուկտոր» հատկությունը վերադարձնում է օբյեկտի ստեղծման համար օգտագործվող ֆունկցիան։

Եթե ​​հավելվածի կոդը պարունակում է «obj[a][b] = արժեք» հանձնարարությունը, և արժեքները դրված են արտաքին տվյալներից, հարձակվողը կարող է «a» սահմանել «__proto__» արժեքի վրա և հասնել սեփական գույքի տեղադրմանը: «b» անունով և «արժեք» արժեքով օբյեկտի արմատային նախատիպում (obj.__proto__.b = արժեք;), իսկ նախատիպի մեջ սահմանված հատկությունը տեսանելի կլինի բոլոր օբյեկտներում: Նմանապես, եթե ծածկագիրը պարունակում է այնպիսի արտահայտություններ, ինչպիսիք են «obj[a][b][c] = արժեք»՝ «a» դնելով «կոնստրուկտոր» արժեքին, իսկ «b»՝ «նախատիպ» բոլոր առկա օբյեկտներում, կարող եք. սահմանել նոր սեփականություն «c» անունով և «արժեք» արժեքով։

Նախատիպը փոխելու օրինակ՝ const o1 = {}; const o2 = new Object(); o1.__proto__.x = 42; // ստեղծել «x» հատկությունը root prototype console.log-ում (o2.x); // մուտք գործել «x» հատկություն մեկ այլ օբյեկտից // ելքը կլինի 42, քանի որ արմատային նախատիպը փոխվել է o1 օբյեկտի միջոցով, որն օգտագործվում է նաև o2 օբյեկտում:

Խոցելի կոդի օրինակ՝ ֆունկցիա enterPoint (arg1, arg2, arg3){ const obj = {}; const p = obj[arg1]; p[arg2] = arg3; վերադարձ p; }

Եթե ​​enterPoint ֆունկցիայի արգումենտները ձևավորվում են մուտքային տվյալներից, ապա հարձակվողը կարող է փոխանցել «__proto__» արժեքը arg1-ին և ստեղծել ցանկացած անունով սեփականություն արմատային նախատիպի մեջ: Եթե ​​դուք փոխանցում եք arg2 արժեքը «toString» և arg3 արժեքը 1, կարող եք սահմանել «toString» հատկությունը (Object.prototype.toString=1) և խափանել հավելվածը toString(-ին) կանչի ժամանակ:

Իրավիճակների օրինակներ, որոնք կարող են հանգեցնել հարձակվողի կոդի կատարման, ներառում են «հիմնական», «շելլ», «արտահանում», «contextExtensions» և «env» հատկությունների ստեղծումը: Օրինակ՝ հարձակվողը կարող է օբյեկտի արմատային նախատիպում ստեղծել «հիմնական» հատկություն՝ դրանում գրելով դեպի իր սցենարի ուղին (Object.prototype.main = «./../../pwned.js») և այս հատկությունը կկանչվի կատարման պահին պահանջի («my-package») կոնստրուկցիայի կոդով, եթե ներառված փաթեթը հստակորեն չի սահմանում «հիմնական» հատկությունը package.json-ում (եթե հատկությունը սահմանված չէ, այն կստացվի արմատային նախատիպից): «shell», «exports» և «env» հատկությունները կարող են փոխարինվել նույն կերպ. թող rootProto = Object.prototype; rootProto["exports"] = {".":"./changelog.js"}; rootProto["1"] = "/path/to/npm/scripts/"; // ձգան կանչը պահանջում է ("./target.js"); Object.prototype.main = "/path/to/npm/scripts/changelog.js"; Object.prototype.shell = «հանգույց»; Object.prototype.env = {}; Object.prototype.env.NODE_OPTIONS = "—inspect-brk=0.0.0.0:1337"; // ձգան զանգը պահանջվում է («բայթ»);

Հետազոտողները վերլուծել են 10 NPM փաթեթներ ամենամեծ թվով կախվածություններով և պարզել են, որ դրանցից 1958-ը չունեն հիմնական հատկություն package.json-ում, 4420-ը օգտագործում են հարաբերական ուղիներ իրենց պահանջվող հայտարարություններում, իսկ 355-ն ուղղակիորեն օգտագործում են հրամանի փոխարինման API-ը:

Աշխատանքային օրինակը օգտագործում է «Parse Server» հետնամասի վրա հարձակվելու համար, որը վերացնում է evalFunctions հատկությունը: Նման խոցելիության հայտնաբերումը պարզեցնելու համար մշակվել է գործիքակազմ, որը համատեղում է ստատիկ և դինամիկ վերլուծության մեթոդները: Node.js-ի փորձարկման ժամանակ հայտնաբերվել են 11 գաջեթներ, որոնք կարող են օգտագործվել հարձակումներ կազմակերպելու համար, որոնք հանգեցնում են հարձակվողի կոդի գործարկմանը։ Բացի Parse Server-ից, NPM CLI-ում հայտնաբերվել են նաև երկու շահագործվող խոցելիություններ:

Source: opennet.ru

Добавить комментарий