Path: news.mitre.org!blanket.mitre.org!agate!awabi.library.ucla.edu!128.230.129.106!news.maxwell.syr.edu!news.mathworks.com!mvb.saic.com!info-vax From: Gotfryd Smolik Newsgroups: comp.os.vms Subject: [2:long] Spawn priveleged processes Message-ID: Date: Thu, 8 Jan 1998 13:50:55 +0100 (MET) Organization: Info-Vax<==>Comp.Os.Vms Gateway X-Gateway-Source-Info: Mailing List Lines: 185 On 7 Jan 1998, John Briggs wrote: +In article [cut], Gotfryd Smolik writes: For remind: to resolving proper run for privileged subprocess with captive procedure inside (suprocess created via privileged-installed image) John enumerate the neccessary steps and write (">" is John prompt and "+" my): +> +This much can be defended against with a fair degree of success. It's +> +attack number 4 which is unbeatable. +> + +> +4. Watch out for logicals in LNM$JOB. +> +> Don't agree. The subprocess can be "enought privileged" +> (SYSNAM or CMKRNL as required) then why not: +> +> $ DEFINE/TABLE=LNM$PROCESS_DIRECTORY LNM$JOB LNM$GROUP/EXEC + +Nice try. But no cigar. + +The problem is that the created subprocess comes up with an LNM$JOB +in LNM$PROCESS_DIRECTORY pointing to LNM$JOB_jibaddr. Your definitions +from LNM$PROCESS_DIRECTORY get propagated during the execution of LOGINOUT. + +My recollection is that LNM$PROCESS_DIRECTORY logicals come across +regardless of whether you suppress propagation of logicals with the +appropriate flag. Haven't pay attention any time... Althoutght is relevant to the attack themself in the way that guarantee the propagation of LNM$JOB because prevents unintentional restore of the (modified "by enemy") old LNM$jib_address. But your point say also, that must be prevented the redefinition (means: duplicate name in inner, less privileged mode) for LNM$GROUP, LNM$PROCESS (are without /noalias) and LNM$SYSTEM, LNM$SYSTEM_TABLE (the *DIRECTORY prevents themself and PROCESS_TABLE is /NOALIAS). Ok, thanks, you have show one point to "glue" :) But it is a four DEFINE/TABL=LNM$PROCESS_DIRECTORY only to prevent. (not a /EXEC - simple /SUPER ! It may be /EXEC/NAME=NO_ALIAS instead.) +In any case, this is too late. Don't agree ;) + At this point, the attacker has already +breached your security. It is the logicals in place in LNM$JOB_jibaddr +at process creation time that determine whether LOGINOUT.EXE is ever +executed in the first place. Great hack ! Really hane fun that one can prevent a *logout* from process: not protected in the way DEFINE/TAB=LNM$DIRECTORY LNM$JOB..., then (not related to this thread) we get: BUK::GS> def/job loginout mail BUK::GS> spa %DCL-S-SPAWNED, process GS_1 spawned %DCL-S-ATTACHED, terminal now attached to process GS_1 BUK::GS> lo MAIL> Exit -:) ... but this also will *not* work as you describe ! At *start of process* - you see - the loginout *is* executed but the logical name "LOGINOUT" (in lnm$job) isn't used. Why ? In VMS the automated name translation use only name in the same or higher mode than the executor - then the system and protected routines can't be swindled by unprivileged user/process via logname. When the appriopiate routine in DCL (where does the SPAWN) is run in EXEC then all SUPERVISOR and USER mode name are simply ignored. The LOGOUT command run LOGINOUT.EXE as a "normal" image - then the name is in effect; but *any* name after SPAWN can be prevented in the procedure ! Digress: in older version of VMS also the LNM$FILE_DEV in EXEC mode has been defined as SYSTEM or SYSTEM+GROUP only, but for 6.X and 7 also have the JOB+PROCESS. +One moment while I test an exploit against this defense... + +*Bingo*. I'm in. Took two tries -- they aren't using the first logical +I tried any more. Without privilege ? Looks interesant :) + It's been years since I've played this particular cat and mouse game. [cut and comment: the game is interesant *without* priv.mode hacks :)] + +But you can't just define the job table out of the way. You'll have to try +something else. + Comment: I know of some disadvantages *other* than you points: b.ex. DCL use the JOB table to save the ATTACH mailbox name (for /WAIT, of matter) then if the table doesn't exist or the process have enought privilege in the moment of creation (and this can do in sub-subprocesses) then we get "no privilege to attempted...". Resolution like "create a new shared name table and define it as a new JOB" also doesn't work in all case: the "enemy" user can define a name within it from another process. The simplest solution looks as: remove the JOB table from the automat ! But this *also* have a disadvantage: if the procedure itself use /JOB name for its own use... For all the point we have the list of limitation: a. the procedure and all called subprocedures can't remove the SYSNAM and SYSPRV privilege any moment; means "in any state must have at least SYSNAM *or* SYSPRV" - one of it can be removed. *or* b. the procedure must *not* use the JOB table itself (means: don't define or depend of name in JOB table). ...and we get the start of the "more than captive" procedure: ================= for limitation "b": $ DEFINE/KERNEL/NAME=NO_ALIAS/table=LNM$PROCESS_DIRECTORY - LNM$PROCESS,LNM$GROUP,LNM$SYSTEM Yes ! We haven't /KERNEL in DCL but can do a equivalent via a privileges (note: not a hack, but legal $CMKRNL + $CRELNM) program; we anyway use a installed, privileges one (another) to run the privilege subprocess ! But we can safe use a simple EXEC: for user+supervisor+executive mode the name will be "covered" and if even is possible (can't at the moment imagine a example) the use of LNM$JOB for KERNEL_OLNY mode (hm... will we load a driver ?) then the user is prevented: having not a privilege it can't define a name where may be used :) And better resolution is a simple loop where will copy all non-world-writable location (b.ex. DECW$LOGICAL_NAMES) in the specific configuration. The real code: $ i=0 $ iteml="" $ptd: $ item=f$trnlnm("LNM$FILE_DEV","LNM$SYSTEM_DIRECTORY",i,"EXECUTIVE") $ if item.eqs."" then goto eptd $ i=i+1 $ if item.eqs."LNM$JOB" then goto ptd ! Definitely isn't the last :) $ if iteml.nes."" then iteml=iteml+"," $ iteml=iteml+item $ goto ptd $eptd: $ DEFINE/EXEC/TABLE=LNM$PROCESS_DIRECTORY - LNM$FILE_DEV 'iteml' ================= next: for limitation "a": $ nam:=LNM_JOB'f$getjpi(0,"PID")' ! ok, we can use any uniquely i'd ! $ CREATE/NAME/EXEC 'nam' - /PARENT=LNM$SYSTEM_DIRECTORY $ SET SECURITY/OBJECT=LOGICAL 'nam'/OWNE=[1,4]/PROT=(G=R,W=R) $ tbl:=TABLE=LNM$PROCESS_DIRECTORY $ DEFINE/'tbl'/EXEC LNM$JOB 'nam'/NAME=NO_ALIAS $ DEFINE/'tbl'/EXEC LNM$GROUP/NAME=NO_ALIAS - LNM$GROUP_'f$fao("!OW",f$getjpi(0,"GRP"))' $ DEFINE/'tbl'/EXEC LNM$PROCESS - LNM$PROCESS_TABLE/NAME=NO_ALIAS $! and to prevent any SYSTEM name trick: $ DEFINE/'tbl'/EXEC LNM$SYSTEM LNM$SYSTEM_TABLE/NAME=NO_ALIAS $! also for FILE_DEV: $ DEFINE/'tbl'/EXEC LNM$FILE_DEV LNM$SYSTEM/NAME=NO_ALIAS $ DEASSI/'tbl'/EXEC LNM$FILE_DEV ! Or use the loop from "b" .. here you have the body ... and at end (carefully for error/interrupt exception if you will not eat memory for the "second job" table !): $ DEASSIGN/TABLE=LNM$PROCESS_DIRECTORY/EXEC LNM$JOB $ DEASSIGN/TABLE=LNM$SYSTEM_DIRECTORY/EXEC LNM_JOB'f$getjpi(0,"PID")' +The last time I played this game, I won. But that defender wasn't nearly +as competent as you are. Your move. You say ! Interest what hack may be the next :) + John Briggs vaxs09@alpha.vitro.com Regards - Gotfryd -- ===================================================================== $ ON F$ERROR("LANGUAGE","ENGLISH","IN_MESSAGE").GT.F$ERROR("NORMAL") - THEN EXCUSE/OBJECT=ME $! GS@stanpol.zabrze.pl =====================================================================