
    \i^"                     F   S r SSKrSSKrSSKrSSKrSSKrSSKrSSKJrJ	r	J
r
  SSKJrJr  SSKJr  SSKJrJrJr  SSKJr  SSKJr  \" S	\S
S9r/ SQrS\4S jrS rS\4S jrS\S\ S\!4S jr"S\S\ S\!4S jr#\RI                  SS/S9\S 5       5       r%\RI                  SS/S9\S 5       5       r&\RI                  SS/S9\S 5       5       r'0 r(S \S!\ S"\4S# jr)\RT                  " S$S%S&9S' 5       r+\RT                  " S(S%S&9S) 5       r,\RT                  " S*S%S&9S+ 5       r-g),u)   
后台 Shell 管理接口与 TTY 通道
    N)	Blueprintrequestjsonify)
disconnectemit)socketio)dbSystemConfig
ShellAudit)AuthService)admin_required	shell_apiz/api/admin/shell)
url_prefix)rmrebootshutdownhaltmkfsz	mkfs.ext4zmkfs.xfsmountumountiptableszfirewalld-cmdddchownchmoduseradduserdelgroupaddgroupdeldockerkubectl	systemctlservicereturnc                  :   [         R                  R                  [        5      n [         R                  R	                  [         R                  R	                  [         R                  R	                  U 5      5      5      n[         R                  R                  US5      $ )u"   默认知识库根路径 /ctf/ge10ge10)ospathabspath__file__dirnamejoin)current_filectf_roots     9/Users/yu22x/Desktop/ge/ctf/app/routes/admin/shell_api.py_default_base_dirr/      sU    77??8,Lwwrwwrww|/LMNH77<<&))    c                  .   [         R                  " SS 5      n [        5       nU (       d  U/[        USSS.$ U R	                  SU/5        U R	                  S[        5        U R	                  SU5        U R	                  SS5        U R	                  S	S5        U $ )
Nadmin_shell_config      allowed_pathsforbid_commandsdefault_workdirtimeout_sec
max_outputr6   r7   r8   r9   r:   )r
   
get_configr/   DEFAULT_FORBID
setdefault)cfgdefault_bases     r.   _load_shell_configr@   &   s    

!
!"6
=C$&L*^-+
 	
 NN?\N3NN$n5NN$l3NN=!$NN<'Jr0   r>   c                 2    [         R                  " SU SSS9  g )Nr2   u   后台 Shell 管理配置admin)descriptioncategory)r
   
set_configr>   s    r.   _save_shell_configrG   :   s    /	r0   r'   r6   c                     [         R                  R                  U 5      nU H:  n[         R                  R                  U5      nUR                  U5      (       d  M:    g   g)NTF)r&   r'   realpath
startswith)r'   r6   	real_pathapap_reals        r.   _is_path_allowedrN   C   sM      &I''""2&((  r0   cmdforbid_listc                     U (       d  g [         R                  " U 5      nU(       d  gUS   n[        R                  R                  U5      nXA;   $ ! [         a     gf = f)NFTr   )shlexsplit
ValueErrorr&   r'   basename)rO   rP   partshead	head_bases        r.   _is_command_forbiddenrY   L   s]    C  8D  &I##  s   A 
AAz/configGET)methodsc                  2    [        5       n [        SU S.5      $ )u   获取 Shell 配置T)successconfig)r@   r   rF   s    r.   get_shell_configr_   [   s     
Cts344r0   POSTc                     [         R                  " 5       =(       d    0 n U R                  S/ 5      nU R                  S/ 5      nU R                  S5      n[        U R                  SS5      5      n[        U R                  SS5      5      nU(       d  [	        SS	S
.5      S4$ U H<  n[
        R                  R                  U5      (       a  M)  [	        SSU 3S
.5      S4s  $    U(       a   [        X15      (       d  [	        SSS
.5      S4$ UU=(       d    [        U=(       d    US   UUS.n[        U5        [	        SSUS.5      $ )u   更新 Shell 配置r6   r7   r8   r9   r3   r:   r4   Fu   allowed_paths 不能为空r]   message  u   路径不存在: u%   default_workdir 不在允许目录内r   r5   Tu   配置已更新)r]   rc   r^   )r   get_jsongetintr   r&   r'   existsrN   r<   rG   )datar6   r7   r8   r9   r:   pr>   s           r.   update_shell_configrk   c   s3    #DHH_b1Mhh0"5Ohh01Odhh}a01KTXXlE23J55QRSUXXX ww~~a  u;LQC9PQRTWWW  /OO55\]^`ccc '*<n*>mA.>" C st0ASQRRr0   z/execc            
      Z   [         R                  " 5       n [        R                  " 5       =(       d    0 nUR	                  S5      nUR	                  S5      nU(       d  [        SSS.5      S4$ [        5       nUS   nUS   nUS	   nUS
   nU(       d  US   n[        X55      (       d  [        SSS.5      S4$ [        X&5      (       a  [        SSS.5      S4$ [        R                  " 5       n	 [        R                  " USU[        R                  [        R                  SSS9n
 U
R                  US9u  pU
R                  n[%        U5      U:  a  USU S-   n[%        U5      U:  a  USU S-   n['        [        R                  " 5       U	-
  S-  5      n [)        U (       a  U R*                  OSUUUUUUS9n[,        R.                  R1                  U5        [,        R.                  R3                  5         [        SUUUUS.5      $ ! [        R                   a:    U
R!                  5         U
R                  5       u  pU=(       d    SSU S3-   nSn GNf = f! ["         a  n[        SSU 3S.5      S4s SnA$ SnAff = f! ["         a!    [,        R.                  R5                  5          Nf = f)u   单次命令执行（非 TTY）rO   workdirFu   cmd 不能为空rb   rd   r6   r7   r9   r:   r8   u!   工作目录不在允许范围内u   命令被禁止执行T	/bin/bash)shellcwdstdoutstderrtext
executable)timeout u   
[timeout] 命令超过 u   s 被终止u   执行失败: i  Nz
...[truncated]...i  )user_idcommandrm   	exit_codeduration_msrq   rr   )r]   rq   rr   rz   r{   )r   get_current_userr   re   rf   r   r@   rN   rY   time
subprocessPopenPIPEcommunicate
returncodeTimeoutExpiredkill	Exceptionlenrg   r   idr	   sessionaddcommitrollback)userri   rO   rm   r>   r6   r7   r9   r:   startprocrq   rr   rz   er{   audits                    r.   
exec_shellr      s    '')D#D
((5/Chhy!G55GHI3NN

C(M+,Om$K\"J'(G3355XYZ\___S2255LMNPSSSIIKEQ????"
	(!--k-BNF I
 6{Z$'<<
6{Z$'<<tyy{U*d23K#DGG#
 	

u


 "  E (( 	IIK!--/NFl(A+k&ZZFI		  Q5~aS5IJKSPPQ0  


sV   -6I $H 5I AI? A
II II 
I<I71I<7I<?(J*)J*rm   r7   sidc           	      >  ^ ^^ [         R                  " 5       u  mn[        R                  R	                  5       nSUS'   [
        R                  " / SQU 4S jUUUUS9n[        R                  " U5        UU4S jn[        R                  " U5        UTUS.[        T'   g)	u   创建受限 TTY shell 进程z/tmp/.admin_shell_historyHISTFILE)rn   z--noprofilez--norcz-rc                  0   > [         R                  " T 5      $ )N)r&   chdir)rm   s   r.   <lambda>_spawn_shell.<locals>.<lambda>   s    288G,r0   )
preexec_fnstdinrq   rr   envc            	        >    [         R                  " TS5      n U (       d  O[        SSU R	                  SS90STS9  M=  [
        R                  TS 5        [         R                  " T5        [        S0 STS9  g ! [         a     MF  f = f! [
        R                  TS 5        [         R                  " T5        [        S0 STS9  f = f)	Ni   outputri   ignore)errors/admin/shell)	namespacetoexit)r&   readOSErrorr   decodetty_sessionspopclose)ri   	master_fdr   s    r.   reader_spawn_shell.<locals>.reader   s    	?779d3D X8(DEQ_dgh  S$'HHY~#>   S$'HHY~#>s-   B A: %B :
BB BB :C)r   fdforbidN)ptyopenptyr&   environcopyr~   r   r   eventletspawnr   )rm   r7   r   slave_fdr   r   r   r   s   ` `    @r.   _spawn_shellr      s    ++-Ix
**//
C1C
O4,D HHX?  NN6!Lr0   connectr   )r   c                     [         R                  " 5       n U (       a  U R                  S:w  a  [        SSS05        [	        5       $ [        5       nUR                  S5      =(       d    US   S   n[        X!S   [        R                  5        g )	NrB   errorrc   u	   未授权r8   r6   r   r7   )
r   r|   roler   r   r@   rf   r   r   r   )r   r>   rm   s      r.   tty_connectr     so    '')D499'Wy+./|

Cgg'(CC,@,CG/0'++>r0   inputc                 H   [         R                  [        R                  5      nU(       d  [	        SSS05      $ U R                  SS5      n[        UR                  5       US   5      (       a  [	        SSS05      $ [        R                  " US	   UR                  5       5        g )
Nr   rc   u   会话不存在ri   rv   r   r   z[forbidden command]\nr   )
r   rf   r   r   r   rY   stripr&   writeencode)ri   r   lines      r.   	tty_inputr     s    w{{+GGi):;<<88FBDTZZ\78+<==Hv'?@AAHHWT]DKKM*r0   r   c                      [         R                  [        R                  S 5      n U (       d  g  [        R
                  " U S   5         U S   R                  5         g ! [         a     N!f = f! [         a     g f = f)Nr   r   )r   r   r   r   r&   r   r   	terminate)r   s    r.   tty_disconnectr     so    w{{D1G
!!#    s#   A A, 
A)(A),
A98A9).__doc__r&   rR   r~   r}   r   r   flaskr   r   r   flask_socketior   r   app.extensionsr   app.models.databaser	   r
   r   app.services.authr   app.services.auth.decoratorsr   __name__shell_api_bpr<   strr/   r@   dictrG   listboolrN   rY   router_   rk   r   r   r   onr   r   r    r0   r.   <module>r      s   
    
  - - + # < < ) 7 h;MN*3 *(D 3 t  $s $ $$ $ Iw/5  05 Ix0S  1S> GfX.N  /Nd &# & &3 &R 
Y.1? 2? 
W/+ 0+ 
\^4 5r0   