mouldybread / DCS-6100LH

Hacking the D-Link DCS-6100LH
53 stars 4 forks source link

Root Access, Cutting the Cloud and Firmware Decryption #8

Open DSchndr opened 10 months ago

DSchndr commented 10 months ago

Hi, I've spent a night to play around with that platform The information might be useful for others which want to play around a bit more

Be warned - without a dump you cannot recover most of the system since the update packages are "incomplete"

Root access can be achieved quite easy:

Cutting the Cloud is just as simple:

Now how do we get the camera into the wifi without any app?

How can the Stream be accessed?

How can the update package be decrypted?

Other infos:

For 15€ that thing is quite nice and seems to feature some interesting hardware features

inge-arnesen commented 10 months ago

Great work, DSchndr - thanks! Is it running busybox and if so, what is compiled in? What would be the best way to dump the current image with as few changes to it as possibe?

DSchndr commented 10 months ago

Busybox, yes Just use a hardware programmer like ch341a... or you can dump over uart with uboot with something like: sf probe sf read [somewhere in ram in hex] 0 [flashsize in hex] md.b [somewhere in ram hex] [flashsize in hex] record output with a serial monitor that can save to a file, then put it back to binary with xxd extract mtd partitions with dd, as to where which one is the kernel boot log tells you that as for the rest: rts3904n_base_defconfig.txt btw, the uboot change above is just temporary to get a initial root shell, saveenv makes it permanent

MaiZumm commented 10 months ago

May you prepare a flashable firmware with all those mods?

grocid commented 10 months ago

The /etc/shadow entry for root is

root:urJK6EZeAewo.:17683:0:99999:7:::

This is descrypt which is eight chars only. Unfortunately, dictionary attacks didn't work for me, so it is probably a 8-char randomized password. Would interesting to see if it is device specific.

I'd say the simplest solution would be to take the v1.0 firmware, modify so that telnetd starts (it is commented out in /mydlink/mydlink_watchdog.sh) and repack and encrypt it using the same key, IV and seed.

Sidenote: As @DSchndr mentioned, aoni_ipc has debug symbols. This seems to be the case for all non-standard unix binaries I looked at.

Sidenote 2: Password cracked

urJK6EZeAewo.:b46bb4a2

inge-arnesen commented 10 months ago

On my system, with firmware version 1.01, nothing was mounted after boot, not even /mnt/cfg, so I had to manually run:

mount -t jffs2 /dev/mtdblock5 /mydlink 
mount -t jffs2 /dev/mtdblock6 /mnt/conf

Optionally:

mount -t jffs2 /dev/mtdblock4 /mnt/mtd

Shadow entry for root was (so device specific):

root:w7FMsOnLqEvTU:17683:0:99999:7:::

Was not able to set WIFI parameters successfully. Did on my laptop:

inge@huhei:~$ echo myssid | base64
bXlzc2lkCg==
inge@huhei:~$ echo mypassword | base64
bXlwYXNzd29yZAo=

Then modified the [Net] section in /mnt/conf/SystemConfig.ini to read:

[Net]
Dhcp = on
WIFI_SECURITY_TYPE = 5 
WIFI_SSID = bXlzc2lkCg==
WIFI_PWD = bXlwYXNzd29yZAo= 
register_st = 1

During boot it says:

....
2018-06-01 00:00:17 info    [network_wifi_build_wpa_cfg:2041]iwlist done
2018-06-01 00:00:17 info    [network_wifi_build_wpa_cfg:2057]ready to connect ssid myssid
 passwd:mypassword
.....

But later says:

....
2018-06-01 00:00:24 info    [network_cur_interface_type:258]current net interface was WIIRELESS_NET_TYPE
Failed to connect to non-global ctrl_ifname: wlan0  error: No such file or directory
Successfully initialized wpa_supplicant
Line 9: invalid quotation '"mypassword'.
Line 10: Invalid SSID line '"'.
Line 11: failed to parse network block.
Failed to read or parse configuration '/mnt/mtd/wpa_supplicant.conf'.
2018-06-01 00:00:25 info    [network_cur_interface_type:258]current net interface was WIIRELESS_NET_TYPE
Failed to connect to non-global ctrl_ifname: wlan0  error: No such file or directory
.....

Unsure how to proceed. Could it be the firmware version?

DSchndr commented 10 months ago

so they do use device specific passwords, nice

@inge-arnesen check /mnt/mtd/wpa_supplicant.conf, something is wrong there (did you reboot after setting/getting the password?) register_st = 1 has to be in one of the lower config sections, it says 0 on a unconfigured device there (and causes it to go back to wifi ap mode)

inge-arnesen commented 10 months ago

Thanks @DSchndr !

I had forgotten "-n" in my echo to base64, so there was a newline added to each string. Fixing that and changing the register_st value further down fixed the IP connectivity.

For telnet enable I noticed that telnetd is actually started during normal, unmodified boot (its PID file is present in /var/run), but is stopped in /mnt/mtd/boot.sh with:

/etc/init.d/S50telnet stop

Commenting out that line lets it continue running

EDIT: I also noticed that (at least my unit) has no working RTC and date is set to 2018. I appended the following to /mnt/mdt/boot.sh to get correct (UTC) time on my streams:

sleep 20
g=`/bin/curl -s --head http://google.com | /bin/grep '^Date:' | /bin/cut -d' ' -f3-`
d=`/bin/date  -d "$g" -D '%d %b %Y %H:%M:%S %Z'  +'%Y-%m-%d %H:%M:%S'`
/bin/date -s "$d"

Have you guys a working RTC or a better solution?

DSchndr commented 10 months ago

aoni_ipc should get the time from an dlink ntp server, at least the code is in there (plop the binary into ghidra and check where it gets set and why)

The best thing to work on would be to add support for it in OpenIPC in order to have a cloudless camera with more features (than just a rstp stream), the issue for that is here

inge-arnesen commented 9 months ago

Just to let you know: I cracked my original root password and unfortunately it is not the same as @grocid 's (adjusting for the salt).

Worth noting is that my original root password contained [0-9a-f] (hex) characters only. If that is the same on all devices, the factory root passwords are easily cracked

grocid commented 9 months ago

@inge-arnesen You don't really need the password for the devices since there is a rather trivial RCE (as root obviously) vulnerability in the recovery. I've reported it to D-link and will give them a couple of weeks to act, but I am pretty sure you can find it yourself.

Edit: But in case you really want to derive the password there is a function mydlink_set_root_pwd which essentially MD5s the model name and the MAC address and uses the 8 first hex chars as root password. Not that great source of entropy to be honest.

grocid commented 7 months ago

Since D-link showed no interest in the vulnerability, I'm publishing the exploit for rooting the camera without needing to access the camera physically (apart from setting it in recovery mode):

https://gist.github.com/grocid/becaff3b0c7bef3edcb5801b70b7af21

adriannnpv commented 3 months ago

I've used this to hack a DCS-8620LH but it seems I can't connect to the RTSP stream.

Even tho the console prints this

[RtspServer_set_loginInfo] stream_num : 2 , username : admin , password : 490027  stream type : h265 h264 - aac
RTSP server ip filter : 0

and this

RTPINFO: rtpWriterOpen: called for name = sip=0.0.0.0,prt=554,mpath=live,ses=profile.0,vid=h265,aud=aac,ach=1,sr=16000,abps=16000,bch=1,mod=0,ums=1370,tms=8192,mip=NULL,mptv=5678,mpta=2345,mp2t=0,sto=60,user=admin,pass=490027,rtcp=0,sri=3000
RTPINFO: rtpWriterOpen: Calling parse function
RTPINFO: Create Session namely profile.0 with rtspSingleModeFlag as 0 UDP MTU size as 1370 and TCP MTU size as 8192
!!!INFO!!! :
ENTER :
        ServerHandle = 7673704
        SessionName = profile.0
        MulticastIP = (null)
        FileEndTime = 0 sec

        MaxBitrate = 0
        MinBitrate = 0

        MaxFramerate = 0
        MinFramerate = 0
!!!INFO!!! : Waiting for RTSP Client Connection on port 554
!!!INFO!!! : User added to session 7674016
RTPINFO: rtpWriterOpen: RTSP server started on IP =0.0.0.0, port = 554
RTPINFO: rtpWriterOpen: exits
data start 246192 index start 28 data_circle 0 index circle 0
ch:0 === ch_type:0 === 0x6c55ec
data start 4800 index start 6 data_circle 0 index circle 0
ch:1 === ch_type:0 === 0x751b04
RTPINFO: rtpWriterCreate: exits
RTPINFO: rtpWriterOpen: called for name = sip=0.0.0.0,prt=554,mpath=live,ses=profile.1,vid=h264,aud=aac,ach=1,sr=16000,abps=16000,bch=1,mod=0,ums=1370,tms=8192,mip=NULL,mptv=5679,mpta=2346,mp2t=0,sto=60,user=admin,pass=490027,rtcp=0,sri=10000
RTPINFO: rtpWriterOpen: Calling parse function
RTPINFO: Create Session namely profile.1 with rtspSingleModeFlag as 0 UDP MTU size as 1370 and TCP MTU size as 8192
!!!INFO!!! :
ENTER :
        ServerHandle = 7673704
        SessionName = profile.1
        MulticastIP = (null)
        FileEndTime = 0 sec

        MaxBitrate = 0
        MinBitrate = 0

        MaxFramerate = 0
        MinFramerate = 0
!!!INFO!!! : User added to session 7504496
RTPINFO: rtpWriterOpen: RTSP server started on IP =0.0.0.0, port = 554
RTPINFO: rtpWriterOpen: exits
data start 218056 index start 19 data_circle 0 index circle 0
ch:0 === ch_type:1 === 0x751c44
data start 5600 index start 7 data_circle 0 index circle 0
ch:1 === ch_type:0 === 0x7284d4
killall: dhcp6c: no process killed
!!!INFO!!! : 'H264' Stream Added Successfully
!!!INFO!!! : 'MPEG4-GENERIC' Stream Added Successfully
!!!INFO!!! : 'opus' Stream Added Successfully
killall: rdnssd: no process killed

When I try to login in VLC I get this

!!!INFO!!! : DESCRIBE Handle received from client
!!!INFO!!! : Get URL sessionName : live/profile.1/video
!!!INFO!!! : authHeader : Digest username="admin", realm="RtpRtspServer", nonce="ZGM2YWQxMDhhZTEyMzQ1Njc4OWFiY2RlZjI4OWFzZHNhZGFzbDs=", uri="rtsp://10.0.0.165:554/live/profile.1/video", response="d0274d020a8dcbbe374188ef1e357c47"
!!!ERROR!!! : Authorization failed

[Begin]=============== Rtsp Client Ack ==================[Begin]
RTSP/1.0 401 Unauthorized
CSeq: 4
Server: RtpRtspServer
WWW-Authenticate: Digest realm="RtpRtspServer", nonce="ZGM2YWQxMDhiNTEyMzQ1Njc4OWFiY2RlZjI4OWFzZHNhZGFzbDs=", stale=FALSE

  len:184
[End]==================================================================[End]

SystemConfig.ini looks like this

[System]
TimeZone = 0
VideoMode = 0
bFlip = 0
bMirror = 0
Rotate = 0
IrcutEnable = 1
InVol = 100
OutVol = 100
SirenVol = 100
SirenTime = 60
IrledDisable = 0
DevAccount = admin
DevPassWord = admin
Mac = 12:32:45:78:45:22
Vendor = QW9uaQ==
DevModel = QU9OSV9JUEM=
FactoryDefault = 0
ResetWifi = 1
IRcutSeq = 1
DNlux = 10

[Production]
Enable = 0

[Net]
Dhcp = on
WIFI_SECURITY_TYPE = 4
WIFI_SSID = 
WIFI_PWD = 

[Lux]
adc_print_enable = 0
minLuxAdc = 700
maxLuxAdc = 1350
lux_level = 0

[Led]
led_switch = 1
red_enable = 1
blue_enable = 1
green_enable = 1

[Preset]
point_x_0 = -1
point_y_0 = -1
point_x_1 = -1
point_y_1 = -1
point_x_2 = -1
point_y_2 = -1
point_x_3 = -1
point_y_3 = -1
point_x_4 = -1
point_y_4 = -1
point_x_5 = -1
point_y_5 = -1
point_x_6 = -1
point_y_6 = -1
point_x_7 = -1
point_y_7 = -1
point_x_8 = -1
point_y_8 = -1
point_y_8 = -1
point_x_9 = -1
point_y_9 = -1
point_x_10 = -1
point_y_10 = -1
point_x_11 = -1
point_y_11 = -1

[AlarmPlan]
Alarm_Enable = 0
MDLevel = 2
active1 = 0
day_flag1 = 0
start_time1 = 0
end_time1 = 0
active2 = 0
day_flag2 = 0
start_time2 = 0
end_time2 = 0
active3 = 0
day_flag3 = 0
start_time3 = 0
end_time3 = 0
active4 = 1
day_flag4 = 127
start_time4 = 0
end_time4 = 86400
alarm_interval = 60

[OSD]
OsdDisplayEnable = 1
OsdTimeStyle = 3
OsdTime12or24format = 24
OsdDeviceName =

[Time]
NtpEnable = 1
NtpSrv1 = ntp1.dlink.com
DstActive = 0
DstOffsetSeconds = 0
DstStartTimestamp = 0
DstStopTimestamp = 0
SystimeDstStatus = 0

[AudioDetect]
audio_detect_enable = 0
audio_record_enable = 1
trigger_db = 60
audioInterval = 60

[HumanDetect]
enable = 0
sensitivity = 5
human_track_enable = 0

[Onvif]
OnvifUser_0 = admin
OnvifDiscoveryMode = 1
OnvifHttpport = 80

[Vehicle]
enable = 0

[Pet]
enable = 0

[AIAudio]
GB = 0

[Mydlink]
pin_code = NDkwMDI3
register_st = 0
oob_changed = 0
oob_switch = 0
md_sensitivity = 70
md_mask = FFFFFFFFFFFFFFFFFFFFFFFFF
pirvacy_mode = 0
light_status = 1
flicker = 0
mdzone0_x = 0
mdzone0_y = 0
mdzone1_x = 40
mdzone1_y = 0
mdzone2_x = 40
mdzone2_y = 20
mdzone3_x = 0
mdzone3_y = 20
alarm_type = 1
alarm_time = 60
odzone0_x = 0
odzone0_y = 0
odzone1_x = 544
odzone1_y = 0
odzone2_x = 544
odzone2_y = 320
odzone3_x = 0
odzone3_y = 320
alarm_en = 0

[PIR]
pir_1_on_off = 0
pir_2_on_off = 0
pir_3_on_off = 0
pir_sen_level = 0
pir_sen_percentage = 0

[LIGHT]
Enable = 0
Lightness = 50
Duration = 60

I even edited onvif section to add a new password and a new user, same thing it prints the new user/pass in the console, but I can't login

OnvifPsw_0 = admin
OnvifPsw_1 = admin
OnvifLevel_0 = administrator
OnvifLevel_1 = administrator

Any suggestions ?