Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги хакеры / практический хакинг.pdf
Скачиваний:
24
Добавлен:
19.04.2024
Размер:
31.35 Mб
Скачать

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

udp

0

0

0.0.0.0:53

0.0.0.0:*

udp

0

0

0.0.0.0:67

0.0.0.0:*

udp

0

0

:::53

:::*

udp

0

0

:::69

:::*

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

Вместо того чтобы заменять двоичный файл, можно изменить его, чтобысохранитьисходнуюфункциональностьиоболочку.Этоснизит вероятностьтого,что пользователи обнаружатбэкдор.Завершитьэто упражнение предоставляем вам самостоятельно.

Нацеливание на механизмы обновления микропрограмм

Механизм обновления микропрограмм является важным вектором атаки и одной из уязвимостей в IoT-устройствах,вошедших в десятку основныхрисковповерсииOWASP.Механизмобновлениямикропро- граммы – это процесс, который загружает новую версию микропро- граммы через веб-сайт поставщика или внешнее устройство, напри- мер USB-накопитель, и устанавливает ее путем замены более ранней версии. Эти механизмы могут создать ряд проблем безопасности­ . Они часто не могут проверить микропрограммное обеспечение или используют незашифрованные сетевые протоколы; в некоторых от- сутствуют механизмы предотвращения отката или уведомления ко- нечного пользователя олюбых изменениях безопасности­ ,вызванных обновлением. Процесс обновления может также усугубить другие проблемы в устройстве, такие как использование жестко заданных учетных данных, небезопасная аутентификация в облачном ком- поненте, на котором размещено микропрограммное обеспечение, и даже излишне подробное и небезопасное ведение журнала.

Чтобы наглядно представить все эти проблемы,мы создали специ- альную уязвимую службу обновления прошивки. Эта служба состоит из эмулированного устройства IoT, которое загружает прошивку из эмулируемой облачной службы обновления. Вы можете загрузить файлы для этого упражнения с веб-сайта книги по адресу https://no- starch.com/practical-iot-hacking/. Эта служба обновления может быть включенавбудущемкакчастьIoTGoat,намереннонебезопаснойпро- шивки на основе OpenWrt, цель которой – показать пользователям распространенные уязвимости в устройствах IoT. Авторы этой книги вносят свой вклад в проект.

Чтобыдоставитьновыйфайлпрошивки,сервербудетпрослушивать TCP-порт 31337.Клиент будет подключаться к серверу через этот порт и аутентифицироваться с помощью­ заранее заданного жестко запро- граммированного ключа. Затем сервер отправит клиенту следующие данные по порядку: длину встроенного ПО, хеш-код файла встроен- ного ПО MD5 и файл встроенного ПО. Клиент проверяет целостность файла микропрограммы, сравнивая полученный хеш MD5 с хешем файла микропрограммы, который он вычисляет с использованием

Взлом прошивки  269

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

того же предварительного ключа (использованного для аутентифи-

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

df-x chan

 

o

 

кации ранее). Если два хеша совпадают, полученный файл микропро-

.

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

граммы записывается в текущий каталог как received_firmware.gz.

Компиляция и установка

Хотя вы можете запускать клиент и сервер на одном хосте, в идеале выдолжны запускатьих на разных хостах,чтобы имитироватьреаль- ный процесс обновления.Поэтому мы рекомендуем скомпилировать и настроить два компонента в разных системах Linux. В нашем при- мере используются Kali Linux для сервера обновлений и Ubuntu для клиентаIoT,новысможетевзятьлюбойдистрибутивLinux,еслиуста- новили правильные зависимости.

Установите следующие пакеты на обе машины:

# apt-get install build-essential libssl-dev

Перейдите в каталог клиента и используйте включенный в него make-файл, чтобы скомпилировать клиентскую программу, введя следующее:

$ make client

Эта команда должна создать исполняемый клиентский файл в те- кущем каталоге.Затем скомпилируйте сервер на второй машине.Пе- рейдите в каталог, где находятся make-файл и server.c, и скомпили- руйте их, введя эту команду:

$ make server

Мы не будем анализировать код сервера, потому что при реальной оценке безопасности­ у вас, скорее всего, будет доступ только к двоич- номуфайлуклиента(даженекисходномукоду!)изфайловойсистемы микропрограммы.Но в образовательных целях рассмотрим исходный код клиента,чтобы исследовать лежащие в его основе уязвимости.

Код клиента

Теперь посмотрим на клиентский код.Эта программа,написанная на

C,доступна по адресу https://nostarch.com/practical-iot-hacking/.Здесь мы выделим только важные части:

#define PORT 31337

#define FIRMWARE_NAME "./received_firmware.gz"

#define KEY "jUiq1nzpIOaqrWa8R21"

270  Глава 9

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Директивы #define определяют постоянные значения. Сначалаwмы

 

 

 

 

 

m

 

w Click

 

 

 

 

 

o

 

 

w

 

 

 

 

 

 

 

 

определяем порт сервера, который будет прослушивать служба обd-f-x chan

.c

 

 

 

.

 

 

 

 

 

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

новления. Далее указываем имя для полученного файла прошивки.

 

 

 

 

 

 

Затем жестко кодируем ключ аутентификации, который уже был пе-

 

 

 

 

 

 

редан серверу.Использование жестко запрограммированных ключей

 

 

 

 

 

 

создает угрозу безопасности­

, как мы объясним позже.

 

 

 

 

 

 

 

 

 

 

Мы разделили код клиентской функции main() на два отдельных списка для большей ясности. Первая часть представлена в листин-

ге 9.2.

Листинг 9.2. Первая половина функции main() незащищенного клиента обновления прошивки

int main(int argc, char **argv) { struct sockaddr_in servaddr;

int sockfd, filelen, remaining_bytes; ssize_t bytes_received;

size_t offset;

unsigned char received_hash[16], calculated_hash[16]; unsigned char *hash_p, *fw_p;

unsigned int hash_len; uint32_t hdr_fwlen;

char server_ip[16] = "127.0.0.1"; FILE *file;

if (argc > 1)

strncpy((char *)server_ip, argv[1], sizeof(server_ip) - 1);

openlog("firmware_update", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_LOCAL1); syslog(LOG_NOTICE, "firmware update process started with PID: %d", getpid());

memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET;

inet_pton(AF_INET, server_ip, &(servaddr.sin_addr)); servaddr.sin_port = htons(PORT);

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) fatal("Could not open socket %s\n", strerror(errno));

if (connect(sockfd, (struct sockaddr *)&servaddr, sizeof(struct sockaddr)) == -1) fatal("Could not connect to server %s: %s\n", server_ip, strerror(errno));

/* отправляем ключ для аутентификации */ write(sockfd, &KEY, sizeof(KEY));

syslog(LOG_NOTICE, "Authenticating with %s using key %s", server_ip, KEY);

/* получаем размер прошивки */

recv(sockfd, &hdr_fwlen, sizeof(hdr_fwlen), 0); filelen = ntohl(hdr_fwlen);

printf("filelen: %d\n", filelen);

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

Взлом прошивки  271

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-xcha

 

 

 

 

 

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

X

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

Мы не будем подробно объяснять сетевую программную часть кода

 

 

 

to

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

 

w

 

df-x chan

 

o

 

и сосредоточимся в большей степени на функциональности высоко-

.

.c

 

 

 

 

p

 

 

 

 

g

 

 

 

 

 

 

 

 

 

 

 

e

 

го уровня. Обратите внимание на переменную server_ip , которая хранит IP-адрес сервера как строку C с завершающим нулем. Если пользователь не указывает аргумент в командной строке при запуске клиента, IP-адресом по умолчанию будет localhost (127.0.0.1). В про- тивном случае мы копируем первый аргумент argv[1] (поскольку argv[0] всегда является именем файла программы) в server_ip . За- тем открываем соединение с системой logger и инструктируем ее,что все сообщения, которые она получит в будущем, будут добавляться к ключевому слову firmware_update,за которым следует идентифика- тор процесса вызывающего абонента (PID). С этого момента каждый раз, когда программа вызывает функцию системного журнала, она отправляет сообщения в файл /var/log/messages – общий журнал ак- тивностисистемы,которыйобычноиспользуетсядлянекритических, неотладочных сообщений.

Следующий блок кода подготавливаетсокетTCP (черездескриптор сокета sockfd) и инициирует TCP-соединение с сервером.Если сер- вер прослушивает на другом конце, клиент успешно выполнит трех- стороннее квитирование TCP. Затем он может начать отправку или получение данных через сокет.

Затем клиент аутентифицируется на сервере, отправляя значение KEY, определенное ранее . Он отправляет в системный журнал дру- гое сообщение, указывающее, что он пытается аутентифицироваться с использованием этого ключа. Это действие демонстрирует две не- безопасные практики: запись избыточных данных в журнал и вклю- чение конфиденциальной информации в файлы журнала. Предвари- тельный секретный ключ теперь записывается в журнал, к которому могут иметь доступ непривилегированные пользователи. Вы можете узнать больше об этих проблемах на https://cwe.mitre.org/data/definitions/779.html и https://cwe.mitre.org/data/definitions/532.html.

После успешной аутентификации клиент ожидает получения дли- ны микропрограммного обеспечения от сервера, сохраняя это значе- ние в hdr_fwlen, а затем преобразует сетевой порядок байтов в поря- док размещения байтов на хосте путем вызова ntohl .

В листинге 9.3 показана вторая часть функции main.

Листинг 9.3. Вторая половина функции main() незащищенного клиента обновления прошивки

/* получение хеша */

recv(sockfd, received_hash, sizeof(received_hash), 0);

/* получение файла */

if (!(fw_p = malloc(filelen)))

fatal("недостаточно памяти для получения прошивки\n");

remaining_bytes = filelen; offset = 0;

272  Глава 9

 

 

 

 

hang

e

 

 

 

 

 

 

 

 

 

C

 

E

 

 

 

 

 

 

X

 

 

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

 

F

 

 

 

 

 

 

 

t

 

 

 

D

 

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

 

 

r

 

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

 

to

 

 

 

 

 

 

while (remaining_bytes > 0) {

 

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

m

w Click

 

 

 

 

 

 

o

bytes_received = recv(sockfd, fw_p + offset, remaining_bytes, 0);

 

w

 

 

 

 

 

 

 

 

 

 

.

 

 

 

 

 

e

 

 

 

p

df

 

 

 

g

.c

 

 

 

 

 

 

 

n

 

 

 

 

 

 

 

 

 

-xcha

 

 

 

 

 

offset += bytes_received;

 

 

 

 

 

 

 

 

 

 

 

 

remaining_bytes -= bytes_received; #ifdef DEBUG

printf("Получено байтов %ld\n", bytes_received);

#endif

}

 

 

 

 

hang

e

 

 

 

 

 

 

 

C

 

E

 

 

 

 

X

 

 

 

 

 

 

-

 

 

 

 

 

d

 

 

F

 

 

 

 

 

 

t

 

 

D

 

 

 

 

 

 

 

i

 

 

 

 

 

 

 

 

 

r

P

 

 

 

 

 

NOW!

o

 

 

 

 

 

 

 

 

 

 

 

 

BUY

 

 

 

 

 

 

to

 

 

 

 

 

w Click

 

 

 

 

 

m

 

 

 

 

 

 

w

 

 

 

 

 

 

 

 

 

 

w

 

 

 

 

 

 

 

o

 

 

.

 

 

 

 

 

.c

 

 

 

p

 

 

 

 

g

 

 

 

 

 

df

 

 

n

e

 

 

 

 

 

-x cha

 

 

 

 

/* проверка прошивки путем сравнения полученного и вычисленного хеша */ hash_p = calculated_hash;

hash_p = HMAC(EVP_md5(), &KEY, sizeof(KEY) - 1, fw_p, filelen, hash_p, &hash_len);

printf("вычисленный хеш: ");

for (int i = 0; i < hash_len; i++) printf("%x", hash_p[i]);

printf("\nполученный хеш: ");

for (int i = 0; i < sizeof(received_hash); i++) printf("%x", received_hash[i]);

printf("\n");

if (!memcmp(calculated_hash, received_hash, sizeof(calculated_hash))) printf("хеши совпадают\n");

else

fatal("хеши не совпадают\n");

/* запись прошивки на диск */

if (!(file = fopen(FIRMWARE_NAME, "w")))

fatal("Не удалось открыть файл для записи %s\n", strerror(errno)); fwrite(fw_p, filelen, 1, file);

syslog(LOG_NOTICE, "Прошивка успешно скачана"); /*очистка */

free(fw_p); fclose(file); close(sockfd); closelog(); return 0;

Послеполучениядлинымикропрограммы(хранящейсявперемен- ной filelen) клиент получает хеш MD5 файла микропрограммы (хра- нится в переменной received_hash) .Затем,в зависимости отдлины микропрограммы, он выделяет необходимую память в куче для по- лучения файла микропрограммы . Цикл while постепенно получа- ет файл микропрограммы с сервера и записывает его в выделенную память.

Затем клиент вычисляет MD5-хеш файла микропрограммы (calculated_hash), используя предварительный ключ . В целях отладки мы также печатаем вычисленные и полученные хеши. Если два хеша соответствуют , клиент создает файл в текущем каталоге, исполь- зуя имя файла,взятое из значения FIRMWARE_NAME.Затем он выгружает микропрограммное обеспечение , которое было сохранено в памя-

Взлом прошивки  273