Performing SAST on Dlink DIR-1253 Firmware (White version)


The second revelation, they have been released official support into this devices! but, its different. This firmware incompatible with DLINK DIR-1253 Black Version.

Avatar

Zuhri

  |  5 min reads

Introduction #

“Finally” I said, my router Dlink DIR-1253 was support officially by dlink here it is! support.dlink.com but I notice something weird, file size are really big its about 23MB.

┌─[root@sv32][~/re]
└──╼ # ls -lah DIR-1253_V1.0.1.250923.142435_official.bin
-rw-r--r-- 1 root root 23M Nov 27 10:04 DIR-1253_V1.0.1.250923.142435_official.bin

My router SPI it just 8MB maybe, so rather than put this update to my router I decide doing analysis (SAST) again. Here what I found!

Methodology #

Analysis using Binwalk #

┌─[root@sv32][~/re]
└──╼ # binwalk DIR-1253_V1.0.1.250923.142435_official.bin

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
480           0x1E0           uImage header, header size: 64 bytes, header CRC: 0xF5B29EE6, created: 2025-09-23 06:41:59, image size: 2304923 bytes, Data Address: 0x40008000, Entry Point: 0x40008000, data CRC: 0x4E508451, OS: Linux, CPU: ARM, image type: OS Kernel Image, compression type: none, image name: "Linux Kernel Image"
544           0x220           Linux kernel ARM boot executable zImage (little-endian)
16079         0x3ECF          LZMA compressed data, properties: 0x5D, dictionary size: 67108864 bytes, uncompressed size: -1 bytes
2297560       0x230ED8        Flattened device tree, size: 7907 bytes, version: 17
2305472       0x232DC0        JFFS2 filesystem, little endian

Most interesting part of these partition is are just JFFS filesystem at the bottom. Then lets use binwalk to extra those in automatically.

┌──[root@sv32][~/re]
└──╼ # binwalk --run-as=root -Me  DIR-1253_V1.0.1.250923.142435_official.bin

Scan Time:     2025-11-27 10:20:01
Target File:   /root/re/DIR-1253_V1.0.1.250923.142435_official.bin
MD5 Checksum:  cd50babdb261bbd2b535424062c2c40b
Signatures:    411
---SNIP---

This is extracted firmware binwalk output

┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # file *;ls -lah
232DC0.jffs2:    Linux jffs2 filesystem data little endian
3ECF:            OpenPGP Public Key
3ECF.7z:         LZMA compressed data, streamed
_3ECF.extracted: directory
total 50M
drwxr-xr-x 3 root root 4.0K Nov 27 10:20 .
drwxr-xr-x 3 root root 4.0K Nov 27 10:20 ..
-rw-r--r-- 1 root root  21M Nov 27 10:20 232DC0.jffs2
-rw-r--r-- 1 root root 5.9M Nov 27 10:20 3ECF
-rw-r--r-- 1 root root  23M Nov 27 10:20 3ECF.7z
drwxr-xr-x 2 root root 4.0K Nov 27 10:20 _3ECF.extracted

Jefferson to extract jffs2 #

We need to download Jefferson first by using this command.

┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # pip install --user jefferson --break-system-packages

Then extract 232DC0.jffs2 using this command.

┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # jefferson 232DC0.jffs2 -d rootfs
┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # ls -lh rootfs/
total 92K
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 bin
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 ctcap
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 db_excp
drwxr-xr-x  4 root root 4.0K Nov 27 10:40 dev
drwxr-xr-x 12 root root 4.0K Nov 27 10:56 etc
drwxr-xr-x  4 root root 4.0K Nov 27 10:40 home
-rwxr-xr-x  1 root root   66 Nov 27 10:40 init
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 ipks
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 kmodule
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 lib
lrwxrwxrwx  1 root root   11 Nov 27 10:40 linuxrc -> bin/busybox
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 mnt
drwxr-xr-x  3 root root 4.0K Nov 27 10:40 opt
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 proc
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 root
drwxr-xr-x  4 root root 4.0K Nov 27 10:40 run
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 sbin
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 sys
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 tagparam
lrwxrwxrwx  1 root root    7 Nov 27 10:40 temp -> var/tmp
lrwxrwxrwx  1 root root    7 Nov 27 10:40 tmp -> var/tmp
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 userconfig
drwxr-xr-x  8 root root 4.0K Nov 27 10:40 usr
drwxr-xr-x  5 root root 4.0K Nov 27 10:40 var
drwxr-xr-x  2 root root 4.0K Nov 27 10:40 wlan
drwxr-xr-x  7 root root 4.0K Nov 27 10:40 www

Hardcoded Credential #

they have two users, and its.

  • root:root
  • tmadmin:password
┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # cat rootfs/etc/shadow | grep -v "\!\!"
root:$1$qGmxLn8v$yTzaaXdb6.6QLLgS0Euz.1:12571:0:99999:7:::
tmadmin:$1$W9mpTzNH$GCFTW1Zoa6LPPOv3T1jDO/:0:0:99999:7:::

┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # john rootfs/etc/shadow
Warning: detected hash type "md5crypt", but the string is also recognized as "md5crypt-long"
Use the "--format=md5crypt-long" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 2 password hashes with 2 different salts (md5crypt, crypt(3) $1$ (and variants) [MD5 128/128 ASIMD 4x2])
Will run 4 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
root             (root)
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
password         (tmadmin)
2g 0:00:00:00 DONE 2/3 (2025-11-27 10:57) 5.263g/s 7847p/s 7850c/s 7850C/s 123456..john
Use the "--show" option to display all of the cracked passwords reliably
Session completed.

┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted/rootfs/etc]
└──╼ # john rootfs/etc/shadow --show
root:root:12571:0:99999:7:::
tmadmin:password:0:0:99999:7:::

2 password hashes cracked, 0 left

fstab #

┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # cat rootfs/etc/fstab
# <file system> <mount point>   <type>  <options>    <dump> <pass>

# The syntax of busybox's fstab entry's a little different than traditional
# mount, and doesn't work with the usual 'rootfs / rootfs rw 0 0' entry.
# Actually, it's not needed unless you're mounting from a non-nfs device,
# like a hard disk.  In that case, you probably need something like the
# following:

# /dev/hda1       /               ext3    rw           1      1

proc            /proc           proc    defaults     0      0
sysfs           /sys            sysfs   defaults     0      0
#devpts          /dev/pts        devpts  defaults     0      0
#tmpfs           /var            tmpfs   rw     0      0

Openwrt pkgs (opkg) and its ARM devices #

┌─[root@sv32][~/re/_DIR-1253_V1.0.1.250923.142435_official.bin.extracted]
└──╼ # file rootfs/bin/opkg
opkg: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 4.1.0, stripped

This is the most interesting part I notice, they own openwrt pkg opkg, but as you can see the architecture is differ they using ARM cpu within 32-bit executable. That why file size are big, this firmware are absolutly uncompatible with the previous one (Black version).

Command injection prevention #

They own regex security prevention at /www/cgi-bin/{upgrade,backup}.

---SNIP---
## urldecode and handle command injection
urldecode()
{
        str=$1
        len1=0
        len2=${#str}
        while [ "$len1" -ne "$len2" ]; do
                str=${str//[\"\'\`|\\<>@?*~!();,.]/}
                str=${str//%/\\x}
                str=${str//+/ }
                str=$(printf "$str")
                len1=$len2
                len2=${#str}
        done
        echo "$str"
}
---SNIP---

Conclusion #

So the conclusion is, this firmware are not compatible with DLINK DIR-1253 Black Version, because it use different architecture, and if you think both are equal? I said no, this is not! even they said “DIR-1253”.