Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

When accessing the web-ui-dashboard simultaneously using http/https, the http method does not display correctly. #2912

Open
halikuosang opened this issue Sep 27, 2024 · 10 comments
Assignees

Comments

@halikuosang
Copy link

  • My goal is:
    Mongoose supports using http/https to open the web-ui-dashboard simultaneously and display the same content.

  • My actions were:
    Added CFLAGS_EXTRA = -DMG_TLS=MG_TLS_BUILTIN in the web-ui-dashboard Makefile and compiled and run it.
    http uses port 8000.
    https uses port 8443.

  • My expectation was:
    When accessing via http/https, Dashboard, Settings, Firmware Update, and Events should display the same content.

  • The result I saw:
    On the https page, Dashboard, Settings, Firmware Update, and Events display complete content.
    On the http page, Firmwares display complete content, but Dashboard, Settings, and Events display blank.

  • My question is:
    Why does the http page display blank content for Dashboard, Settings, and Events when accessed simultaneously with http; And when not using https and only using http, the http page can display normally?

Environment

  • mongoose version: 7.14
  • Compiler/IDE and SDK: gcc version 9.4.0 (Ubuntu 9.4.0-1ubuntu1~20.04.2)
  • Target hardware/board: X86 PC
  • Connectivity chip/module: ?
  • Target RTOS/OS (if applicable): Ubuntu20.04

log.txt
11

@halikuosang
Copy link
Author

I look forward to receiving your reply. Thank you

@scaprile
Copy link
Collaborator

Please use HEAD or at least 7.15. We won't fix an obsolete release.
What browser are you using ? Do you login in both cases ? Which one do you open first ? Did you try reverse order ? Did you try refreshing the screen when you don't see anything ? Did you try selecting an item in the menu when you don't see anything ?
Please sniff your network (using Wireshark, for example) and observe the traffic and provide us with pertinent information (including useful network captures) in order to reproduce and fix the issue.

@halikuosang
Copy link
Author

Today, I updated to version 7.15 from GitHub, and the problem still exists.

  • What browser are you using?
    Google Chrome 120.0.6099.225 (Official Build) (64-bit)
    Microsoft Edge version 129.0.2792.52 (Official Build) (64-bit)

  • Do you login in both cases?
    Yes, using different accounts.
    http (8000) user1/user1
    https (8443) admin/admin

  • Which one do you open first? Did you try reverse order?
    This is the key to the problem.
    In the first case, only using http login without using https login, the page displays normally.
    In the second case, as long as https is logged in, regardless of whether http is logged in first or later, the page will display abnormally.
    However, as soon as https logs out, the http display will return to normal.

  • Did you try refreshing the screen when you don't see anything?
    Yes, I used F5 and Ctrl+F5, but it had no effect.

  • Did you try selecting an item in the menu when you don't see anything?
    Yes, Firmwares display complete content, but Dashboard, Settings, and Events still display blank.

However, today I continued testing and found the following new discoveries:

  1. The Firmwares page actually cannot be obtained; this page may be displayed due to browser cache.
  2. When debugging mongoose/mongoose/reference-projects/windows-macos-linux/web-ui-dashboard/net.c authenticate, it was found that:
    Under normal circumstances, after user1 logs in, when the http page is refreshed or an item is selected, the authenticate function can always parse out [user1_token] for user authentication.
    However, if https admin logs in, when user1 logs in via https, refreshing the page or selecting an item, the authenticate function can only parse out a token of [], and authentication cannot be completed. This results in a 403 "Not Authorised" response.
  3. The above situations occur when the example (http/https) is running on X86 Ubuntu 20.04 and using Chrome and Edge on Windows.
    Today, I directly used Chrome and Firefox (localhost) on Ubuntu 20.04, and this problem did not occur. Because the authenticate function can parse out [user1_token] under http.

This is the packet capture information of user1 page by using wireshark in http mode on Windows 。In this dialog box, I cannot upload wireshark pcapng file, so screenshot to send to you
wireshark

This is printed debugging information
http

@halikuosang
Copy link
Author

halikuosang commented Sep 28, 2024

I believe I have found the reason for the problem

When HTTP and HTTPS access the same web server IP through LAN(not localhost), this problem will occurs:

The reason is as follows:

When there is a cookie under HTTPS, attempting to write a cookie in the same domain under HTTP will fail. The browser prompts: The operation of setting a cookie through the Set-Cookie header is prohibited because this header is not sent over a secure connection, and it will overwrite cookies with the Secure attribute.

This also explains why, after accessing HTTPS first, then HTTP access will fail. Because HTTP cannot send the token to the browser using Set-Cookie, causing the HTTP POST request to always send an empty token [], and the authenticate function fails to validate it.

@scaprile
Copy link
Collaborator

scaprile commented Sep 28, 2024

No screen snapshots, please attach capture files. I can't see TCP traffic on a snapshot. Yes, you can, just zip it.
Nevertheless, we'll check out what you comment

@scaprile
Copy link
Collaborator

scaprile commented Sep 28, 2024

@cpq @robertc2000 #2912 (comment) above and next one below.
Is there anything we can do regarding this ?

static void handle_login(struct mg_connection *c, struct user *u) {
char cookie[256];
mg_snprintf(cookie, sizeof(cookie),
"Set-Cookie: access_token=%s; Path=/; "
"%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n",
u->access_token, c->is_tls ? "Secure; " : "", 3600 * 24);
mg_http_reply(c, 200, cookie, "{%m:%m}", MG_ESC("user"), MG_ESC(u->name));
}

@halikuosang
Copy link
Author

I have updated the last comment.

This is the zip file containing the screenshot and pcapng. Additional explanations are as follows:
10.10.41.149 Windows IP (Chrome or Edge)
10.10.41.131 Ubuntu 20.04 (./example, http/https server)
pcapng filter rule: ip.addr == 10.10.41.131 and tcp.port == 8000
chrome.png "尝试通过 Set-Cookie 标头设置 Cookie 的操作被禁止了,因为此标头不是通过安全连接发送的,而且会覆盖具有Secure属性的Cookie" This translation into English is "The attempt to set a cookie through the Set-Cookie header was blocked because this header was not sent over a secure connection, and it would overwrite a cookie with the Secure attribute."
debug20240929.zip

@cpq
Copy link
Member

cpq commented Oct 7, 2024

@cpq @robertc2000 #2912 (comment) above and next one below. Is there anything we can do regarding this ?

static void handle_login(struct mg_connection *c, struct user *u) {
char cookie[256];
mg_snprintf(cookie, sizeof(cookie),
"Set-Cookie: access_token=%s; Path=/; "
"%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n",
u->access_token, c->is_tls ? "Secure; " : "", 3600 * 24);
mg_http_reply(c, 200, cookie, "{%m:%m}", MG_ESC("user"), MG_ESC(u->name));
}

Right. Does that mean we need to have two different cookies, one for HTTP and one for HTTPS ?
@halikuosang could you try this change please (it prepends s_ to the TLS cookie value):

static void handle_login(struct mg_connection *c, struct user *u) { 
   char cookie[256]; 
   mg_snprintf(cookie, sizeof(cookie), 
               "Set-Cookie: access_token=%s; Path=/; " 
               "%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n", 
               u->access_token, c->is_tls ? "Secure; " : "", 3600 * 24); 
   mg_http_reply(c, 200, cookie, "{%m:%c%s%M%c}", MG_ESC("user"), '"', c->is_tls ? "s_" : "", MG_ESC(u->name), '"'); 
 } 

@halikuosang
Copy link
Author

@cpq @robertc2000 #2912 (comment) above and next one below. Is there anything we can do regarding this ?

static void handle_login(struct mg_connection *c, struct user *u) {
char cookie[256];
mg_snprintf(cookie, sizeof(cookie),
"Set-Cookie: access_token=%s; Path=/; "
"%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n",
u->access_token, c->is_tls ? "Secure; " : "", 3600 * 24);
mg_http_reply(c, 200, cookie, "{%m:%m}", MG_ESC("user"), MG_ESC(u->name));
}

Right. Does that mean we need to have two different cookies, one for HTTP and one for HTTPS ? @halikuosang could you try this change please (it prepends s_ to the TLS cookie value):

static void handle_login(struct mg_connection *c, struct user *u) { 
   char cookie[256]; 
   mg_snprintf(cookie, sizeof(cookie), 
               "Set-Cookie: access_token=%s; Path=/; " 
               "%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n", 
               u->access_token, c->is_tls ? "Secure; " : "", 3600 * 24); 
   mg_http_reply(c, 200, cookie, "{%m:%c%s%M%c}", MG_ESC("user"), '"', c->is_tls ? "s_" : "", MG_ESC(u->name), '"'); 
 } 

@cpq I replaced this code in net.c and still had the same problem, the modified code did not have any effect

@robertc2000
Copy link
Collaborator

It appears the same cookie name cannot be used both for HTTP and HTTPS simultaneous connections.

Doing this will show the following console log on the HTTP tab.

Cookie “access_token” has been rejected because there is an existing “secure” cookie.

The solution is to have different cookie names for HTTP and HTTPS to avoid any conflict.

static void handle_login(struct mg_connection *c, struct user *u) {
  char cookie[256];
  const char *cookie_name = c->is_tls ? "secure_access_token" : "access_token";
  mg_snprintf(cookie, sizeof(cookie),
              "Set-Cookie: %s=%s; Path=/; "
              "%sHttpOnly; SameSite=Lax; Max-Age=%d\r\n",
              cookie_name, u->access_token, 
              c->is_tls ? "Secure; " : "", 3600 * 24);
  mg_http_reply(c, 200, cookie, "{%m:%m}", MG_ESC("user"), MG_ESC(u->name));
}

@halikuosang Could you please try using the above handle_login function? Let us know if this fixes your issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants