Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
ea54b55
Fixing issue with ZEPPELIN-173: Zeppelin websocket server is vulnerab…
Aug 12, 2015
013f22d
Fixing issue with ZEPPELIN-173: Zeppelin websocket server is vulnerab…
Aug 13, 2015
08ff369
unecessary file
djoelz Aug 13, 2015
61e857d
Fixing Rest request lack of Origin validation bug, Added tests that u…
Aug 15, 2015
cecbab8
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 16, 2015
df324de
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 16, 2015
a00adc2
Merge pull request #1 from apache/master
djoelz Aug 19, 2015
47902a6
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 20, 2015
5ff1a47
Merge branch 'masterOrigin'
Aug 20, 2015
52eb1bd
Merge branch 'master' of https://github.com/apache/incubator-zeppelin…
Aug 20, 2015
faa6204
Merge branch 'apache-master'
Aug 20, 2015
7ecf7e9
Merge branch 'master' of https://github.com/djoelz/incubator-zeppelin
Aug 20, 2015
1f851c0
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 20, 2015
3d6ce2e
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 20, 2015
bcb1ac1
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 20, 2015
3795de7
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 20, 2015
4ae9129
Fixing null reference
Aug 20, 2015
b2b418a
Fixing cross origin bug for rest calls that allow a malicious user to…
Aug 20, 2015
b7bb7bf
Fixing Styling
Aug 20, 2015
9260d5d
Fixing adding the origin header for get and post tests.
Aug 20, 2015
2887f0d
Renaming tests to singular name so plugin can detect and run
Aug 21, 2015
e9d8384
Retrying due to git download issue with build
Aug 21, 2015
625b54e
Fixing unit test that reads from a file but initializes to a default …
Aug 21, 2015
989f1e0
Retrying build as it seems ZeppelinIT failed for not reason.
Aug 21, 2015
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions conf/zeppelin-site.xml.template
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,11 @@
</property>
-->

<property>
<name>zeppelin.server.allowed.origins</name>
<value>*</value>
<description>Allowed sources for REST and WebSocket requests (i.e. http://onehost:8080,http://otherhost.com). If you leave * you are vulnerable to https://issues.apache.org/jira/browse/ZEPPELIN-173</description>
</property>

</configuration>

Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,14 @@

package org.apache.zeppelin.server;

import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.utils.SecurityUtils;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.Locale;

Expand All @@ -41,11 +46,15 @@ public class CorsFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
String sourceHost = request.getServerName();
String currentHost = java.net.InetAddress.getLocalHost().getHostName();
String sourceHost = ((HttpServletRequest) request).getHeader("Origin");
String origin = "";
if (currentHost.equals(sourceHost) || "localhost".equals(sourceHost)) {
origin = ((HttpServletRequest) request).getHeader("Origin");

try {
if (SecurityUtils.isValidOrigin(sourceHost, ZeppelinConfiguration.create())) {
origin = sourceHost;
}
} catch (URISyntaxException e) {
e.printStackTrace();
}

if (((HttpServletRequest) request).getMethod().equals("OPTIONS")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.conf.ZeppelinConfiguration.ConfVars;
import org.apache.zeppelin.display.AngularObject;
Expand All @@ -43,12 +41,12 @@
import org.apache.zeppelin.scheduler.JobListener;
import org.apache.zeppelin.server.ZeppelinServer;
import org.apache.zeppelin.socket.Message.OP;
import org.apache.zeppelin.utils.SecurityUtils;
import org.eclipse.jetty.websocket.WebSocket;
import org.eclipse.jetty.websocket.WebSocketServlet;
import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Strings;
import com.google.gson.Gson;
/**
Expand All @@ -69,24 +67,15 @@ private Notebook notebook() {
}
@Override
public boolean checkOrigin(HttpServletRequest request, String origin) {
URI sourceUri = null;
String currentHost = null;

try {
sourceUri = new URI(origin);
currentHost = java.net.InetAddress.getLocalHost().getHostName();
return SecurityUtils.isValidOrigin(origin, ZeppelinConfiguration.create());
} catch (UnknownHostException e) {
e.printStackTrace();
}
catch (URISyntaxException e) {
} catch (URISyntaxException e) {
e.printStackTrace();
}

String sourceHost = sourceUri.getHost();
if (currentHost.equals(sourceHost) || "localhost".equals(sourceHost)) {
return true;
}

return false;
}

Expand Down Expand Up @@ -300,6 +289,7 @@ private void broadcastNoteList() {
List<Map<String, String>> notesInfo = new LinkedList<>();
for (Note note : notes) {
Map<String, String> info = new HashMap<>();

if (hideHomeScreenNotebookFromList && note.id().equals(homescreenNotebookId)) {
continue;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zeppelin.utils;

import org.apache.zeppelin.conf.ZeppelinConfiguration;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;

/**
* Created by joelz on 8/19/15.
*/
public class SecurityUtils {
public static Boolean isValidOrigin(String sourceHost, ZeppelinConfiguration conf)
throws UnknownHostException, URISyntaxException {
if (sourceHost == null){
return false;
}

URI sourceHostUri = new URI(sourceHost);
String currentHost = java.net.InetAddress.getLocalHost().getHostName().toLowerCase();
if (currentHost.equals(sourceHostUri.getHost()) ||
"localhost".equals(sourceHostUri.getHost()) ||
conf.getAllowedOrigins().contains(sourceHost) ||
conf.getAllowedOrigins().contains("*")) {
return true;
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,8 @@ protected static GetMethod httpGet(String path) throws IOException {
LOG.info("Connecting to {}", url + path);
HttpClient httpClient = new HttpClient();
GetMethod getMethod = new GetMethod(url + path);
httpClient.executeMethod(getMethod);
getMethod.addRequestHeader("Origin", "http://localhost:8080");
httpClient.executeMethod(getMethod);
LOG.info("{} - {}", getMethod.getStatusCode(), getMethod.getStatusText());
return getMethod;
}
Expand All @@ -236,6 +237,7 @@ protected static PostMethod httpPost(String path, String body) throws IOExceptio
LOG.info("Connecting to {}", url + path);
HttpClient httpClient = new HttpClient();
PostMethod postMethod = new PostMethod(url + path);
postMethod.addRequestHeader("Origin", "http://localhost:8080");
RequestEntity entity = new ByteArrayRequestEntity(body.getBytes("UTF-8"));
postMethod.setRequestEntity(entity);
httpClient.executeMethod(postMethod);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ public void testInterpreterAutoBinding() throws IOException {
// create note
Note note = ZeppelinServer.notebook.createNote();

// check interpreter is bindded
// check interpreter is binded
GetMethod get = httpGet("/notebook/interpreter/bind/"+note.id());
assertThat(get, isAllowed());
get.addRequestHeader("Origin", "http://localhost");
Map<String, Object> resp = gson.fromJson(get.getResponseBodyAsString(), new TypeToken<Map<String, Object>>(){}.getType());
List<Map<String, String>> body = (List<Map<String, String>>) resp.get("body");
assertTrue(0 < body.size());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.zeppelin.security;

import junit.framework.Assert;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.zeppelin.conf.ZeppelinConfiguration;
import org.apache.zeppelin.utils.SecurityUtils;
import org.junit.Test;

import java.net.URISyntaxException;
import java.net.UnknownHostException;

/**
* Created by joelz on 8/19/15.
*/
public class SecurityUtilsTest {
@Test
public void isInvalid() throws URISyntaxException, UnknownHostException {
Assert.assertFalse(SecurityUtils.isValidOrigin("http://127.0.1.1", ZeppelinConfiguration.create()));
}

@Test
public void isInvalidFromConfig() throws URISyntaxException, UnknownHostException, ConfigurationException {
Assert.assertFalse(
SecurityUtils.isValidOrigin("http://otherinvalidhost.com",
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site.xml"))));
}

@Test
public void isLocalhost() throws URISyntaxException, UnknownHostException {
Assert.assertTrue(SecurityUtils.isValidOrigin("http://localhost", ZeppelinConfiguration.create()));
}

@Test
public void isLocalMachine() throws URISyntaxException, UnknownHostException {
Assert.assertTrue(SecurityUtils.isValidOrigin(
"http://" + java.net.InetAddress.getLocalHost().getHostName(),
ZeppelinConfiguration.create()));
}

@Test
public void isValidFromConfig() throws URISyntaxException, UnknownHostException, ConfigurationException {
Assert.assertTrue(
SecurityUtils.isValidOrigin("http://otherhost.com",
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site.xml"))));
}

@Test
public void isValidFromStar() throws URISyntaxException, UnknownHostException, ConfigurationException {
Assert.assertTrue(
SecurityUtils.isValidOrigin("http://anyhost.com",
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site-star.xml"))));
}

@Test
public void nullOrigin() throws URISyntaxException, UnknownHostException, ConfigurationException {
Assert.assertFalse(
SecurityUtils.isValidOrigin(null,
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site.xml"))));
}

@Test
public void emptyOrigin() throws URISyntaxException, UnknownHostException, ConfigurationException {
Assert.assertFalse(
SecurityUtils.isValidOrigin("",
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site.xml"))));
}

@Test
public void notAURIOrigin() throws URISyntaxException, UnknownHostException, ConfigurationException {
Assert.assertFalse(
SecurityUtils.isValidOrigin("test123",
new ZeppelinConfiguration(this.getClass().getResource("/zeppelin-site.xml"))));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
* @author joelz
*
*/
public class CorsFilterTests {
public class CorsFilterTest {

public static String[] headers = new String[8];
public static Integer count = 0;
Expand All @@ -54,7 +54,7 @@ public void ValidCorsFilterTest() throws IOException, ServletException {
when(mockRequest.getHeader("Origin")).thenReturn("http://localhost:8080");
when(mockRequest.getMethod()).thenReturn("Empty");
when(mockRequest.getServerName()).thenReturn("localhost");

count = 0;

doAnswer(new Answer() {
@Override
Expand All @@ -79,7 +79,6 @@ public void InvalidCorsFilterTest() throws IOException, ServletException {
when(mockRequest.getMethod()).thenReturn("Empty");
when(mockRequest.getServerName()).thenReturn("evillocalhost");


doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
import org.junit.Assert;
import org.junit.Test;

import java.io.IOException;
import org.junit.Assert;
import org.junit.Test;

import java.net.UnknownHostException;

/**
Expand All @@ -31,7 +35,7 @@
* @author joelz
*
*/
public class NotebookServerTests {
public class NotebookServerTest {

@Test
public void CheckOrigin() throws UnknownHostException {
Expand All @@ -45,6 +49,4 @@ public void CheckInvalidOrigin(){
NotebookServer server = new NotebookServer();
Assert.assertFalse(server.checkOrigin(new TestHttpServletRequest(), "http://evillocalhost:8080"));
}


}
}
Loading