# Zyxel authentication bypass patch analysis (CVE-2022-0342)
A few months ago, new firmware was released for many **Zyxel** security
devices to patch a **critical vulnerability**. The vulnerability was
subsequently reported by numerous news outlets, however no technical details
were published.
The vulnerability has been assigned
[CVE-2022-0342](https://www.cve.org/CVERecord?id=CVE-2022-0342) and is
described as follows:
_An authentication bypass vulnerability in the CGI program of Zyxel USG/ZyWALL
series firmware versions 4.20 through 4.70, USG FLEX series firmware versions
4.50 through 5.20, ATP series firmware versions 4.32 through 5.20, VPN series
firmware versions 4.30 through 5.20, and NSG series firmware versions V1.20
through V1.33 Patch 4, which could allow an attacker to bypass the web
authentication and obtain administrative access of the device._
The information released by Zyxel is available at:
* <https://www.zyxel.com/support/Zyxel-security-advisory-for-authentication-bypass-vulnerability-of-firewalls.shtml>
* [https://www.zyxel.com/support/download_landing/product/usg20_vpn_usg20w_vpn_14.shtml?c=gb&l=en&pid=20151111155041&tab=Firmware&pname=USG20-VPN/USG20W-VPN](https://www.zyxel.com/support/download_landing/product/usg20_vpn_usg20w_vpn_14.shtml?c=gb&l=en&pid=20151111155041&tab=Firmware&pname=USG20-VPN/USG20W-VPN)

This is a bonus article for our [Zyxel
audit](https://security.humanativaspa.it/tag/zyxel/) series, in which we
patch-diff the firmware update to discover **the root cause of the fixed
vulnerability and how to exploit it**.
### How HTTP authentication is managed by Zyxel
On Zyxel devices the web interfaces are managed via the Apache HTTP Server.
The main configuration file is /usr/local/zyxel-gui/httpd.conf which contains
the following line:
```
LoadModule auth_zyxel_module modules/mod_auth_zyxel.so
```
This **Apache module** is developed and maintained by Zyxel and manages the
authentication process.
The login process generates a cookie named "authtok" which is used to
authenticate the user in the next requests.

### Diffing the patch
Comparing the two versions of **mod_auth_zyxel.so** with
[Bindiff](https://www.zynamics.com/bindiff.html), it's quite easy to identify
the modified routines that fix the issue:

The function **" check_authtok"** is the one directly called by Apache to
verify the authentication; "create_server_config" has been modified as well.
Based on the analysis it's possible to see that a part of the code has been
removed:

The vulnerable pseudocode is:

and the patched one is:

Basically, all the code that allows direct access without authentication in
some case related to a mysterious **" non GUI access"** has been removed.
The routine **" get_server_conf"** takes the content of the
/tmp/__HTTP_SERVER_CONFIG file and puts it into some variables:

Then these variables are compared with a part of the **data structure** passed
to the "check_authtok" function by Apache.
Based on the [Apache
documentation](https://httpd.apache.org/docs/trunk/developer/modguide.html)
the data structure passed to the function is **" request_rec"** which is
defined in <http://svn.apache.org/repos/asf/httpd/httpd/trunk/include/httpd.h>
The first pointer used during the comparison is "request_rec + 4", which means
the second element of the structure on a 32-bit processor (hoping that
compiler optimization didn't mix up the data structure's order). In this case
"conn_rec *connection;":
```
struct request_rec {
/** The pool associated with the request */
apr_pool_t *pool;
/** The connection to the client */
conn_rec *connection;
/** The virtual host for this request */
server_rec *server;
/** Pointer to the redirected request if this is an external redirect */
request_rec *next;
/** Pointer to the previous request if this is an internal redirect */
request_rec *prev;
```
The second pointer accessed is the 4th element of the "conn_rec" structure
which is **" apr_sockaddr_t *local_addr;"** defined in the same file:
```
struct conn_rec {
/** Pool associated with this connection */
apr_pool_t *pool;
/** Physical vhost this conn came in on */
server_rec *base_server;
/** used by http_vhost.c */
void *vhost_lookup_data;
/* Information about the connection itself */
/** local address */
apr_sockaddr_t *local_addr;
/** remote address; this is the end-point of the next hop, for the address
* of the request creator, see useragent_addr in request_rec
*/
apr_sockaddr_t *client_addr;
```
The third pointer accessed is the 4th element of apr_sockaddr_t defined in [apr_network_io.h](https://apr.apache.org/docs/apr/trunk/apr__network__io_8h_source.html) file and it’s **“apr_port_t [port](https://apr.apache.org/docs/apr/trunk/structapr__sockaddr__t.html#a174c19138de9c208f13ed71b5892e505);”**:
```
239 struct apr_sockaddr_t {
240 /** The pool to use... */
241 apr_pool_t *pool;
242 /** The hostname */
243 char *hostname;
244 /** Either a string of the port number or the service name for the port */
245 char *servname;
246 /** The numeric port */
247 apr_port_t port;
248 /** The family */
249 apr_int32_t family;
```
So, the data which is compared with the results of the get_server_conf()
function is the **local port which received the request**.
It's also possible to confirm this by looking inside the file accessed by the
"get_server_conf" function, which contains the main ports used by the Apache
HTTP Server:

### Root cause of the problem
We need to understand why that check can affect authentication. Since the
check is carried out on the socket we can hypothesize **two different
scenarios** :
* we can connect to other ports, and by modifying the HTTP protocol "Host" header, go to a different virtual host;
* we can reach some CGIs from some virtual hosts accessible via different ports than those present in the control file.
Theoretically, the Apache HTTP Server should guarantee the separation of the
environments according to ports and interfaces on which the listening takes
place, therefore it is unlikely that our first hypothesis can be correct.
Let's check which are the ports used by Apache on our system:

Accessing the TCP port 8008 via browser we get:

It looks like something related to 2FA, which is configured in the
/var/zyxel/service_conf/httpd_twofa.conf file:

Accessing the TCP port 54088 we get this page:

It looks like something related to blocking alert page, which is configured in
the /var/zyxel/service_conf/cf_blockpage_https.conf file:

By checking the main configuration file of the Apache HTTP Server
(/usr/local/zyxel-gui/httpd.conf) it's possible to see that the "cgi-bin"
directory is configured in a global area, which means that **all the CGIs will
be accessible on every different virtual host** :

### Expoitation
Putting together all information found so far, exploitation is quite easy.
Based on the patch we can assume that all CGIs will be reachable on all
interfaces exposed by Apache.
Accessing a CGI via standard ports with an invalid cookie will return an
authentication error:

But accessing the same CGI via a non-standard port will give full access to
the CGIs and consequently also to the device configuration:

See you next time.
暂无评论