Show version and haiku, but not only: looking for all hidden Junos commands

    Hello!

    This article is about the hidden commands of the Junos operating system. Those who worked with Juniper equipment running the Junos OS (this includes the MX, SRX, EX, QFX, T, J series, and many others) probably know that in addition to the “official” (documented) commands in the system there are undocumented ones. Their peculiarity is that they are not visible in the command line interface by contextual help (this is when you enter a question mark) and auto-completion does not work for them, that is, you need to know the command and enter it completely (all letters). Apparently, the most famous (and most useless) of these teams is show version and haiku, which gives out a "Japanese" three-poem about the life of network engineers.

    There are actually many hidden teams. Vendor does not give their complete list anywhere, but, for example, on the official Juniper forum there is a sticky topic with a rather large set. So the manufacturer does not object to our use of such commands, they simply do not give any guarantee - it can work, or it can put your equipment.

    In this article I will talk about how you can get a list of all hidden Junos operating mode commands, within some initial branch. The method is based on a rather simple observation, but by googling I could not find evidence that the question was posed in this form before. An example Python script is included.



    Idea


    The basic idea of ​​the approach is very simple, but to understand it, it’s still good to have access to the CLI of any Junos device.

    Consider, for example, the “show version” command. If we enter “show version a” (at the end - we always press Enter), then the output of the command is like this:
    lab@jsrxA-1> show version a
                               ^
    syntax error.
    

    And if "show version c", then
    lab@jsrxA-1> show version c   
                              ^
    syntax error, expecting .
    

    In the first case, there is a hidden extension (and haiku), in the second - no. As you can see, the response of the CLI in the presence of a hidden continuation differs in two aspects:
    • "Syntax error." Instead of "syntax error, expecting ‹command›."
    • a hat (aka circumflex) stands under the next line position.

    Accordingly, sorting the letters one after another (although it’s better to automate them manually), we can find the hidden commands - Junos himself tells them, although not as explicitly as with ordinary commands!

    Preliminary notes


    Before writing a script, I must warn readers that hidden commands were hidden by the developer for a reason. Some of them may disrupt the device, damage the file system, etc. Therefore, they, even one at a time, should be used with great care. In our case, when a search is done by brute force, this warning is raised to such an extent that in no case should you run such a script on user-processing equipment. After all, we sort through all the commands, which may include file delete, request system zeroize, restart routing, and much more. So play only with pieces of iron that are not connected to the network, which are not a pity to kill, but rather with virtual SRX (aka Firefly Perimeter).

    It should also be clarified that although Junos has a very convenient and advanced XML-based API, it is not possible to use it for this task, since our approach to finding commands is based on the specifics of the CLI. Therefore, we will open a regular telnet session, give commands and parse text output.

    In this article I will limit myself to searching for operating mode commands. There is also a configuration, and it also has a lot of interesting things hidden (the same commit full). Search for hidden commands there can be carried out similarly.

    Algorithm


    So, starting with a specific command (commandStart in the script), we will go around all possible options for the commands, adding a character each time (from the alphabet array) and entering Enter. The output sent by Junos in response may be as follows:
    1. Swearing about “syntax error.” (And at the same time the hat indicates the presence of the continuation of the command) - a sign of the presence of a hidden command, iterate further, adding new characters.
    2. Swearing about "syntax error, expecting ‹command›." -
      here it is necessary to analyze the position of the cap. If it is on the current letter, as above in the “show version c” example, then we do not go further, there are no hidden commands.
      If she indicates the continuation of the command, as here:
      lab@jsrxA-1> show version and 
                                    ^
      syntax error, expecting .
      

      then in this case the team has a continuation and it is necessary to go further (the team here may be hidden or not, depending on the background).
    3. Just the output of the command, without swearing about syntax errors, but it is possible with swearing about ambiguous input, for example, like here:
      lab@jlab-Firefly-3> show chassis cluster i
                                                ^
      'i' is ambiguous.
      Possible completions:
        interfaces           Display chassis cluster interfaces
        ip-monitoring        Display IP monitoring related information
      

      In this case, the search must be continued, because further, a hidden command may be contained (in this case, show chassis cluster information).

    It is also necessary to take into account that the outputs of some commands may occupy several screens, which leads to the issuance of the invitation "--- (more) ---". In this case, just a helmet space.

    Script


    Actually, here it is (or on github ).
    Script (Python 3)
    import telnetlib
    import re
    HOST = "192.168.65.161"
    user = "lab"
    password = "lab123"
    commandStart = "show version "     # note space at the end
    alphabet = "abcdefghijklmnopqrstuvwxyz-1234567890."
    PAUSE = 3 
    def SearchCommands (cmd, on_hidden_now=False):
        for nChar in range(0, len(alphabet)):
            char = str(alphabet[nChar])
            tn.write(cmd.encode('ascii') + char.encode('ascii') + b"\n")
            totData=""
            finished = False
            while (not finished):
                inpData = tn.read_until(prompt.encode('ascii'), PAUSE)
                totData = totData + inpData.decode('ascii')
                if "---(more" in inpData.decode('ascii'): 
                    tn.write(b" ")
                else:
                    finished = True
            cmdNext = cmd + str(char)
            synt_error_exp_cmd = False
            synt_error_period = False
            if "syntax error, expecting ." in totData:
                synt_error_exp_cmd = True
            if "syntax error." in totData:
                synt_error_period = True
            if not (synt_error_exp_cmd or synt_error_period):  # normal output or ambiguity
                if on_hidden_now:
                    print("hidden command >> " + cmdNext)
                else:
                    SearchCommands(cmdNext, on_hidden_now) # i.e. False
            else:
                l = re.findall(' *\^', totData)
                lenToHat = len(l[len(l)-1])            
                if synt_error_period:                         
                    if lenToHat > lenPrompt + len(cmdNext):
                        SearchCommands(cmdNext, True)        # Hidden command in progress
                if synt_error_exp_cmd:
                    if (lenToHat == 2 + lenPrompt + len(cmdNext)): 
                        if on_hidden_now:
                            print("hidden command >> " + cmdNext + "  (incomplete)")
                        # else: print("Entering: " + cmdNext)
                        SearchCommands(cmdNext+" ", on_hidden_now)
                    if lenToHat > 2 + lenPrompt + len(cmdNext):  
                        SearchCommands(cmdNext, on_hidden_now)                            
    tn = telnetlib.Telnet(HOST)
    tn.read_until(b"login: ")
    tn.write(user.encode('ascii') + b"\n")
    tn.read_until(b"Password:")
    tn.write(password.encode('ascii') + b"\n")
    loginText = tn.read_until(b"> ").decode('ascii')
    prompt = re.search(".*@.*", loginText).group()
    print("Working with prompt = " + prompt)
    lenPrompt = len(prompt)
    SearchCommands(commandStart)
    


    Examples of work:
    Running for show version branch
    hidden command >> show version and (incomplete)
    hidden command >> show version and blame
    hidden command >> show version and haiku
    hidden command >> show version extensive
    hidden command >> show version forwarding-context
    hidden command >> show version invoke- on (incomplete)
    hidden command >> show version invoke-on a
    hidden command >> show version invoke-on o
    hidden command >> show version no-forwarding
    hidden command >> show version scc-dont-forward
    hidden command >> show version sdk

    Launch for the show chassis branch
    hidden command >> show chassis accurate-statistics
    hidden command >> show chassis beacon
    hidden command >> show chassis broadcom
    hidden command >> show chassis cfeb
    hidden command >> show chassis cip
    hidden command >> show chassis clocks
    hidden command >> show chassis cluster ethernet-switching (incomplete)
    hidden command >> show chassis cluster information
    hidden command >> show chassis cluster ip-monitoring (incomplete)
    hidden command >> show chassis craft-interface
    hidden command >> show chassis customer-id
    hidden command >> show chassis ethernet-switch
    hidden command >>show chassis fabric (incomplete)
    hidden command >> show chassis fchip
    hidden command >> show chassis feb
    hidden command >> show chassis fpc-feb-connectivity
    hidden command >> show chassis hsl (incomplete)
    hidden command >> show chassis hsr
    hidden command >> show chassis hss (incomplete)
    hidden command >> show chassis hst
    hidden command >> show chassis in-service-upgrade
    hidden command >> show chassis ioc-npc-connectivity
    hidden command >> show chassis lccs
    hidden command >> show chassis message-statistics (incomplete)
    hidden command >> show chassis message -statistics i
    hidden command >> show chassis network-services
    hidden command >> show chassis nonstop-upgrade
    hidden command >>show chassis power-budget-statistics
    hidden command >> show chassis psd
    hidden command >> show chassis redundancy (incomplete)
    hidden command >> show chassis redundant-power-system
    hidden command >> show chassis scb
    hidden command >> show chassis sfm
    hidden command >> show chassis sibs
    hidden command >> show chassis spmb
    hidden command >> show chassis ssb
    hidden command >> show chassis synchronization
    hidden command >> show chassis tfeb
    hidden command >> show chassis timers
    hidden command >> show chassis usb (incomplete)
    hidden command >> show chassis zones

    Launch for show security idp branch (on SRX240)
    hidden command >> show security idp active-policy
    hidden command >> show security idp application-ddos (incomplete)
    hidden command >> show security idp application-identification (incomplete)
    hidden command >> show security idp detector (incomplete)
    hidden command> > show security idp detector a
    hidden command >> show security idp detector c
    hidden command >> show security idp detector p
    hidden command >> show security idp ips-cache
    hidden command >> show security idp logical-system (incomplete)

    As you can see, the script marks some commands as incomplete - those that are supposed to continue. In the event that the continuation of the Junos command no longer hides, such a command is also located in the script, but it is issued in an abbreviated form (show chassis message-statistics i is show chassis message-statistics ipc).

    There were no goals to process the script with any possible errors and situations, so if you have a synax error line in the interface descriptions that the script responds to or logging to the terminal is turned on, the operation logic may break.

    Another problem is commands that accept any name as an input, for example, show interfaces AnyInterfaceNameIsOKHere (in the absence of such an interface an error is generated, other similar commands may not produce anything). For obvious reasons, the script when setting it on show interfaces crashes with an error about maximum recursion depth exceeded. But the search with commandStart = "show interfaces ge-0/0/0" works fine:
    Launch for show interfaces ge-0/0/0
    hidden command >> show interfaces ge-0/0/0 forwarding-context
    hidden command >> show interfaces ge-0/0/0 ifd-index
    hidden command >> show interfaces ge-0/0/0 ifl-index
    hidden command >> show interfaces ge-0/0/0 instance
    hidden command >> show interfaces ge-0/0/0 no-forwarding
    hidden command >> show interfaces ge-0/0/0 scc-dont-forward


    Conclusion


    It should be understood that a significant part of hidden commands are hidden due to the fact that they are not supported (or do not make sense) on this equipment or in this version of software. Many of them are useless, however, among them there are "nuggets" (for example, show chassis cluster information). Since I work as a Juniper instructor, I often hear from students a question - where to get a list of all hidden teams. So now I will refer all to this article. I hope that someone will benefit from this recipe.

    Also popular now: