有没有想过黑客如何在任何网站上访问某人的帐户?或者,当您单击从未知地址收到的电子邮件链接时,您的组织要求您不要单击并报告他们的网络安全团队作为强制性安全培训的一部分时,实际会发生什么。原因是为了防止您成为黑客使用的跨站点脚本实践的受害者。让我们创建真正的应用程序并观察使用 java 编程平台的实践。
演示
该演示将展示银行站点的客户如何成为不同跨站点脚本实践的受害者。我们将考虑以下各方:
- 银行网站
- 攻击者网站
- 受害者浏览器
用 Java 创建 HTTP 服务器
银行网站服务器:
package com.banking.application;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class BankHttpServer {
public static void main(String[] args) throws IOException {
System.out.println("Starting banking website server");
com.sun.net.httpserver.HttpServer server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress("localhost", 8001), 0);
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
server.createContext("/banking", new BankHttpServer().new MyHttpHandler());
server.setExecutor(threadPoolExecutor);
server.start();
System.out.println(" Server started on port 8001");
}
public class MyHttpHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
if("GET".equals(exchange.getRequestMethod()) && exchange.getRequestURI().getQuery() != null && exchange.getRequestURI().getQuery().contains("productName")) {
handleResponse(exchange, getSearchPage(exchange.getRequestURI().getQuery()));
} else {
handleResponse(exchange, getDefaultPage());
}
}
private String getDefaultPage() {
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append("<html><body><form action=\"\" method=\"get\">\n" +
" <div>\n" +
" <label for=\"name\">Product Name: </label>\n" +
" <input size=\"100\" type=\"text\" name=\"productName\" id=\"productName\">\n" +
" <input type=\"submit\" value=\"Search\">\n" +
" </div>\n" +
"</form>").append("</body></html>");
return htmlBuilder.toString();
}
private String getSearchPage(String query) {
System.out.println("query: " + query);
query = query.substring(query.indexOf("=") + 1);
String searchParam = query.replace("+", " ");
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append("<html><body><form action=\"search\" method=\"get\">\n" +
" <div><span>").append(searchParam).append("</span></div></body></html>");
return htmlBuilder.toString();
}
private void handleResponse(HttpExchange exchange, String htmlResponse) throws IOException {
OutputStream outputStream = exchange.getResponseBody();
exchange.sendResponseHeaders(200, htmlResponse.length());
outputStream.write(htmlResponse.getBytes());
outputStream.flush();
outputStream.close();
}
}
}
上面的代码创建了一个在 8001 端口上运行的 http 服务器。它在http://localhost:8001/banking提供一个非常基本的网页,如下所示:
网站实现的问题是使用免费输入文本框,允许用户输入任何内容。让我们通过键入银行产品名称来进行示例搜索。
正如我们所见,网站的响应是产品名称,任何黑客都会看到这一点并尝试像这样疯狂的事情:
由于网站按原样返回文本而不进行编码,因此浏览器将其视为合法脚本代码,并执行显示警报消息的代码。这是一个非常强大的黑客线索,可以利用它从本地浏览器会话中读取机密 cookie 并将其发送回黑客。让我们创建另一个服务器应用程序(攻击者的网站),如下所示:
package com.banking.application;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class AttackerHttpServer {
public static void main(String[] args) throws IOException {
System.out.println("Starting attacker website server");
com.sun.net.httpserver.HttpServer server = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress("localhost", 8002), 0);
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
server.createContext("/attacker", new AttackerHttpServer().new MyHttpHandler());
server.setExecutor(threadPoolExecutor);
server.start();
System.out.println(" Server started on port 8002");
}
public class MyHttpHandler implements HttpHandler {
@Override
public void handle(HttpExchange exchange) throws IOException {
handleResponse(exchange, getDefaultPage());
}
private String getDefaultPage() {
StringBuilder htmlBuilder = new StringBuilder();
htmlBuilder.append("alert('Hacked');window.location.href = \"http://localhost:8001/banking\";");
return htmlBuilder.toString();
}
private void handleResponse(HttpExchange exchange, String htmlResponse) throws IOException {
OutputStream outputStream = exchange.getResponseBody();
exchange.getResponseHeaders().add("Content-Type", "application/javascript");
exchange.sendResponseHeaders(200, htmlResponse.length());
outputStream.write(htmlResponse.getBytes());
outputStream.flush();
outputStream.close();
}
}
}
上述代码中的重要代码片段是 getDefaultPage() 方法,它显示警报然后重定向到银行网站:
htmlBuilder.append("alert('Hacked');window.location.href = \"http://localhost:8001/banking\";");
现在可以从银行站点提供的网页执行上述代码,如下所示:
请注意,作为获取请求发送到“银行”网站的 url 嵌入了脚本标签。
现在,我创建了一封包含如下链接的电子邮件,并将其发送给“John”,其中包含一条非常诱人的消息,促使他点击链接:
Bingo!!!,攻击者能够在银行网站的帮助下,在受害者的浏览器上执行他网站上的代码。
解决方案
银行网站如何确保不允许此类攻击?解决方案是使用HTML sanitisation的做法。有一些开源工具和项目可用于清理 HTML 文档,方法是在将其作为响应发回之前删除诸如“<script>、<link>、<object>、<embed>”之类的威胁标签。OWASP是一个在线社区,它在Web 应用程序安全领域产生可免费获得的文章、方法、文档、工具和技术 。一个非常有用的项目是“OWASP Java HTML Sanitizer”,它提供了实现并允许配置自定义策略。
结论
“这个世界上没有什么是免费的,只要记住一切都是有代价的”,所以不要点击来自未知发件人的链接。