Take control of your Buffalo Linkstation NAS
I finally bought a NAS for all of my super-important stuff. It became a Buffalo Linkstation LS200, most because of the price ($300 for 4TB). It supports all of the standard protocols such as FTP, SAMBA, ATP and so on.
However, it would be really useful to use some sane protocols like sftp so you could use rsync for your backup scripts.
Bring a big coffee mug and let the hacking begin....
I knew that the NAS was based on the ARM architecture and supports a whole set of high level protocols, so one qualified guess is that there lives a little penguin in the box.
Lets start with download the latest firmware from the Buffalo webpage. When the firmware is unzipped we have these files:
marcus@tuxie:~/shared/buffalo\$ ls -al total 780176 drwxr-xr-x 4 marcus marcus 4096 Jun 13 00:06 . drwxr-xr-x 18 marcus marcus 4096 Jun 12 23:27 .. -rw-r--r-- 1 marcus marcus 190409979 Jun 13 00:06 hddrootfs.img drwxr-xr-x 2 marcus marcus 4096 Apr 8 13:25 img -rw-r--r-- 1 marcus marcus 12602325 Apr 1 15:25 initrd.img -rw-r--r-- 1 marcus marcus 656 Apr 1 15:25 linkstation_version.ini -rw-r--r-- 1 marcus marcus 198 Apr 1 15:25 linkstation_version.txt -rw-r--r-- 1 marcus marcus 205568610 Jun 12 23:13 LS200_series_FW_1.44.zip -rw-r--r-- 1 marcus marcus 350104 Apr 1 15:25 LSUpdater.exe -rw-r--r-- 1 marcus marcus 327 Apr 1 15:25 LSUpdater.ini -rw-r--r-- 1 marcus marcus 674181 Apr 1 15:25 u-boot.img -rw-r--r-- 1 marcus marcus 2861933 Apr 1 15:25 uImage.img -rw-r--r-- 1 marcus marcus 4880 Apr 8 13:23 update.html
Ok, u-boot.img, uImage.img, initrd.img and hddrootfs.img tells us that I have a black little penguin cage in front of me. First of all, find out what kind of file these *.img files really are.:
marcus@tuxie:~/shared/buffalo$ file ./hddrootfs.img ./hddrootfs.img: Zip archive data, at least v2.0 to extract
Really? It's just an zip-file. Lets extract it then.:
marcus@tuxie:~/shared/buffalo$ unzip hddrootfs.img Archive: hddrootfs.img [hddrootfs.img] hddrootfs.buffalo.updated password:
Of course, it's protected with a password. I will let my old friend John the Ripper take a look at it (I guess I had a great luck, the brute force attack only took 2.5 hours).
The password for the file is: aAhvlM1Yp7_2VSm6BhgkmTOrCN1JyE0C5Q6cB3oBB
marcus@tuxie:~/shared/buffalo$ unzip hddrootfs.img Archive: hddrootfs.img [hddrootfs.img] hddrootfs.buffalo.updated password: inflating: hddrootfs.buffalo.updated
Terrific. We got a hddrootfs.buffalo.updated file. What is it anyway?:
marcus@tuxie:~/shared/buffalo$ file hddrootfs.buffalo.updated hddrootfs.buffalo.updated: gzip compressed data, was "rootfs.tar", from Unix, last modified: Tue Apr 1 08:24:05 2014, max compression
It's just a gzip compressed tar archive, couldn't be better!
Extract it:
marcus@tuxie:~/shared/buffalo$ mkdir rootfs marcus@tuxie:~/shared/buffalo$ tar -xz --numeric-owner -f hddrootfs.buffalo.updated -C ./rootfs/ marcus@tuxie:~/shared/buffalo$ ls -1l rootfs/ total 80 drwxr-xr-x 2 root root 4096 Apr 1 08:23 bin -rwxr-xr-x 1 root root 1140 Feb 3 07:51 chroot.sh drwxr-xr-x 2 root root 4096 Apr 1 08:23 debugtool drwxr-xr-x 5 root root 4096 Apr 1 08:23 dev drwxr-xr-x 33 root root 4096 Jun 12 23:17 etc drwxr-xr-x 4 root root 4096 Apr 1 08:23 home drwxr-xr-x 9 root root 4096 Apr 1 08:23 lib drwxr-xr-x 3 root root 4096 Feb 3 07:51 mnt drwxr-xr-x 2 root root 4096 Apr 1 07:35 opt -rwxr-xr-x 1 root root 2741 Feb 3 07:51 prepare.sh drwxr-xr-x 2 root root 4096 Apr 1 07:35 proc drwxr-xr-x 3 root root 4096 Apr 1 08:23 root drwxr-xr-x 3 root root 4096 Apr 1 08:22 run drwxr-xr-x 2 root root 4096 Apr 1 08:23 sbin drwxr-xr-x 2 root root 4096 Apr 1 07:35 sys -rwxr-xr-x 1 root root 3751 Feb 3 07:51 test.sh drwxrwxrwt 3 root root 4096 Apr 1 08:23 tmp drwxr-xr-x 11 root root 4096 Apr 1 08:23 usr drwxr-xr-x 9 root root 4096 Apr 1 08:22 var drwxrwxrwx 6 root root 4096 Apr 1 07:53 www
Here we go!
Modify the root filesystem
First of all, I really would like to have SSH access to the box, and I found that there is a SSH daemon in here (/usr/bin/sshd), but why is it not activated?
Take a look in one of the scripts that seems to be related to ssh:
marcus@tuxie:~/shared/buffalo/rootfs$ head -n 20 etc/init.d/sshd.sh #!/bin/sh [ -f /etc/nas_feature ] && . /etc/nas_feature SSHD_DSA=/etc/ssh_host_dsa_key SSHD_RSA=/etc/ssh_host_rsa_key SSHD_KEY=/etc/ssh_host_key SSHD=`which sshd` if [ "${SSHD}" = "" -o ! -x ${SSHD} ] ; then echo "sshd is not supported on this platform!!!" fi if [ "${SUPPORT_SFTP}" = "0" ] ; then echo "Not support sftp on this model." > /dev/console exit 0 fi umask 000
What about the second if-statement? SUPPORT_SFTP? And what is the /etc/nas_feature file?
It does not exist in the package. Is it auto generated at boot?
Anyway, I remove the second statement, it seems evil.
So, if this starts up the ssh daemon, we would like to login as root, uncomment PermitRootLogin in sshd_config:
marcus@tuxie:~/shared/buffalo/rootfs$ sed -i 's/#PermitRootLogin/ PermitRootLogin/' etc/sshd_config
Then copy your public rsa-key to /root/.ssh/authorized_keys. If you don't have a key, generate it with:
marcus@tuxie:~/shared/buffalo/rootfs$ ssh-keygen
Copy the key to target:
marcus@tuxie:~/shared/buffalo/rootfs$ mkdir ./root/.ssh marcus@tuxie:~/shared/buffalo/rootfs$ cat ~/.ssh/id_rsa.pub > ./root/.ssh/authorized_keys
This will let you to login without give any password.
Lets try to re-pack the whole thing.:
marcus@tuxie:~/shared/buffalo/rootfs$ mv ../hddrootfs.buffalo.updated{,.old} marcus@tuxie:~/shared/buffalo/rootfs$ tar -czf ../hddrootfs.buffalo.updated * marcus@tuxie:~/shared/buffalo/rootfs$ cd .. marcus@tuxie:~/shared/buffalo$ zip -e hddrootfs.img hddrootfs.buffalo.updated
I encrypt the file with the same password as before, I dare not think about what happens if I don't.
Time to update firmware
I execute the LSUpdater.exe from a virtual Windows machine and hold my thumbs... The update process takes about 8 minutes and is a real pain, would it brick my NAS..?
After a while the power LED is indicating that the NAS is up and running. Wow.
Quick! Do a portscan!:
marcus@tuxie:~/shared/buffalo$ sudo nmap -sS 10.0.0.4 [sudo] password for marcus: Starting Nmap 5.21 ( http://nmap.org ) at 2014-06-13 11:59 CEST Nmap scan report for nas (10.0.0.4) Host is up (0.00049s latency). Not shown: 990 closed ports PORT STATE SERVICE 21/tcp open ftp 22/tcp open ssh 80/tcp open http 139/tcp open netbios-ssn 443/tcp open https 445/tcp open microsoft-ds 548/tcp open afp 873/tcp open rsync 8873/tcp open unknown 22939/tcp open unknown MAC Address: DC:FB:02:EB:06:A8 (Unknown) Nmap done: 1 IP address (1 host up) scanned in 0.27 seconds
And there it's! The SSH daemon is running on port 22.:
marcus@tuxie:~$ ssh admin@10.0.0.4 admin@10.0.0.4's password: [admin@LS220D6A8 ~]$ ls / bin/ debugtool/ home/ mnt/ proc/ sbin/ tmp/ www/ boot/ dev/ lib/ opt/ root/ sys/ usr/ chroot.sh* etc/ lost+found/ prepare.sh* run/ test.sh* var/ [admin@LS220D6A8 ~]$
It's just beautiful!
Wait, what about the /etc/nas_features file?
[admin@LS220D6A8 ~]$ cat /etc/nas_feature DEFAULT_LANG=english DEFAULT_CODEPAGE=CP437 REGION_CODE=EU PRODUCT_CAPACITY="040" PID=0x0000300D SERIES_NAME="LinkStation" PRODUCT_SERIES="LS200" PRODUCT_NAME="LS220D(SANJO)" SUPPORT_NTFS_WRITE=on NTFS_DRIVER="tuxera" SUPPORT_DIRECT_COPY=on SUPPORT_RAID=on SUPPORT_RAID_DEGRADE=off SUPPORT_FAN=on SUPPORT_AUTOIP=on SUPPORT_NEW_DISK_AUTO_REBUILD=off SUPPORT_2STEP_INSPECTION=off SUPPORT_RESYNC_DELAY=off SUPPORT_PRINTER_SERVER=on SUPPORT_ITUNES_SERVER=on SUPPORT_DLNA_SERVER=on SUPPORT_NAS_FIREWALL=off SUPPORT_IPV6=off SUPPORT_DHCPS=off SUPPORT_UPNP=off SUPPORT_SLIDE_POWER_SWITCH=on SUPPORT_BITTORRENT=on BITTORRENT_CLIENT="transmission" SUPPORT_USER_QUOTA=on SUPPORT_GROUP_QUOTA=on SUPPORT_ACL=on SUPPORT_TIME_MACHINE=on SUPPORT_SLEEP_TIMER=on SUPPORT_AD_NT_DOMAIN=on SUPPORT_RAID0=1 SUPPORT_RAID1=1 SUPPORT_RAID5=0 SUPPORT_RAID6=0 SUPPORT_RAID10=0 SUPPORT_RAID50=0 SUPPORT_RAID60=0 SUPPORT_RAID51=0 SUPPORT_RAID61=0 SUPPORT_NORAID=0 SUPPORT_RAID_REBUILD=1 SUPPORT_AUTH_EXTERNAL=1 SUPPORT_SAMBA_DFS=0 SUPPORT_LINKDEREC_ANALOG=0 SUPPORT_LINKDEREC_DIGITAL=0 SUPPORT_WEBAXS=1 SUPPORT_UPS_SERIAL=0 SUPPORT_UPS_USB=0 SUPPORT_UPS_RECOVER=0 SUPPORT_NUT=0 SUPPORT_SYSLOG_FORWARD=0 SUPPORT_SYSLOG_DOWNLOAD=0 SUPPORT_SHUTDOWN_FROMWEB=0 SUPPORT_REBOOT_FROMWEB=1 SUPPORT_IMHERE=0 SUPPORT_POWER_INTERLOCK=1 SUPPORT_SMTP_AUTH=1 NEED_MICONMON=off ROOTFS_FS=ext3 USERLAND_FS=xfs NASFEAT_VM_WRITEBACK=default NASFEAT_VM_EXPIRE=default MAX_DISK_NUM=2 MAX_USBDISK_NUM=1 MAX_ARRAY_NUM=1 DEV_BOOT=md0 DEV_ROOTFS1=md1 DEV_SWAP1=md2 SDK_VERSION=2 DEVICE_NETWORK_PRIMARY=eth1 DEVICE_NETWORK_SECONDARY= DEVICE_NETWORK_NUM=1 DEVICE_HDD1_LINK=disk1_6 DEVICE_HDD2_LINK=disk2_6 DEVICE_HDD3_LINK=disk3_6 DEVICE_HDD4_LINK=disk4_6 DEVICE_HDD5_LINK=disk5_6 DEVICE_HDD6_LINK=disk6_6 DEVICE_HDD7_LINK=disk7_6 DEVICE_HDD8_LINK=disk8_6 DEVICE_HDD_BASE_EDP=md100 DEVICE_HDD1_EDP=md101 DEVICE_HDD2_EDP=md102 DEVICE_HDD3_EDP=md103 DEVICE_HDD4_EDP=md104 DEVICE_HDD5_EDP=md105 DEVICE_HDD6_EDP=md106 DEVICE_HDD7_EDP=md107 DEVICE_HDD8_EDP=md108 DEVICE_MD1_REAL=md10 DEVICE_MD2_REAL=md20 DEVICE_MD3_REAL=md30 DEVICE_MD4_REAL=md40 DEVICE_USB1_LINK=usbdisk1_1 DEVICE_USB2_LINK=usbdisk2_1 DEVICE_USB3_LINK=usbdisk1_5 DEVICE_USB4_LINK=usbdisk2_5 MOUNT_GLOBAL=/mnt MOUNT_LVM_BASE=/mnt/lvm MOUNT_HDD1=/mnt/disk1 MOUNT_HDD2=/mnt/disk2 MOUNT_HDD3=/mnt/disk3 MOUNT_HDD4=/mnt/disk4 MOUNT_HDD5=/mnt/disk5 MOUNT_HDD6=/mnt/disk6 MOUNT_HDD7=/mnt/disk7 MOUNT_HDD8=/mnt/disk8 MOUNT_ARRAY1=/mnt/array1 MOUNT_ARRAY2=/mnt/array2 MOUNT_ARRAY3=/mnt/array3 MOUNT_ARRAY4=/mnt/array4 MOUNT_USB1=/mnt/usbdisk1 MOUNT_USB2=/mnt/usbdisk2 MOUNT_USB3=/mnt/usbdisk3 MOUNT_USB4=/mnt/usbdisk4 MOUNT_USB5=/mnt/usbdisk5 MOUNT_MC_BASE=/mnt/mediacartridge SUPPORT_MC_VER=1 SUPPORT_INTERNAL_DISK_APPEND=0 STORAGE_TYPE=HDD BODY_COLOR=NORMAL SUPPORT_MICON=0 SUPPORT_LCD=0 SUPPORT_USER_QUOTA_SOFT=0 SUPPORT_GROUP_QUOTA_SOFT=0 SUPPORT_NFS=0 SUPPORT_LVM=0 SUPPORT_OFFLINEFILE=0 SUPPORT_HIDDEN_SHARE=0 SUPPORT_HOT_SWAP=0 SUPPORT_LCD_LED=0 SUPPORT_ALERT=0 SUPPORT_PORT_TRUNKING=0 SUPPORT_REPLICATION=0 SUPPORT_USER_GROUP_CSV=0 SUPPORT_SFTP=0 SUPPORT_SERVICE_MAPPING=0 SUPPORT_SSLKEY_IMPORT=1 SUPPORT_SLEEPTIMER_DATE=0 SUPPORT_TERA_SEARCH=0 SUPPORT_SECURE_BOOT=0 SUPPORT_PACKAGE_UPDATE=0 SUPPORT_HDD_SPINDOWN=0 SUPPORT_DISK_ENCRYPT=0 SUPPORT_FTPS=1 SUPPORT_CLEANUP_ALL_TRASHBOX=0 SUPPORT_WAKEUP_BY_REBOOT=1 SUPPORT_DTCP_IP=0 SUPPORT_MYSQL=0 SUPPORT_APACHE=0 SUPPORT_PHP=0 SUPPORT_UPS_STANDBY=0 SUPPORT_HIDDEN_RAID_MENU=0 SUPPORT_ISCSI=0 SUPPORT_ISCSI_TYPE= DEFAULT_WORKINGMODE= MAX_LVM_VOLUME_NUM=0 MAX_ISCSI_VOLUME_NUM=0 INTERNAL_SCSI_TYPE=multi-host SUPPORT_ELIMINATE_ADLIMIT= USB_TREE_TYPE= SUPPORT_WOL=0 WOL_TYPE= SUPPORT_HARDLINK_BACKUP=0 SUPPORT_SNMP=0 SUPPORT_EDP=1 SUPPORT_POCKETU=0 SUPPORT_MC=0 SUPPORT_FOFB=0 SUPPORT_EDP_PLUS=0 SUPPORT_INIT_SW=1 SUPPORT_SQUEEZEBOX=0 SUPPORT_OL_UPDATE=1 SUPPORT_AMAZONS3=0 SUPPORT_SURVEILLANCE=0 SUPPORT_WAFS=0 SUPPORT_SUGARSYNC=0 SUPPORT_INTERNAL_DISK_REMOVE=1 SUPPORT_SETTING_RECOVERY_USB=0 SUPPORT_PASSWORD_RECOVERY_USB=0 SUPPORT_AV= SUPPORT_TUNEUP_RAID=on SUPPORT_FLICKRFS=0 SUPPORT_WOL_INT=1 TUNE=0 SUPPORT_EDP_PLUS=0 SUPPORT_SXUPTP=0 SUPPORT_SQUEEZEBOX=0 SUPPORT_EYEFI=0 SUPPORT_OL_UPDATE=1 SUPPORT_INIT_SW=1 SUPPORT_USB=1 SUPPORT_WAFS=0 SUPPORT_INFO_LED=1 SUPPORT_ALARM_LED=1 POWER_SWITCH_TYPE=none SUPPORT_FUNC_SW=1 DLNA_SERVER="twonky" SUPPORT_TRANSCODER=0 SUPPORT_LAYOUT_SWITCH=1 SUPPORT_UTILITY_DOWNLOAD=1 SUPPORT_BT_CLOUD=0 DEFAULT_VALUE_DLNA=1 DEFAULT_VALUE_BT_CLOUD=0 SUPPORT_EXCLUSION_LED_POWER_INFO_ERROR=1 DEFAULT_DLNA_SERVICE=off SUPPORT_MOBILE_WEBUI=1 SUPPORT_SHUTDOWN_DEPEND_ON_SW=1 SUPPORT_SPARE_DISK=0
It seems that the files is generated. It also has the SUPPORT_SFTP config that we saw in sshd.sh.
What about the kernel
In the current vanilla kernel, there is devicetrees that seems to be for the Buffalo linkstation.:
marcus@tuxie:~/marcus/linux/linux$ grep -i buffalo arch/arm/boot/dts/*.dts arch/arm/boot/dts/kirkwood-lschlv2.dts: model = "Buffalo Linkstation LS-CHLv2"; arch/arm/boot/dts/kirkwood-lschlv2.dts: compatible = "buffalo,lschlv2", "buffalo,lsxl", "marvell,kirkwood-88f6281", "marvell,kirkwood"; arch/arm/boot/dts/kirkwood-lsxhl.dts: model = "Buffalo Linkstation LS-XHL"; arch/arm/boot/dts/kirkwood-lsxhl.dts: compatible = "buffalo,lsxhl", "buffalo,lsxl", "marvell,kirkwood-88f6281", "marvell,kirkwood";
The device tree seems to match the current CPU:
[admin@LS220D6A8 ~]$ cat /proc/cpuinfo Processor : Marvell PJ4Bv7 Processor rev 1 (v7l) BogoMIPS : 795.44 Features : swp half thumb fastmult vfp edsp vfpv3 vfpv3d16 tls CPU implementer : 0x56 CPU architecture: 7 CPU variant : 0x1 CPU part : 0x581 CPU revision : 1 Hardware : Marvell Armada-370 Revision : 0000 Serial : 0000000000000000
Also, the kernel is not tainted indicating that there is no out-of-tree modules.:
[admin@LS220D6A8 ~]$ cat /proc/sys/kernel/tainted 0
It could therefor be possible to compile a custom kernel with support for more USB-devices that may be plugged into the NAS.
Other tips
The LSUpdater.exe will refuse to update if the same version of software is already on the target. This means that you cannot upload the same firmware again... unless you change the version.
Together with the uploader application, there is a linkstation_version.ini file that contains information about each of the *.img.
The first thing I tried was just to increase the VERSION by one. This makes the LSUpdater.exe move a little forward, It stops complain about the same version, instead it complains about that this firmware is already on the target.
However, I needed to change the timestamp of each binary (increased the day by one), then it updates the firmware without any problem.
marcus@tuxie:~/shared/buffalo$ cat linkstation_version.ini [COMMON] VERSION=1.44-0.36 BOOT=0.20 KERNEL=2014/04/01 14:33:46 INITRD=2014/04/01 14:35:10 ROOTFS=2014/04/01 15:23:41 FILE_BOOT = u-boot.img FILE_KERNEL = uImage.img FILE_INITRD = initrd.img FILE_ROOTFS = hddrootfs.img [TARGET_INFO1] PID=0x0000001D FILE_KERNEL=uImage.img KERNEL=2014/04/01 14:33:46 FILE_BOOT_APPLY=u-boot.img BOOT=0.20 BOOT_UP_CMD="" [TARGET_INFO2] PID=0x0000300D FILE_KERNEL=uImage.img KERNEL=2014/04/01 14:33:46 FILE_BOOT_APPLY=u-boot.img BOOT=0.20 BOOT_UP_CMD="" [TARGET_INFO3] PID=0x0000300E FILE_KERNEL=uImage.img KERNEL=2014/04/01 14:33:46 FILE_BOOT_APPLY=u-boot.img BOOT=0.20 BOOT_UP_CMD=""