[vlc-devel] [PATCH 1/2] httpd: mitigate CRSF attack by checking request Origin
Pierre Lamot
pierre at videolabs.io
Wed Jan 31 18:38:01 CET 2018
---
src/network/httpd.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 52 insertions(+), 1 deletion(-)
diff --git a/src/network/httpd.c b/src/network/httpd.c
index d9237ebb9c..cfd947ad94 100644
--- a/src/network/httpd.c
+++ b/src/network/httpd.c
@@ -81,6 +81,7 @@ struct httpd_host_t
int *fds;
unsigned nfd;
unsigned port;
+ char *psz_origin;
vlc_thread_t thread;
vlc_mutex_t lock;
@@ -971,6 +972,7 @@ static httpd_host_t *httpd_HostCreate(vlc_object_t *p_this,
host->i_client = 0;
host->client = NULL;
host->p_tls = p_tls;
+ host->psz_origin = url.psz_host ? strdup( url.psz_host ) : NULL;
/* create the thread */
if (vlc_clone(&host->thread, httpd_HostThread, host,
@@ -1040,6 +1042,8 @@ void httpd_HostDelete(httpd_host_t *host)
net_ListenClose(host->fds);
vlc_cond_destroy(&host->wait);
vlc_mutex_destroy(&host->lock);
+ if ( host->psz_origin )
+ free( host->psz_origin );
vlc_object_release(host);
vlc_mutex_unlock(&httpd.mutex);
}
@@ -1687,6 +1691,41 @@ auth_failed:
return false;
}
+//https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#Verifying_Same_Origin_with_Standard_Headers
+static bool httpdOriginOk( const httpd_host_t *p_host, const httpd_message_t *p_query )
+{
+ char* psz_source_origin = NULL;
+ char* psz_target_origin = NULL;
+
+ const char* psz_origin = NULL;
+ const char* psz_referer = NULL;
+ if ( ( psz_origin = httpd_MsgGet( p_query, "Origin") ) != NULL )
+ psz_source_origin = strdup( psz_origin );
+ else if ( ( psz_referer = httpd_MsgGet( p_query, "Referer" ) ) != NULL ) {
+ vlc_url_t referer_url;
+ vlc_UrlParse( &referer_url, psz_referer );
+ psz_source_origin = strdup( referer_url.psz_host );
+ vlc_UrlClean( &referer_url );
+ } else //unknowned source origin
+ return true;
+
+ const char* psz_host = NULL;
+ if ( p_host->psz_origin ) {
+ psz_target_origin = strdup( p_host->psz_origin );
+ } else if ( ( psz_host = httpd_MsgGet( p_query, "Host" ) ) != NULL ) {
+ psz_target_origin = strndup( psz_host, strcspn(psz_host, ":") );
+ } else { //unknowned target origin
+ free( psz_source_origin );
+ return true;
+ }
+
+ bool ret = (strcmp( psz_source_origin, psz_target_origin ) == 0);
+ free( psz_source_origin );
+ free( psz_target_origin );
+ return ret;
+}
+
+
static void httpdLoop(httpd_host_t *host)
{
struct pollfd ufd[host->nfd + host->i_client];
@@ -1821,6 +1860,7 @@ static void httpdLoop(httpd_host_t *host)
default: {
int i_msg = query->i_type;
bool b_auth_failed = false;
+ bool b_crsf_failed = false;
/* Search the url and trigger callbacks */
for (int i = 0; i < host->i_url; i++) {
@@ -1835,8 +1875,17 @@ static void httpdLoop(httpd_host_t *host)
b_auth_failed = !httpdAuthOk(url->psz_user,
url->psz_password,
httpd_MsgGet(query, "Authorization")); /* BASIC id */
+
if (b_auth_failed)
break;
+
+ if ( query->i_proto == HTTPD_PROTO_HTTP )
+ {
+ b_crsf_failed = !httpdOriginOk( host, query );
+
+ if ( b_crsf_failed )
+ break;
+ }
}
if (url->catch[i_msg].cb(url->catch[i_msg].p_sys, cl, answer, query))
@@ -1858,7 +1907,9 @@ static void httpdLoop(httpd_host_t *host)
answer->i_type = HTTPD_MSG_ANSWER;
answer->i_version= 0;
- if (b_auth_failed) {
+ if ( b_crsf_failed ) {
+ answer->i_status = 403;
+ } else if ( b_auth_failed ) {
httpd_MsgAdd(answer, "WWW-Authenticate",
"Basic realm=\"VLC stream\"");
answer->i_status = 401;
--
2.14.1
More information about the vlc-devel
mailing list