Secure-Compliance-Solutions-LLC / GVM-Docker

Greenbone Vulnerability Management Docker Image with OpenVAS
https://securecompliance.gitbook.io/projects/
MIT License
247 stars 91 forks source link

[Bug] regex library on Alpine causes NASL script to fail #288

Closed karlffox closed 2 years ago

karlffox commented 3 years ago

Describe the bug The GVM plugin

/var/lib/openvas/plugins/2012/secpod_apache_http_srv_cookie_info_disc_vuln.nasl

throws the following error every time it is run from the securecompliance/gvm:21.4.3-v1-data container:

lib nasl:MESSAGE:2021-09-20 16h36.25 utc:4470: 4470 nasl_exec: bad regex at or near line 93 lib nasl:MESSAGE:2021-09-20 16h41.00 utc:11405: 1…

I filed this with Greenbone and they sent the following reply:

AFAICT this is a limitation of the regex library used by the scanner host (in this case Alpine linux running within the docker container or more specifically the mus libc of Alpine).

Currently there are a few options:

  1. switching the underlying operating system to a Debian / Ubuntu based system where this doesn’t occur
  2. ignoring the log entries as that limitation of musl libc is only affecting a VT from 2012
  3. a third party patch (tested on Alpine and Debian) by the community (posted at https://community.greenbone.net/c/vulnerability-tests/7) to work around this limitation on the regex library side of Apline (if this is possible at all) while keeping compatibility with our reference system (which is Debian).

To Reproduce Steps to reproduce the behavior:

  1. Run a vulnerability scan that includes the above-mentioned plugin
  2. Search the OpenVAS log file for regex errors:
    docker exec gvm bash -c 'grep bad.regex /var/log/gvm/openvas.log'
  3. See errors

Expected behavior The regular expression should be parsed and the plugin should complete without error.

Host Device: Host:

Image in use:

# docker image inspect securecompliance/gvm:21.4.3-v1-data
[
    {
        "Id": "sha256:c1b8fb4147c6111631d906db0d4fa98585ef16d20ba621f70f35af4d4a697a9c",
        "RepoTags": [
            "securecompliance/gvm:21.4.3-v1-data"
        ],
        "RepoDigests": [
            "securecompliance/gvm@sha256:8d00f21ea9808c89ef5623ce7a29217b60d71c447b6b4b697d95877642768cb8"
        ],
        "Parent": "",
        "Comment": "buildkit.dockerfile.v0",
        "Created": "2021-08-08T20:39:17.163431132Z",
        "Container": "",
        "ContainerConfig": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": null,
            "Cmd": null,
            "Image": "",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "DockerVersion": "",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "22/tcp": {},
                "5432/tcp": {},
                "8081/tcp": {},
                "9392/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                "SUPVISD=supervisorctl",
                "USERNAME=admin",
                "PASSWORD=adminpassword",
                "PASSWORD_FILE=none",
                "TIMEOUT=15",
                "DEBUG=N",
                "RELAYHOST=smtp",
                "SMTPPORT=25",
                "AUTO_SYNC=true",
                "HTTPS=true",
                "CERTIFICATE=none",
                "CERTIFICATE_KEY=none",
                "TZ=Etc/UTC",
                "SSHD=false",
                "DB_PASSWORD=none",
                "DB_PASSWORD_FILE=none",
                "LANG=en_US.UTF-8",
                "LANGUAGE=en_US.UTF-8",
                "LC_ALL=en_US.UTF-8",
                "MUSL_LOCPATH=/usr/share/i18n/locales/musl",
                "SETUP=0",
                "OPT_PDF=0"
            ],
            "Cmd": [
                "/usr/bin/supervisord",
                "-n",
                "-c",
                "/etc/supervisord.conf"
            ],
            "ArgsEscaped": true,
            "Image": "",
            "Volumes": {
                "/etc/ssh": {},
                "/opt/database": {},
                "/var/lib/gvm": {},
                "/var/lib/openvas/plugins": {}
            },
            "WorkingDir": "",
            "Entrypoint": [
                "/entrypoint.sh"
            ],
            "OnBuild": null,
            "Labels": {
                "org.opencontainers.image.created": "2021-08-08T20:34:33.356Z",
                "org.opencontainers.image.description": "Greenbone Vulnerability Management Docker Image with OpenVAS",
                "org.opencontainers.image.licenses": "MIT",
                "org.opencontainers.image.revision": "45166f1b9bc1c5314303b99ee1a94bb7552bc153",
                "org.opencontainers.image.source": "https://github.com/Secure-Compliance-Solutions-LLC/GVM-Docker",
                "org.opencontainers.image.title": "GVM-Docker",
                "org.opencontainers.image.url": "https://github.com/Secure-Compliance-Solutions-LLC/GVM-Docker",
                "org.opencontainers.image.version": "21.4.3-v1-data"
            }
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 2216784430,
        "VirtualSize": 2216784430,
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/248778d6ed08ec5a0e597eb04b69cc21655f4c40518ed6d75254ad66d42186c5/diff:/var/lib/docker/overlay2/ebf213220e2f16907e0d528ef0241dc542a6631cab4787df63cbba5d09e6f8c6/diff:/var/lib/docker/overlay2/b570476f3a8ed5565ce75f9027c67b621554b387b57747eaf4d0b8b4438c1c9b/diff:/var/lib/docker/overlay2/514e63bc38502ca0110b8005be96abd656f581a09f6a388015cae7dd36c25d05/diff:/var/lib/docker/overlay2/069e0bc406716c550b2f1e8dbec63662bdcfc574aebbb70c04038184a04515ba/diff:/var/lib/docker/overlay2/af7f5c86eab82e24033f448e7f391e59b46a80ebce83e3c69de643ee6693eeb9/diff:/var/lib/docker/overlay2/1bda4775298658e23911435d88323328530c2d262211a58af5578f2c95f13280/diff:/var/lib/docker/overlay2/45d4c9a75bef8c655fc5adfc8fbe68f6385d73db506e49df47f77ad7a314a32b/diff:/var/lib/docker/overlay2/d030dad3fa6cb22c0422e52688f348f9f8b7fb67091f72c15ead13941c4804d3/diff:/var/lib/docker/overlay2/d44e30cd9ed380b07728ae442b1a7b743381b84ec69fea6b2d363464bb4e637c/diff:/var/lib/docker/overlay2/7634702b7deecfcf8d2a50450924ea8465ba0b92eb289b277a4ada307be6d9c6/diff:/var/lib/docker/overlay2/301e801d8c4fa0a78e428d66adb558fa66a46b152d298c5e671b40dcc75afe25/diff:/var/lib/docker/overlay2/b199614b69e1a315ae785e8ac63ec8f30556f78fea3e499bd6673e6c25121aea/diff",
                "MergedDir": "/var/lib/docker/overlay2/7d7bad7584ad94af33f4bf652c7e0edf76fe23bf5ce09b2111a1202476b50f98/merged",
                "UpperDir": "/var/lib/docker/overlay2/7d7bad7584ad94af33f4bf652c7e0edf76fe23bf5ce09b2111a1202476b50f98/diff",
                "WorkDir": "/var/lib/docker/overlay2/7d7bad7584ad94af33f4bf652c7e0edf76fe23bf5ce09b2111a1202476b50f98/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:bc276c40b172b1c5467277d36db5308a203a48262d5f278766cf083947d05466",
                "sha256:0c4ac070c4f03cca7c16a747fd9d467b485c061795399010bd3100581ec41c0a",
                "sha256:5d6bbd2dcce5feb5424d1e3ee6b44049d37071d175d18eb303a73a79916848d8",
                "sha256:16695a3a00062961220ed6f18b64cfd35358523af07e29a8883d0cafa5c96527",
                "sha256:a59e5a6ab44c1b2ed1afea4e2f931ef547f4bf63c6fdd8285b67fe8a5a2ce99f",
                "sha256:9036d1e8e0173202f37107495ca936ea7212936b6ee822bc0b9382e486a99e3d",
                "sha256:ee290c784570e9d71576d06e5c05cb1174d72c1c2b280d4cfa8018ccda0fed88",
                "sha256:b0a7804131f6cd5ae9b6527379c0a374fa76e960f2201e4d3dd2df94bb3cdde6",
                "sha256:2e640983d7088266c796b233ed6c949e118a8b043108b1e3c98e74413fec2383",
                "sha256:a9ae95a9e54ee4eeb73c72bf88e5d799274f94daa6f984924531d12633469129",
                "sha256:02b18ec11a49495185b7cef99d3ed5a332123c17fd699a460cbd7bfda57d0cae",
                "sha256:1a0a0799c42ce65f726c5454d3d6656b80dd854dbb05747e6d43f497e124535a",
                "sha256:93ce1cb27fbd99165639d00f5b8626d938ccf9de99aecbddb21c9a474eede731",
                "sha256:e2ac0ff4bc79aaaddd97f9f1cb5fd0083b1fa8cbc2c095a720e7bca57d467d99"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

Additional context The code in secpod_apache_http_srv_cookie_info_disc_vuln.nasl that fails:

res = http_keepalive_send_recv(port:port, data:req, bodyonly:TRUE);

if(res && "400 Bad Request" >< res &&
   res =~ "Cookie: c[0-9]=X{820}; path=/;" &&
   "Size of a request header field exceeds server limit" >< res){
  security_message(port:port);
  exit(0);
}
cfi-gb commented 3 years ago

As researched in https://github.com/greenbone/gvmd/issues/1667 this seems to be coming from a limitation in the musl libc of Alpine related to this:

X{820}

It seems that there is a limitation in the regex library used on Alpine which can't handle such a huge number of repetitions in {}.

Maybe some one having such an Alpine setup can try something like e.g. the following:

(X{82}){10}

https://regexper.com/#%28X%7B82%7D%29%7B10%7D

which could work around this limitation.

austinsonger commented 3 years ago

We are currently working on a new Debian version on the dev branch, if you have a workaround this limitation of alpine, then please fork and submit a pull request.

cfi-gb commented 3 years ago

A workaround would be required to be submitted to the Greenbone feed side. If some one is able to test and confirm the previously mentioned suggestion i'm happy to push a fix on Greenbone feed side.

Dexus commented 3 years ago

Will do a patch for the src and test it once I have time.

Thank you.

Von meinem iPhone gesendet

Am 12.10.2021 um 17:23 schrieb cfi-gb @.***>:

 A workaround would be required to be submitted to the Greenbone feed side. If some one is able to test and confirm the previously mentioned suggestion i'm happy to push a fix on Greenbone feed side.

— You are receiving this because you were assigned. Reply to this email directly, view it on GitHub, or unsubscribe.

karlffox commented 3 years ago

I just updated my ticket with Greenbone, suggesting making the X{820} -> (X{82}){10} change to their plugin. I have implemented a filter to my Greenbone plugin feed that does exactly that edit, and it does indeed prevent the error message. I have no way to test whether it is actually working properly, though.

I consider this issue closed. Thank you for providing me what I needed.

Karl

austinsonger commented 3 years ago

@karlffox can you add the ticket link in this issue?

karlffox commented 3 years ago

Certainly.

https://community.greenbone.net/t/openvas-is-throwing-this-regex-error/10217/3

Dexus commented 3 years ago

As researched in https://github.com/greenbone/gvmd/issues/1667 this seems to be coming from a limitation in the musl libc of Alpine related to this:


X{820}

It seems that there is a limitation in the regex library used on Alpine which can't handle such a huge number of repetitions in {}.

Maybe some one having such an Alpine setup can try something like e.g. the following:


(X{82}){10}

https://regexper.com/#%28X%7B82%7D%29%7B10%7D

which could work around this limitation.

https://regexper.com/#%28X%7B82%7D%29%7B10%7D%20X%7B820%7D

But this would not be the same result!

Or do I'm currently see this wrong?

cfi-gb commented 3 years ago

The regex should work the same way:

Basically X{820} says that X needs to be included 820 times in the response.

The same should work for (X{82}){10} because it says X should be included 82 times ((X{82}) in the response multiplied by 10 ({10}).

Below is a reproducing .nasl script, maybe some one with an Alpine docker installation and having access to openvas-nasl in that environment can check that:

res = "Cookie: c1=" + crap( 820 ) + "; path=/; ";
res += '\n400 Bad Request';
res += '\nSize of a request header field exceeds server limit';

# nb: The default regex
if(res && "400 Bad Request" >< res &&
   res =~ "Cookie: c[0-9]=X{820}; path=/;" &&
   "Size of a request header field exceeds server limit" >< res)
  display("Default regex works / matches");

# nb: Workaround regex for Alpine
if(res && "400 Bad Request" >< res &&
   res =~ "Cookie: c[0-9]=(X{82}){10}; path=/;" &&
   "Size of a request header field exceeds server limit" >< res)
  display("Workaround regex for Alpine works / matches");

This can be launched like e.g.:

openvas-nasl -X regex.nasl

and gives the following on my Debian system:

lib  nasl-Message: 10:52:38.646: Default regex works / matches
lib  nasl-Message: 10:52:38.647: Workaround regex for Alpine works / matches

and on Alpine it probably throws the previously mentioned error for the first regex but the second string should be included.