01 Бер, 2023

Умови гонки в багатопотокових застосуваннях

Vulnerability Assessment as a Service (VAaaS)

Tests systems and applications for vulnerabilities to address weaknesses.

Що таке багатопотокове додаток?

Багатопотокове програма - це комп'ютерна програма, яка використовує кілька потоків для одночасного виконання декількох завдань або операцій. Потік - це полегшений процес, який може виконуватися незалежно від інших потоків в рамках того ж процесу. Використовуючи декілька потоків, програма може підвищити свою продуктивність, продуктивність і масштабованість.

В багатопотоковому додатку кожен потік виконує окрему послідовність інструкцій, які можуть виконуватися одночасно з іншими потоками в тій же програмі. Це дозволяє програмі виконувати кілька завдань або операцій одночасно, таких як обробка користувальницького введення, а також виконання фонових завдань, таких як файловий ввід / вивід (введення / висновок) або мережевий зв'язок.

Багатопоточність може використовуватися в різних додатках, включаючи веб-сервери, системи управління базами даних та мультимедійні додатки. Багатопотокове додаток може забезпечити більш чуйний інтерфейс, оскільки фонові завдання можуть виконуватися одночасно, не блокуючи потік користувальницького інтерфейсу.

Що таке уразливість в умовах гонки?

В кібербезпеки стан гонки виникає, коли вразливість системи безпеки виникає часу і порядку подій в системі. Умови гонки можуть дозволити зловмисникам отримати несанкціонований доступ до ресурсів або інформації, обійти засоби контролю безпеки або підвищити привілеї.

Наприклад, в багатокористувацької системою може виникнути стан гонки, якщо два користувача спробують одночасно отримати доступ до одного і того ж ресурсу. Якщо система не забезпечує належного контролю доступу або механізмів блокування ресурсів, один користувач може отримати доступ до ресурсу раніше іншого, що потенційно може поставити під загрозу його конфіденційність, цілісність або доступність.

Іншим прикладом стану гонки в кібербезпеки є уразливість від часу перевірки до часу використання (TOCTTOU). Це відбувається, коли програма перевіряє умову або ресурс в один момент часу, але потім використовує або покладається на це умова чи ресурс в більш пізній момент часу. Якщо зловмисник може змінити або маніпулювати умовою або ресурсом протягом минулого періоду часу, він може скористатися уразливістю і отримати несанкціонований доступ або виконати довільний код.

Для запобігання конфліктних ситуацій в області кібербезпеки розробники і системні адміністратори повинні впроваджувати методи безпечного кодування, такі як належне використання механізмів синхронізації і контролю доступу, а також ретельне тестування і аудит своїх систем для виявлення і усунення вразливостей. Також важливо підтримувати програмне забезпечення і системи в актуальному стані з допомогою виправлень і оновлень безпеки для усунення відомих вразливостей.

Що таке нитка?

В обчислювальній техніці потік - це найменша одиниця виконання, яку програма може запланувати для виконання. Потік - це послідовність інструкцій, які можуть виконуватися незалежно від інших потоків в рамках однієї і тієї ж програми. Кілька потоків можуть виконуватися одночасно в рамках одного процесу, що дозволяє програмі виконувати кілька завдань або операцій одночасно.

При одночасному запуску декількох потоків додаток може виконувати кілька завдань одночасно, що може призвести до більш швидкої і гнучкої продуктивності. Використовуючи декілька потоків, додаток може легше масштабуватися для обробки великих робочих навантажень і підвищених вимог користувачів. Використання потоків може допомогти розбити складні завдання на дрібніші, більш керовані фрагменти коду, що спрощує написання, тестування та обслуговування великих і складних додатків.

Потоки можуть обмінюватися даними та спільно використовувати ресурси з іншими потоками в тому ж процесі, такі як змінні, пам'ять або файли. Однак це також створює нові проблеми, такі як умови гонки, взаємоблокування і проблеми з синхронізацією, які при неправильному використанні можуть призвести до непередбачуваного і небажаного поведінки.

Щоб розробити програму, що використовує потоки, розробники повинні ретельно спроектувати свою програму, щоб забезпечити безпечний і синхронізований доступ до загальних ресурсів. Це вимагає використання методів синхронізації, таких як блокування, семафори або атомарні операції, щоб гарантувати, що тільки один потік може отримати доступ до спільного ресурсу одночасно. Крім того, розробники повинні протестувати і налагодити свою програму, щоб виявити і усунути будь-які умови гонки або проблеми з синхронізацією, які можуть виникнути.

Що таке умови гонки в багатопотоковому додатку

Умови гонки в багатопоточних додатках виникають, коли два або більш потоків одночасно звертаються до спільного ресурсу, і кінцевий результат роботи програми залежить від порядку виконання потоків. Це може призвести до непередбачуваного і небажаної поведінки, включаючи пошкодження даних, збої програм або уразливості в системі безпеки.

В багатопотоковому додатку потоки часто спільно використовують доступ до таких ресурсів, як пам'ять, файли або мережеві підключення. Якщо два або більш потоків намагаються змінити один і той же ресурс одночасно, може виникнути стан гонки. Наприклад, якщо один потік читає з файлу, в той час як інший потік намагається його видалити, кінцевий результат залежить від того, який потік виконується першим.

Умови гонки може бути важко виявити і відтворити, оскільки вони часто виникають спорадично і залежать від таких факторів, як завантаження системи і час виконання потоку. Їх також може бути важко виправити, оскільки вони вимагають ретельної синхронізації і координації між потоками для забезпечення безпечного і передбачуваного доступу до спільних ресурсів.

Щоб уникнути умов гонки в багатопотокових застосуваннях, розробникам слід використовувати методи синхронізації, такі як блокування, семафори або атомарні операції, щоб гарантувати, що тільки один потік може одночасно звертатися до спільного ресурсу. Вони також повинні ретельно керувати порядком виконання потоків, щоб забезпечити послідовний і передбачуваний доступ до загальних ресурсів. Крім того, ретельне тестування і налагодження можуть допомогти виявити і усунути умови гонки до того, як вони можуть викликати серйозні проблеми.

Користувачі можуть визначати умови гонки в багатопотоковому додатку

Умови гонки в багатопоточних додатках можуть проявлятися різними способами, але деякі загальні поведінки додатків, які можуть вказувати на стан гонки, включають:

Невірний або несподіваний висновок. Якщо вихідні дані програми невірними або неочікувані, це може вказувати на те, що декілька потоків одночасно звертаються до одного і того ж ресурсу і видають суперечливі результати.

Збій або зависання. Якщо додаток несподівано виходить з ладу або зависає, це може бути ознакою того, що з-за стану гонки програма зависає або перестає відповідати на запити.

Непослідовна поведінка. Якщо поведінка додатки непослідовно, це може вказувати на те, що різні потоки по-різному звертаються до спільних ресурсів, що призводить до несподіваних результатів.

Проблеми з продуктивністю. Якщо продуктивність програми знижується при високій навантаженні або паралелізм, це може вказувати на те, що кілька потоків конкурують за одні і ті ж ресурси і викликають затримки чи вузькі місця.

Тупики. Взаємоблокування виникає, коли два або більш потоків блокуються в очікуванні звільнення ресурсу один одним, що призводить до ситуації, коли ні один з потоків не може виконати прогрес. Взаємоблокування можуть бути ознакою стану перегонів, якщо вони виникають, коли кілька потоків звертаються до спільних ресурсів.

Як пентестеры або розробники можуть виявляти умови гонки в багатопотоковому додатку

Перевірка коду. Одним із способів виявлення умов перегонів є ретельний аналіз вихідного коду програми. Розробники можуть шукати коду області, в яких доступ до загальних ресурсів, таким як змінні та структури даних, здійснюється декількома потоками без належної синхронізації.

Приклад 1 

Коли кілька потоків звертаються до одного і того ж спільного ресурсу без належної синхронізації, може виникнути стан гонки. Наприклад, якщо два потоку намагаються збільшити значення загальної змінної одночасно, вони обидва можуть зчитувати одне і те ж значення, а потім записувати назад одне і те ж збільшене значення, в результаті чого збільшується тільки змінна один раз, а не двічі.

				
					import threading

# A shared variable
counter = 0

def increment():
    global counter
    for i in range(100000):
        counter += 1

# Create two threads that both call the increment function
thread1 = threading.Thread(target=increment)
thread2 = threading.Thread(target=increment)

# Start the threads
thread1.start()
thread2.start()

# Wait for the threads to finish
thread1.join()
thread2.join()

# The expected result is 200000, but due to the race condition, the 
# actual result may be lower
print("Counter value:", counter)
				
			

У цьому прикладі у нас є загальна змінна з ім'ям counter це збільшується кожним потоком в циклі. В increment функція збільшує змінну лічильника на 1 в 100000 разів. Однак, оскільки у нас є два потоку, виконують increment функціонуючи одночасно, вони можуть одночасно зчитувати і записувати в змінну лічильника, викликаючи стан гонки. У результаті змінна лічильника може бути збільшена не так, як очікувалося, і кінцеве значення може бути нижче очікуваного значення 200000.

Приклад 2

Якщо кілька потоків записують дані в один і той же файл без належної синхронізації, може виникнути стан гонки, при якому записи чергуються, а вихідні дані спотворюються.

				
					import threading

def write_to_file(file_name, text):
    with open(file_name, 'a') as f:
        f.write(text)

threads = []

# Create 5 threads that write to the same file
for i in range(5):
    t = threading.Thread(target=write_to_file, args=('output.txt', f'Thread {i}\n'))
    threads.append(t)
    t.start()

# Wait for all threads to finish
for t in threads:
    t.join()
				
			
				
					Thread 1
Thread 2
ThThread 3
read 4
d 0
				
			

У цьому коді створюється декілька потоків для запису тексту в один і той же файл output.txt. Однак, оскільки синхронізація між потоками відсутня, текст з кожного потоку може чергуватися, а вихідні дані можуть спотворюватися. Наприклад, висновок output.txt може виглядати приблизно так, як описано вище. 

Приклад 3

Коли кілька потоків оновлюють одну і ту ж структуру даних без належної синхронізації, може виникнути стан гонки. Наприклад, якщо два потоку намагаються додати елемент в один і той же список одночасно, вони обидва можуть прочитати одну і ту ж довжину списку, вставити свій елемент, а потім записати назад нову довжину списку, в результаті чого один з елементів буде перезаписаний.

				
					import threading

# A shared list
my_list = []

def add_item():
    global my_list
    # Read the current length of the list
    current_length = len(my_list)
    # Add an item to the list
    my_list.append(threading.current_thread().name)
    # Write back the new length of the list
    new_length = len(my_list)
    print(f"{threading.current_thread().name} added an item to the list. List length: {new_length}")
    # Check for race condition
    if new_length != current_length + 1:
        print(f"Race condition detected by {threading.current_thread().name}! List length should be {current_length + 1}, but is {new_length}.")

# Create multiple threads that add an item to the list
t1 = threading.Thread(target=add_item)
t2 = threading.Thread(target=add_item)
t1.start()
t2.start()
t1.join()
t2.join()

				
			

У цьому прикладі два потоку намагаються додати елемент в один і той же список. В add_item() функція зчитує поточну довжину списку, додає елемент у списку, а потім записує назад нову довжину списку. Однак, оскільки синхронізація між потоками відсутня, може виникнути стан гонки, коли обидва потоку зчитують список однакової довжини, вставляють свій елемент, а потім записують назад ту ж нову довжину списку, в результаті чого один з елементів перезаписується.

Коли ви запустите цей код, ви можете побачити наступні вихідні дані:

				
					Thread-1 added an item to the list. List length: 1
Thread-2 added an item to the list. List length: 1
Race condition detected by Thread-1! List length should be 2, but is 1.

				
			

У цьому випадку умова гонки виникло з того, що обидва потоку прочитали однакову довжину списку, а потім записали назад ту ж нову довжину списку, в результаті чого був доданий тільки один елемент замість двох. В if заява в add_item() функція визначає стан гонки і виводить повідомлення на консоль.

Приклад 4 

В цьому прикладі є два потоки і дві блокування. Кожен потік отримує одну блокування, а потім намагається отримати іншу блокування. Якщо один потік отримує lock1, а інший потік отримує lock2, то виникає глухий кут, тому що кожен потік чекає, поки інший потік зніме необхідну йому блокування.

				
					import threading

# Create two locks
lock1 = threading.Lock()
lock2 = threading.Lock()

def thread1():
    lock1.acquire()
    lock2.acquire()
    # Do something
    lock1.release()
    lock2.release()

def thread2():
    lock2.acquire()
    lock1.acquire()
    # Do something else
    lock2.release()
    lock1.release()

# Create two threads and start them
t1 = threading.Thread(target=thread1)
t2 = threading.Thread(target=thread2)
t1.start()
t2.start()
t1.join()
t2.join()

				
			

Тестування. Пентестеры можуть виконувати комплексне тестування програми, використовуючи такі інструменти, як стрес-тестування та стрес-тестування, для моделювання сценаріїв з високим трафіком і одночасним доступом. Це може допомогти виявити потенційні умови гонки і проблеми з синхронізацією.

Налагодження. Якщо є підозра на стан гонки, розробники можуть використовувати відладчик для покрокового виконання коду та відстеження стану змінних і інших ресурсів по мірі звернення до них різних потоків. Це може допомогти визначити першопричину стану гонки.

Ведення журналу. Розробники можуть додавати оператори ведення журналу код, щоб відстежувати послідовність подій і виявляти будь-які невідповідності або несподіване поведінку, які можуть вказувати на стан гонки.

КРАЩІ CWES для умов гонки в багатопотокових застосуваннях

CWE-362: Одночасне виконання з використанням загального ресурсу з неправильною синхронізацією ('Стан гонки') Цей CWE виникає, коли кілька потоків виконуються одночасно, звертаються до спільного ресурсу без належної синхронізації і призводять до несподіваного чергуванню ресурсу. Це може призвести до суперечливих даними, невірних результатів і збоїв.

CWE-835: Цикл з недосяжним умовою виходу ('Нескінченний цикл') Цей CWE виникає, коли цикл виконується в многопоточной середовищі, і один потік змінює змінну циклу, в той час як інший потік очікує завершення циклу. Це може призвести до нескінченного циклу, і програма перестане відповідати на запити.

CWE-831: Неправильна синхронізація Цей CWE виникає, коли кілька потоків звертаються до спільного ресурсу без належної синхронізації, що призводить до стану гонки. Це може привести до неузгодженості даних, неправильним результатами і збоїв.

CWE-833: Взаємоблокування Цей CWE виникає, коли два або більш потоків блокуються, чекаючи, поки один від одного звільниться ресурс, необхідний їм для продовження роботи. Це може призвести до глухий кут, коли потоки не можуть продовжити роботу і програма перестає відповідати.

CWE-834: Неправильно контрольована модифікація атомарної операції Цей CWE виникає, коли кілька потоків змінюють атомарну операцію, таку як ціле число або логічне значення, без належної синхронізації. Це може призвести до суперечливих даних і невірних результатів.

КРАЩІ CVE для умов гонки в багатопотокових застосуваннях

CVE-2016-2324 – Обхід Apache Tomcat Security Manager через завантажувач класів контексту потоку Цей CVE впливає на Apache Tomcat і пов'язаний зі станом гонки в реалізації Security Manager. Його можна використовувати для обходу диспетчера безпеки і отримання несанкціонованого доступу до ресурсів.

CVE-2018-16640 – WordPress 4.9.8 Підвищення привілеїв Цей CVE впливає на WordPress і пов'язаний зі станом гонки в механізмі оновлення. Його можна використовувати для підвищення привілеїв та виконання довільного коду в вразливою системі.

CVE-2019-11477 – Linux Kernel SACK Panic Цей CVE впливає на ядро Linux і пов'язаний зі станом гонки в реалізації TCP. Він може бути використаний для того, щоб викликати атаки типу "відмова в обслуговуванні" (DoS) шляхом збою системи.

CVE-2019-11478 – Уповільнення роботи ядра Linux Цей CVE також впливає на ядро Linux і пов'язаний зі станом гонки в реалізації TCP. Він може бути використаний для того, щоб викликати DoS-атаку, сповільнюючи роботу системи.

CVE-2020-25223 – Вразливість стану гонки Apache Struts2 Цей CVE впливає на Apache Struts2 і пов'язаний зі станом гонки в реалізації TokenInterceptor. Його можна використовувати для обходу аутентифікації та отримання несанкціонованого доступу до ресурсів.

CVE-2021-32027 – Apache Tomcat jsp: вразливість forward Цей CVE впливає на Apache Tomcat і пов'язаний зі станом гонки в реалізації jsp:forward. Його можна використовувати для обходу обмежень безпеки і отримання несанкціонованого доступу до ресурсів.

CVE-2021-31800 – Вразливість віддаленого виконання коду на сервері Microsoft Exchange Цей CVE впливає на сервер Microsoft Exchange і пов'язаний зі станом гонки в додатку панелі керування Exchange (ПЕК). Він може бути використаний для виконання довільного коду в вразливою системі.

Реальні приклади з життя 

У січні 2021 року в macOS Big Sur від Apple була виявлена помилка, яка могла викликати стан гонки, коли кілька процесів одночасно намагалися отримати доступ до одного і того ж файлу. Це може призвести до пошкодження даних і привести до збоїв системи.

У березні 2021 року було повідомлено про уразливості в Microsoft Exchange Server, яка може дозволити зловмисникам виконувати довільний код у вразливою систему, використовуючи стан гонки в додатку.

У квітні 2021 року в Apache Cassandra була виявлена уразливість, яка могла дозволити зловмисникам виконувати довільний код у вразливою систему, використовуючи умову гонки при обробці додатком з'єднань SSL / TLS

У травні 2020 року Microsoft Windows зіткнулася з уразливістю, пов'язаної зі станом гонки в інтерфейсі графічного пристрою Windows (GDI). Зловмисники можуть використовувати цю уразливість для підвищення привілеїв та виконання довільного коду в вразливою системі.

У липні 2020 року Apple macOS зіткнулася з уразливістю, пов'язаної зі станом гонки в коді ядра. Зловмисники можуть скористатися цією вразливістю, щоб отримати підвищені привілеї і виконати довільний код у вразливою системі.

У серпні 2020 року операційна система Android зіткнулася з уразливістю, пов'язаної зі станом гонки в драйвері binder. Зловмисники можуть скористатися цією вразливістю, щоб отримати підвищені привілеї і виконати довільний код у вразливою системі.

Як захистити додаток від умов гонки при багатопоточності

Синхронізація: Використовуйте механізми синхронізації, такі як блокування, семафори та монітори, щоб гарантувати, що тільки один потік може одночасно звертатися до загальних ресурсів. Правильна синхронізація запобіжить одночасний доступ декількох потоків до одного і того ж ресурсу або його зміну.

Атомарні операції: Використовуйте атомарні операції, які гарантують, що операція буде виконана за один неподільний крок. Атомарні операції особливо корисні для простих операцій з загальними змінними, таких як збільшення або зменшення лічильника.

Безпека різьби: Переконайтеся, що код з самого початку розроблений таким чином, щоб бути потокобезопасным. Потокобезопасность може бути досягнута за рахунок відмови від глобальних змінних, використання незмінних структур даних і відділення від стану поведінки.

Огляди коду: Проведіть перевірку коду, щоб переконатися, що програма розроблена з урахуванням паралелізму. Огляди коду можуть виявити потенційні умови конкуренції і гарантувати, що код написаний таким чином, щоб його було легко зрозуміти і підтримувати.

Висновок

На закінчення, умови гонки в багатопоточних додатках можуть бути значним джерелом вразливостей в системі безпеки та інших проблем, які можуть вплинути на продуктивність і стабільність програми. Ці проблеми можуть виникнути, коли кілька потоків намагаються отримати доступ до загальних ресурсів без належної синхронізації або коли додаток не розроблено з урахуванням паралелізму.

Щоб усунути умови гонки в багатопотокових застосуваннях, розробники повинні впровадити механізми синхронізації, використовувати атомарні операції, спроектувати код так, щоб він був потокобезопасным з самого початку, ретельне тестування і провести перевірку коду. Крім того, розробники повинні бути в курсі останніх вразливостей і виправлень системи безпеки, щоб гарантувати захист своїх додатків від нових і виникаючих загроз.

В цілому, хоча умови гонки можуть бути складними для виявлення та пом'якшення їх можна запобігти за допомогою правильного проектування, тестування і впровадження методів синхронізації, що призведе до створення більш безпечних і надійних багатопоточних додатків.

Інші Послуги

Готові до безпеки?

зв'язатися з нами