- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试找到一种解决方案来获取 SessionID 和更重要的 SessionKey。我已经找到了一个基于 Java 的解决方案:
http://jsslkeylog.sourceforge.net
它使用以下类来记录 RSA-SessionKey:
/**
* Transformer to transform <tt>RSAClientKeyExchange</tt> and
* <tt>PreMasterSecret</tt> classes to log <tt>RSA</tt> values.
*/
public class RSAClientKeyExchangeTransformer extends AbstractTransformer {
public RSAClientKeyExchangeTransformer(String className) {
super(className, "<init>");
}
@Override
protected void visitEndOfMethod(MethodVisitor mv, String desc) {
String preMasterType = "Ljavax/crypto/SecretKey;";
if (className.endsWith("/PreMasterSecret")) {
preMasterType = "[B";
}
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "encrypted", "[B");
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETFIELD, className, "preMaster", preMasterType);
mv.visitMethodInsn(INVOKESTATIC, className, "$LogWriter$logRSA", "([B" + preMasterType + ")V");
}
}
在我的 android 应用程序中,我使用 DefaultHttpClient (org.apache.http.impl.client) 建立 HTTPS 连接。对于此连接,我试图找到 SessionKey。有人知道是否可以使用 android/java 方法读出 key 吗?如果没有,有人知道 key 生成是在哪里实现的吗?
最佳答案
我不认为这可以通过公共(public) API 完成。您可以获取 session ID,但没有公共(public)接口(interface)来获取 key 。
但是,我能够结合使用反射和 native 代码来访问底层 OpenSSL struct ,其中包含 session ID 和主 key 。所以这是可能的,但它一点也不安全,因为隐藏的成员和库不能保证保持不变。事实上,看起来 OpenSSL master 分支上的结构布局已经改变,因此如果/当它被拉入 Android 时,下面的解析代码将需要更新。
我使用 URL.openConnection()
而不是 DefaultHttpClient
来建立 HTTPS 连接,因为后者现在已被弃用。这是调用 URL.openConnection()
并替换默认的 SSLSocketFactory
的类(这里没什么有趣的):
public class MyConnection implements Runnable {
@Override
public void run() {
try {
// Create the connection.
URL url = new URL("https://www.google.com");
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
// Replace the default SSLSocketFactory with our own.
MySSLSocketFactory sslSocketFactory = new MySSLSocketFactory();
urlConnection.setSSLSocketFactory(sslSocketFactory);
// Establish the TLS connection.
int statusCode = urlConnection.getResponseCode();
Log.i("MyConnection", String.format("status %d", statusCode));
// Get SSL details from the captured socket.
sslSocketFactory.getSessionInfo();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这里是自定义 SSLSocketFactory
,大部分的魔法都在这里。它所做的只是将覆盖的方法转发给真正的 SSLSocketFactory
,缓存创建的 SSLSocket
实例。还有两个新的(未覆盖的)方法 - 下面进一步显示的 native 方法和 getSessionInfo()
使用 SSLSocket
上的反射来获取 native OpenSSL ssl_session_st
指针并解析(和记录)感兴趣的字段。请注意,您可以使用支持的 SSLSession.getId()
获取 session ID ;它正在获取需要偷偷摸摸的 key 。
// Use Decorator pattern to capture the SSL socket from the default SSLSocketFactory.
class MySSLSocketFactory extends SSLSocketFactory {
// Load NDK shared library.
static {
System.loadLibrary("my_native_helper");
}
// All overridden methods will be forwarded to the real SSLSocketFactory.
// The only addition is that the SSLSocket returned by createSocket() is
// cached.
SSLSocketFactory realFactory_ = HttpsURLConnection.getDefaultSSLSocketFactory();
SSLSocket s_;
// This native method copies data from a native pointer into a ByteBuffer.
native void readNative(long pointer, ByteBuffer dst);
// Use the cached SSLSocket to access native OpenSSL session data.
void getSessionInfo() throws NoSuchFieldException, IllegalAccessException {
// Get the protected OpenSSL ssl_session_st pointer. Note that this
// is not part of the API and could change across Android versions.
// See https://android.googlesource.com/platform/external/conscrypt/+/lollipop-mr1-dev/src/main/java/org/conscrypt/OpenSSLSessionImpl.java
SSLSession session = s_.getSession();
Field field = session.getClass().getDeclaredField("sslSessionNativePointer");
field.setAccessible(true);
long sessionPointer = field.getLong(session);
// Read as many bytes as we need from the native pointer.
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(104);
byteBuffer.order(ByteOrder.nativeOrder());
readNative(sessionPointer, byteBuffer);
// Parse the OpenSSL ssl_session_st. Note that the layout of this structure
// may change with OpenSSL versions and different compilers/platforms (e.g.
// 32-bit vs. 64-bit).
// See https://github.com/openssl/openssl/blob/OpenSSL_1_0_0-stable/ssl/ssl.h#L451
IntBuffer intBuffer = byteBuffer.asIntBuffer();
Log.i("MyConnection", String.format("SSL version %04x", intBuffer.get(0)));
int master_key_length = intBuffer.get(4);
String master_key = "";
for (int i = 0; i < master_key_length; ++i)
master_key += String.format("%02x", byteBuffer.get(20 + i));
Log.i("MyConnection", String.format("Master key %s", master_key));
int session_id_length = intBuffer.get(17);
String session_id = "";
for (int i = 0; i < session_id_length; ++i)
session_id += String.format("%02x", byteBuffer.get(72 + i));
Log.i("MyConnection", String.format("Session ID %s", session_id));
}
@Override
public String[] getDefaultCipherSuites() {
return realFactory_.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return realFactory_.getSupportedCipherSuites();
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
s_ = (SSLSocket)realFactory_.createSocket(s, host, port, autoClose);
return s_;
}
@Override
public Socket createSocket(String host, int port) throws IOException {
s_ = (SSLSocket)realFactory_.createSocket(host, port);
return s_;
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
s_ = (SSLSocket)realFactory_.createSocket(host, port, localHost, localPort);
return s_;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
s_ = (SSLSocket)realFactory_.createSocket(host, port);
return s_;
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
s_ = (SSLSocket)realFactory_.createSocket(address, port, localAddress, localPort);
return s_;
}
}
最后,这里是 native C 代码,可以从 native 指针将内存读入 ByteBuffer。这需要使用 Android NDK 构建并加载,如 MySSLSocketFactory
顶部所示。
#include <jni.h>
#include <string.h>
JNIEXPORT
void JNICALL Java_com_example_mysocketfactory_MySSLSocketFactory_readNative(
JNIEnv *env, jobject o,
jlong pointer, jobject buffer) {
const char *p = (const char *)pointer;
memcpy(
(*env)->GetDirectBufferAddress(env, buffer),
p,
(*env)->GetDirectBufferCapacity(env, buffer));
}
就是这样。在我的 KitKat 设备上调用 MyConnection.run()
时,日志显示:
I/MyConnection﹕ status 200
I/MyConnection﹕ SSL version 0301
I/MyConnection﹕ Master key 81ef39c5f8f7f796a34b307ff453511378fd081d14c37eb2e912fa829edf280e0fa7a499c370fdc156b8499758373d67
I/MyConnection﹕ Session ID b9ee4ae0c7738909430d47e9b0d6d60420d34a17d08181f21996e55a463aa5cf
我确实对 DefaultHttpClient
做了一个简短的尝试,但是当我不知道如何访问默认的 SchemeRegistry 时放弃了它。 .我认为这可以通过在构造 DefaultHttpClient
时指定 ClientConnectionManager
来完成,但我不想再继续使用已弃用的路径。如果您想尝试,那么您可能会使用类似的方法来拦截 SSLSessionImpl
处理连接的实例。此类有一个 master_secret
成员,因此不需要本地代码,只需要反射(此代码路径不使用 OpenSSL)。
关于java - 搜索 HTTPS Session 中的 SessionID、SessionKey,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30530077/
我正在使用 cakephp 2.4.7 进行开发,其中我使用 auth 组件进行多次登录(用户和公司登录)。 我的目标是在 beforeFilter 中设置正确的 sessionKey(Auth.Us
我这样设置 session : request.session['mykey']= 33 如何清除它?我只想删除它。 最佳答案 del request.session['mykey'] 关于pyth
我正在尝试找到一种解决方案来获取 SessionID 和更重要的 SessionKey。我已经找到了一个基于 Java 的解决方案: http://jsslkeylog.sourceforge.net
我有一个用 Django 构建的 shopify 应用程序,直到最近它都运行良好。 session 不会在每个请求中持续存在,因此会引发异常,因为在上一个请求中设置的给定键的 session 不存在。
本文整理了Java中org.apache.accumulo.fate.zookeeper.ZooSession.sessionKey()方法的一些代码示例,展示了ZooSession.sessionK
使用 centos 7 Node v8.6.0 npm v5.3.0 尝试在 centos 上设置 etherpad,如下所述:https://github.com/ether/etherpad-li
一些背景 在 asp.net core 中,当使用 SqlServer 存储 session 时,奇怪的是 SqlServer 表中的 Id 列被设置为 sessionKey 的值,这是一个 Guid
我们使用 Apache Shiro 一段时间了,没有出现任何问题,但最近注意到用户在尝试登录或注销我们的应用程序后收到以下错误: java.lang.IllegalArgumentException:
首先我知道 http://blog.kadirpekel.com/2009/11/09/facebook-connect-integration-with-spring-security/ 唯一的问题
我正在开发一个项目,我们将 JAAS/Krb5LoginModule 与 useTicketCache 和 doNotPrompt 以及 allowtgtsessionkey 结合使用。注册表更改以在
我是一名优秀的程序员,十分优秀!