CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/lib/msf/core/auxiliary/login.rb
Views: 1904
# -*- coding: binary -*-12module Msf34###5#6# This module exposes methods that may be useful to exploits that deal with7# servers that require authentication via /bin/login8#9###10module Auxiliary::Login1112NULL = "\000"13CR = "\r"14LF = "\n"15EOL = CR + LF1617#18# Creates an instance of a login negotiation module.19#20def initialize(info = {})21super2223create_login_ivars24end2526def create_login_ivars27# Appended to by each read and gets reset after each send. Doing it28# this way lets us deal with partial reads in the middle of expect29# strings, e.g., the first recv returns "Pa" and the second returns30# "ssword: "31@recvd = ''32@trace = ''3334#35# Some of these regexes borrowed from NeXpose, others added from datasets36#37@login_regex = /(?:log[io]n( name|)|user( ?name|id|))\s*\:/i38@password_regex = /(?:password|passwd)\s*\:/i39@false_failure_regex = /(?:(^\s*last)\ login *\:|allows only\ .*\ Telnet\ Client\ License)/i40@failure_regex = /(?:41Incorrect | Unknown | Fail | Invalid |42Login | Password | Passwd | Username |43Unable | Error | Denied | Reject |44Refuse | Close | Closing | %\ Bad |45Sorry |46^http | html |47Not\ on\ system\ console |48Enter\ username\ and\ password |49Auto\ Apply\ On |50YOU\ LOGGED\ IN\ USING\ ALL\ UPPERCASE\ CHARACTERS|51\n\*$ |52(Login ?|User ?)(name|): |53^\s*\<[a-f0-9]+\>\s*$ |54^\s*220.*FTP|55not\ allowed\ to\ log\ in56)/mix5758@waiting_regex = /(?:59.*please\ wait.* |60.*one\ minute.*61)/mix6263@busy_regex = /(?:64Another\ telnet\ session\ is\ in\ progress | Disconnecting\.\.\.65)/mix6667@success_regex = /(?:68list\ of\ built-in |69sh.*[\#\$]\s*$ |70\[\/\]\s*$ |71or\ the\ MENU\ system |72Password\ is\ not\ set |73logging\ in\ as\ visitor |74Login\ successful75)/mix76end7778#79# Appends to the @recvd buffer which is used to tell us whether we're at a80# login prompt, a password prompt, or a working shell.81#82def recv(fd=self.sock, timeout=10)8384data = ''8586begin87data = fd.get_once(-1, timeout)88return nil if not data or data.length == 08990# combine EOL into "\n"91data.gsub!(/#{EOL}/no, "\n")9293@trace << data94@recvd << data95fd.flush9697rescue ::EOFError, ::Errno::EPIPE98end99100data101end102103def login_prompt?104return true if @recvd =~ @login_regex105return false106end107108def command_echo?(cmd)109recvn = @recvd.gsub(/^(\s*#{cmd}\r?\n\s*|\s*\*+\s*)/, '')110if(recvn != @recvd)111@recvd = recvn112return true113end114false115end116117def waiting_message?118recvn = @recvd.gsub(@waiting_regex, '')119if(recvn != @recvd)120@recvd = recvn.strip121return true122end123false124end125126def busy_message?127recvn = @recvd.gsub(@busy_regex, '')128if(recvn != @recvd)129@recvd = recvn.strip130return true131end132false133end134135def password_prompt?(username=nil)136return true if(@recvd =~ @password_regex)137if username138return true if !(username.empty?) and @recvd.to_s.include?("#{username}'s")139end140return false141end142143def login_failed?144# Naively, failure means matching the failure regex.145#146# However, this leads to problems with false positives in the case of147# "login:" because unix systems commonly show "Last login: Sat Jan 3148# 20:22:52" upon successful login, so check against a false-positive149# regex, also.150#151152# Empty strings should not count153if @recvd.strip.length == 0154return true155end156157# If we have not seen a newline, this is likely an echo'd prompt158if ! @recvd.index("\n")159return true160end161162# We do have a set of highly-accurate success patterns163if (@recvd =~ @success_regex)164return false165end166167if @recvd =~ @failure_regex168if @recvd !~ @false_failure_regex169return true170end171end172return false173end174175def login_succeeded?176# Much easier to test for failure than success because a few key words177# mean failure whereas all kinds of crap is used for success, much of178# which also shows up in failure messages.179return (not login_failed?)180end181182#183# This method logs in as the supplied user by transmitting the username184#185def send_user(user, nsock = self.sock)186got_prompt = wait_for(@login_regex)187if not got_prompt188print_error("#{rhost} - Something is wrong, didn't get a login prompt")189end190return send_recv("#{user}\r\n")191end192193#194# This method completes user authentication by sending the supplied password195#196def send_pass(pass, nsock = self.sock)197got_prompt = wait_for(@password_regex)198if not got_prompt199print_error("#{rhost} - Something is wrong, didn't get a password prompt")200end201return send_recv("#{pass}\r\n")202end203204def send_recv(msg, nsock = self.sock)205raw_send(msg, nsock)206recv_all(nsock)207return @recvd208end209210def recv_all(nsock = self.sock, timeout = 10)211# Make sure we read something in212wait_for(/./)213end214215#216# This method transmits a telnet command and does not wait for a response217#218# Resets the @recvd buffer219#220def raw_send(cmd, nsock = self.sock)221@recvd = ''222@trace << cmd223nsock.put(cmd)224end225226#227# Wait for the supplied string (or Regexp) to show up on the socket, or a228# timeout229#230def wait_for(expect, nsock = self.sock)231if expect.kind_of? Regexp232regx = expect233else234regx = /#{Regexp.quote(expect)}/i235end236return true if @recvd =~ regx237238resp = ''239while (resp and not @recvd =~ regx)240resp = recv(nsock)241end242243return (@recvd =~ regx)244end245246end247248end249250251