Кіріспе

Компьютерлік қауіпсіздік және бағдарламалаудағы аномалия. Бағдарламалау және ақпараттық қауіпсіздікте буферлік ағып кету немесе буферлік асып кету – бұл бағдарламаның буферге, оның бөлінген жадысынан тыс деректерді жазу арқылы туындайтын аномалия, соның салдарынан жақын орналасқан жад орындары жаңартылып жазылады. Буферлер – бағдарламаның бір бөлімінен екіншісіне немесе бағдарламалар арасында деректерді жылжыту кезінде деректерді сақтауға арналған жад аймақтары. Буферлік ағып кету көбінесе бұрыс кіріс деректерінен туындайды. Егер кіріс дерегінің барлығы белгілі бір көлемнен кіші болады деп есептелсе және буфер сол көлемде құрылса, онда одан көп деректерді тудыратын аномальді транзакция буфердің соңынан тысқары жазуға себеп болуы мүмкін. Егер бұл жақын орналасқан деректерді немесе орындалатын кодты жаңартып жазса, бағдарламаның тұрақсыз мінез-құлқына, жадқа қол жеткізу қателеріне, дұрыс емес нәтижелерге және құлауларға әкелуі мүмкін. Буферлік ағып кетуді пайдалану – кең таралған қауіпсіздік әдісі. Көптеген жүйелерде бағдарламаның немесе жүйенің жад құрылымы анықталған. Буферлік ағып кетуге себеп болатын деректерді жіберу арқылы орындалатын кодты сақтайтын аймақтарға жазуға және оны зиянды кодпен алмастыруға, немесе бағдарламаның күйіне қатысты деректерді таңдап жаңартуға болады, бұл бастапқы бағдарламашы көздемеген мінез-құлыққа әкеледі. Буферлер операциялық жүйе (ОЖ) кодында кеңінен қолданылады, сондықтан рұқсаттарды арттыруға және компьютер ресурстарына шексіз қол жеткізуге мүмкіндік беретін шабуылдар жасауға болады. 1988 жылғы танымал Моррис құрты осы әдісті шабуылдың бір түрі ретінде пайдаланды. Буферлік ағып кетумен жиі байланысты бағдарламалау тілдері – C және C++, олар жадтың кез келген бөлігінде деректерге қол жеткізуге немесе жаңартуға қарсы қорғаныспен жабдықталмаған және массивке жазылған деректердің (буфердің енгізілген түрі) сол массивтің шегінде екенін автоматты түрде тексермейді. Шекараны тексеру буферлік ағып кетуді болдырмауы мүмкін, бірақ ол қосымша кодты және өңдеу уақытын қажет етеді. Қазіргі операциялық жүйелер зиянды буферлік ағып кетулермен күресу үшін әртүрлі әдістерді қолданады, әсіресе жад құрылымын кездейсоқ түрде өзгерту арқылы немесе буферлер арасында бос орын қалдырып, сол аймақтарға жазатын әрекеттерді ("канарлар") іздеу арқылы.

Техникалық сипаттама

Буфердің асығуы жеткіліксіз шектеулерді тексеру салдарынан буферге жазылған деректер мақсатты буферге жақын жад мекенжайларындағы деректерді зақымдағанда пайда болады. Бұл деректерді көшіру кезінде, олар мақсатты буферге сыятыны тексерілмесе, бір буферден екінші буферге көшіру арқылы орын алуы мүмкін.

Пайдалану

Буферлік ағызу осалдығын пайдалану тәсілдері архитектураға, операциялық жүйеге және жад облысына қарай әртүрлі болады. Мысалы, динамикалық жадқа бөлінген жадта (үйірде) пайдалану, шақыру стегіндегі пайдаланудан едәуір өзгеше. Жалпы алғанда, үйірдегі пайдалану нысана жүйеде қолданылатын үйір менеджеріне, ал стектегі пайдалану архитектура мен компилятор қолданатын шақыру конвенциясына байланысты.

Жинақталған пайдалану

Баффердің ағындысы жинақтағы деректер аймағында пайда болған жағдайда, ол жинақ ағындысы деп аталады және стектік ағындылардан өзгеше жолмен қолданылуы мүмкін. Жинақтағы жад бағдарлама орындалу кезінде динамикалық түрде бөлінеді және әдетте бағдарлама деректерін қамтиды. Бұл деректерді белгілі бір тәсілмен бұрмалау арқылы, бағдарламаның ішкі құрылымдарды, мысалы, тізбекті тізімдегі көрсеткіштерді жаңартуына мүмкіндік туады. Стандартты жинақ ағындысы әдісі динамикалық жадты бөлу байланысын (мысалы, malloc метадеректері) жаңартып, нәтижедегі көрсеткіш алмасуын бағдарлама функциясының көрсеткішін жаңарту үшін пайдаланады. Microsoft-тың JPEG файлдарын өңдеудегі GDI+ осалдығы – жинақ ағындысының қаншалықты қауіпті болуының мысалы.

Пайдалануға кедергілер

Буферді оқу немесе орындау алдында жасалған манипуляциялар, әрекеттің сәтсіздікке ұшырауына әкелуі мүмкін. Мұндай манипуляциялар пайдалану қаупін азайтуға көмектеседі, бірақ оны толығымен болдырмайды. Манипуляцияларға әріптерді үлкен немесе кішкентайға түрлендіру, метасимволдарды жою және әріп-сандық емес тізбектерді сүзу кіруі мүмкін. Дегенмен, осы сүзгілерді және манипуляцияларды айналып өтуге болатын әдістер бар, мысалы, әріп-сандық шелл-код, полиморфты код, өзін-өзі өзгертетін код және libc-ға қайта оралу шабуылдары. Осы әдістерді енуді анықтау жүйелерінен жасыру үшін де қолдануға болады. Кейбір жағдайларда, мысалы, код Юникодқа түрлендірілген кезде, ақпаратты жариялаушылар бұл қауіпті тек қызметтен бас тарту ретінде көрсетіп бұрмалаған, бірақ шындығында кез келген кодты қашықтан орындау мүмкін.

Пайдаланудың практикалық ерекшеліктері

Нақты әлемдегі шабуылдарда, эксплойттардың сенімді жұмыс істеуі үшін еңсеру қажет болатын түрлі қиындықтар кездеседі. Осы факторларға адрестердегі нөлдік байттар, шелл-кодтың орналасуындағы өзгермелілік, ортаның өзгешеліктері және қолданылып жатқан түрлі қарсы шаралар жатады.

NOP санақ техникасы

NOP шлейфтері – стек буферінің ағып кетуін пайдаланудың ең көне және кең таралған әдісі. C тілі жадтың кез келген бөлігіндегі деректерге қол жеткізуге немесе оларды жаза бастыруға қарсы ешқандай қорғаныс шарасын қарастырмайды. Нақтырақ айтқанда, ол буферге жазылған деректердің сол буфердің шегінде екенін тексермейді. Стандартты C++ кітапханалары деректерді қауіпсіз буферлеудің көптеген тәсілдерін ұсынады, ал C++ стандартты үлгілер кітапханасы (STL) бағдарламашы деректерге қол жеткен кезде тексеруді қажет етсе, шектеулерді тексеруді қосымша мүмкіндік ретінде орындай алатын контейнерлерді ұсынады. Мысалы, вектордың мүше функциясы `at` шектеуді тексеріп, егер тексеру сәтсіз болса, диапазоннан тыс қателік тудырады. Дегенмен, C++ шектеуді тексеру нақты шақырылмаса, C сияқты жұмыс істейді. Буфер ағып кетуін болдырмау үшін C үшін де әдістер бар. Қатты типтелген және тікелей жадқа қол жеткізуге рұқсат бермейтін COBOL, Java, Python және басқа тілдер көп жағдайда буфер ағып кетуін болдырмайды. Жақсы жазылған және тексерілген абстрактілі деректер типі кітапханалары, буферді басқаруды орталықтандырып, автоматты түрде орындайтын, соның ішінде шектеулерді тексеруді қамтитын, буфер ағып кетуін және оның салдарларын азайта алады. Буфер ағып кетуі жиі кездесетін тілдердегі негізгі дерек түрлері – жолдар мен массивтер. Осылайша, осы дерек түрлерінде буфер ағып кетуін болдырмайтын кітапханалар қажетті қамтудың басым бөлігін қамтамасыз ете алады. Алайда, осы қауіпсіз кітапханаларды дұрыс пайдаланбау буфер ағып кетуіне және басқа да осалдықтарға әкелуі мүмкін, ал кітапханадағы кез келген қате де әлеуетті осалдық болып табылады. "Қауіпсіз" кітапханаларды іске асыруларға "The Better String Library", Vstr және Erwin кіреді. OpenBSD операциялық жүйесінің C кітапханасы `strlcpy` және `strlcat` функцияларын ұсынады, бірақ олар толыққанды қауіпсіз кітапханалық іске асырулардан шектеулі. 2007 жылдың қыркүйегінде C стандарттар комитеті дайындаған 24731 техникалық есеп жарияланды. Ол стандартты C кітапханасының жол және кіріс-шығыс функцияларына негізделген функциялар жиынтығын, қосымша буфер өлшемі параметрлерімен анықтайды. Алайда, осы функциялардың буфер ағып кетуін азайтудағы тиімділігі күмәнді. Олар бағдарламалаушының араласуын қажет етеді, ол әр функцияны шақыру кезіндегі араласу, бұл араласу ескі стандартты кітапхана функцияларын буфер ағып кетуінен қорғай алады.

Буфердің толып кетуін қорғау

Буферлік ағып кетуден қорғау, функция қайтарылғанда стек өзгермегенін тексеру арқылы ең көп кездесетін буферлік ағып кетуді анықтау үшін қолданылады. Егер стек өзгертілген болса, бағдарлама сегментациялық қатемен тоқтатылады. Libsafe, StackGuard және ProPolice gcc патчтары – мұндай үш жүйе. Microsoft-тың Data Execution Prevention (DEP) режимі Structured Exception Handler (SEH) көрсеткішінің жазылуынан тікелей қорғайды. Стекты екіге бөлу арқылы күштірек қорғауға қол жеткізуге болады: біреуі деректер үшін, екіншісі функциялардың қайтарылуы үшін. Бұл бөліну Forth тілінде де бар, бірақ ол қауіпсіздікке негізделген дизайн шешімі емес. Дегенмен, бұл буферлік ағып кету мәселесіне толыққанды шешім емес, себебі қайтару мекенжайынан басқа құпиялы деректер де жазылуы мүмкін. Бұл қорғау түрі де толыққанды дәл емес, өйткені ол барлық шабуылдарды анықтай алмайды. StackGuard сияқты жүйелер шабуылдардың мінез-құлқына көбірек назар аударады, бұл оларды ауқымды тексеру жүйелерімен салыстырғанда тиімді және жылдам етеді.

Көрсеткіш қорғанысы

Буферлік ағымдау, сақталған адрестерді қоса алғанда, көрсеткіштермен жұмыс істейді. PointGuard көрсеткіштер мен адрестерді шабуылшылардың сенімді түрде манипуляциялауына жол бермеу үшін компиляторға қосымша мүмкіндік ретінде ұсынылды. Бұл тәсіл компиляторға көрсеткіштерді пайдалану алдында және кейін автоматты түрде XOR кодымен шифрлейтін кодты қосу арқылы жұмыс істейді. Теориялық тұрғыдан алғанда, шабуылшы көрсеткішті шифрлеу және ашып алу үшін қандай мән қолданылатынын білмейтіндіктен, егер ол жаңа мәнмен жазылса, көрсеткіш неге нұсқама беретінін болжау мүмкін емес. PointGuard ешқашан жарияланбаған, бірақ Microsoft Windows XP SP2 және Windows Server 2003 SP1 нұсқаларынан бастап ұқсас тәсілді енгізді. Көрсеткіштерді қорғауды автоматты мүмкіндік ретінде енгізудің орнына, Microsoft шақыруға болатын API функциясын қосты. Бұл жақсы өнімділікке мүмкіндік береді (өйткені ол үнемі қолданылмайды), бірақ бағдарламашыны оның қолданылуы қажет болған кезде білуге міндеттейді. XOR сызықтық болғандықтан, шабуылшы шифрланған көрсеткішті адрестің төменгі байттарын ғана жазып өзгерту арқылы манипуляциялай алады. Егер шабуылшы бірнеше рет әрекет етуге тырысса немесе көрсеткішті бірнеше орның біріне (мысалы, NOP шлейфіндегі кез келген орынға) нұсқау беру арқылы шабуылды аяқтаса, бұл шабуылға мүмкіндік береді. Microsoft осы кемшілікті ішінара жазып өзгертуге қатысты шешу үшін шифрлеу схемасына кездейсоқ бұруды қосты.

Адрес кеңістігінің жайласуын кездейсоқ таңдау

Адрес кеңістігінің кездейсоқ орналасуы (ASLR) – компьютерлік қауіпсіздіктің мүмкіндігі, ол процестің адрес кеңістігіндегі негізгі деректер аймақтарының – орындалатын файлдың бастапқы орны, кітапханалардың, үйіндінің және стектің орналасуы сияқты – орнын кездейсоқ түрде анықтайды. Функциялар мен айнымалылардың ізделуіне арналған виртуалды жад адрестерін кездейсоқ ету, буферлік асығуды пайдалануды қиындатады, бірақ толығымен болдырмайды. Бұл сонымен қатар шабуылшыны әрекетін нақты жүйеге бейімдеуге мәжбүр етеді, осылайша интернет құрттарының таралмауына кедерес жасайды. Процестер мен кітапханаларды виртуалды адрес кеңістігінде қайта орналастыру – бұған ұқсас, бірақ азырақ тиімді әдіс.

Терең пакеттерді тексеру

Терең пакеттерді тексеру (DPI) желі периметрінде шабуыл қолтаңбалары мен эвристиканы қолдану арқылы буфер асығуын пайдалануға жасалған қарапайым қашықтықтан жасалатын әрекеттерді анықтауға мүмкіндік береді. Бұл техника белгілі шабуылдың қолтаңбасын ұсынған пакеттерді тоқтатуға мүмкіндік береді. Бұрын, бұл әдіс ұзақ тізбектес операциясыз нұсқаулар (NOP шлейф деп аталады) анықталғанда және эксплойттің пайдалы жүктемесінің орны шамалы өзгерген жағдайларда қолданылған. Пакеттерді сканерлеу тиімді әдіс емес, себебі ол тек белгілі шабуылдарды ғана тоқтатуға болады, ал NOP шлейфін кодтаудың көптеген тәсілдері бар. Шабуылшылар қолданатын шелл-кодты әріп-сандық, метаморфтық немесе өздігінен өзгертіп, эвристикалық пакет сканерлері мен кіргізуді анықтау жүйелерінен жасыруға болады.

Сынау

Буфердің толып кетуін тексеру және оларды тудыратын қателерді жою буфердің толып кетуін алдын алуға көмектеседі. Оларды анықтаудың бір жалпы автоматтандырылған тәсілі – фаззинг. Шекті жағдайларды тексеру, сондай-ақ статикалық талдау буфердің толып кетуін анықтауға көмектеседі. Буфердің болуы мүмкін толып кетуі анықталғаннан кейін, оны жою қажет. Бұл сынақ тәсілі әзірлену үстіндегі бағдарламалық қамтамасы үшін пайдалы, бірақ енді қолдау көрсетілмейтін немесе жаңартылмайтын ескі бағдарламалық қамтамасы үшін тиімсіз.

Тарих

Буферлік ағып кетулер 1972 жылға дейін түсінілді және ішінара жарияланды, Компьютерлік қауіпсіздік технологиясын жоспарлау туралы зерттемеде техника сипатталған: "Бұл функцияны орындайтын код бастапқы және түмендік мекенжайларды тиісті түрде тексермейді, бұл пайдаланушыға монитордың бөліктерін жабуға мүмкіндік береді. Бұл пайдаланушыға машинаны бақылауға мүмкіндік беретін кодты мониторға енгізу үшін пайдаланылуы мүмкін". Бүгінде монитор ядро деп аталады. Буферлік ағып кетулерді қастандықпен пайдаланудың ең алғашқы құжатталған жағдайы 1988 жылы тіркелді. Бұл Morris құртының интернетте таралуының бірнеше тәсілдерінің бірі болды. Пайдаланылған бағдарлама Unix жүйесіндегі finger қызметі еді. Кейін, 1995 жылы Томас Лопатик буферлік ағып кетуді тәуелсіз түрде қайта ашты және оның нәтижелерін Bugtraq қауіпсіздік пошта тізімінде жариялады. Бір жыл өткен соң, 1996 жылы Элиас Леви (сонымен қатар Алеф One ретінде белгілі) Phrack журналында "Күлкі мен пайда үшін стекке шабуыл" атты мақала жариялады, ол стекке негізделген буферлік ағып кетулердің осалдықтарын пайдалануға қадамдық нұсқаулық болды. Одан бері кем дегенде екі ірі интернет құрты буферлік ағып кетулерді пайдаланып көптеген жүйелерді бұзды. 2001 жылы Code Red құрты Microsoft Internet Information Services (IIS) 5.0 буферлік ағып кетуін пайдаланды, ал 2003 жылы SQL Slammer құрты Microsoft SQL Server 2000 жүретін машиналарды бұзды. 2003 жылы лицензияланған Xbox ойындарындағы буферлік ағып кетулер лицензияланбаған бағдарламалық жасақтаманы, соның ішінде үй жасалған ойындарды аппараттық өзгерістерсіз консольде іске қосу үшін пайдаланылды, олар модчиптер деп белгілі. PS2 Independence Exploit PlayStation 2 үшін де осы мақсатқа жету үшін буферлік ағып кетуді пайдаланды. Twilight хакі Wii консолінде де осылай болды, The Legend of Zelda: Twilight Princess ойынында буферлік ағып кетуді пайдаланды.