0x00 简介
文章目录
0x01 socket端口开放问题
1、漏洞原理
部分应用使用socket端口作为进程间通信的接口或者实现自定义网络协议。 本地app或者远程攻击者可以通过网络直接连接端口,并且进行功能的调用,导致恶意行为发生。
2、检测方法
-
netstat
命令查看是否使用socket端口。 -
通过三步定位法确定开放端口的应用程序。
第一步,利用netstat寻找感兴趣的开放socket端口。
第二步,将端口转换为十六进制值,查看位于/proc/net/目录下对应的socket套接字状态文件,在其中找到使用该socket的应用的uid。
如15555的十六进制表示为1cc3,协议类型为tcp6,那么查看/proc/net/tcp6文件。注意上面的10115,就是使用该socket的应用的uid。通过这个uid可以得知应用的用户名为u0_a115。
第三步,根据用户名就可以找到应用。
至此,我们就知道开放15555端口的应用为com.qiyi.video,尽管我们还不能分辨出开放该端口的准确进程,但仍然为进一步的漏洞挖掘打下基础。
3、漏洞危害
- 造成任意代码执行
例如如下的代码:
sockfd=socket(AF_INET,SOCK_STREAM,0);
my_addr.sin_family=AF_INET;
my_addr.sin_port=htons(8000);
my_addr.sin_addr.s_addr=htonl(INADDR_ANY);
bzero(&(my_addr.sin_zero),8);
bind(sockfd,(struct sockaddr*)&my_addr,sizeof(struct sockaddr);
listen(sockfd,3);
while(1)
{
sin_size=sizeof(struct sockaddr_in);
new_fd=accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);
do_shell(new_fd); //执行端口发送过来的指令
}
上面的示例,由于高危服务的开放,造成任意代码执行 。
- 造成缓冲区溢出
char input[20];
new_fd=accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);
strcpy(input,new_fd); //未校验输入的长度,可以造成缓冲区溢出
char input[20];
new_fd=accept(sockfd,(struct sockaddr*)&their_addr,&sin_size);
sprintf(input,"aaa+%s",new_fd); //未校验输入的长度,可以造成缓冲区溢出
上面的示例,由于开发的不谨慎,造成缓冲区溢出。
4、修复方案
针对请求做鉴权,并且校验数据的合法性
0x02 SSL证书信任问题
1、漏洞原理
如果重写checkServerTrusted
函数,返回null或者空,则会造成APP信任任何证书。
错误代码如下所示:
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
//没有抛出异常,返回null,信任任何证书
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
2、检测方法
检查checkServerTrusted
函数,返回null
或者空
。
3、相关设置
-
继承关系
- javax.net.ssl.X509TrustManager
- public interface X509TrustManager implements TrustManager
在JSSE中,证书信任管理器类就是实现了接口X509TrustManager的类。该类有以下三个方法。
-
主要方法
- checkClientTrusted(X509Certificate[] chain, String authType)
- 校验客户端证书,若不信任该证书则抛出异常。
- checkServerTrusted(X509Certificate[] chain, String authType)
- 校验服务器端证书,若不信任该证书则抛出异常。
- X509Certificate[] getAcceptedIssuers()
- 返回受信任的X509证书数组。
- checkClientTrusted(X509Certificate[] chain, String authType)
4、漏洞危害
造成APP信任任何证书。
5、修复方案
- 如果APP的安全性要求比较高,请使用证书锁定,例如:
OkHttpClient client = new OkHttpClient.Builder()
.certificatePinner(new CertificatePinner.Builder()
.add("sbbic.com", "sha1/C8xoaOSEzPC6BgGmxAt/EAcsajw=")
.add("closedevice.com", "sha1/T5x9IXmcrQ7YuQxXnxoCmeeQ84c=")
.build())
- 由于证书锁定不灵活,如果需要动态认证,请不要重写函数,在
checkServerTrusted
函数当证书不符合预期的时候,抛出异常。
0x03 明文协议通信
1、漏洞原理
使用http通信或者没有良好加密的自定义协议通信,会使得第三方可以获取传输的数据内容,或者对数据内容进行篡改 。
例如如下的代码:
public String getReultForHttpPost(String name,String pwd) throws ClientProtocolException, IOException{
//服务器 :服务器项目 :servlet名称
String path="http://192.168.0.1:8080/test/test";
HttpPost httpPost=new HttpPost(path);
List<NameValuePair>list=new ArrayList<NameValuePair>();
list.add(new BasicNameValuePair("name", name));
list.add(new BasicNameValuePair("pwd", pwd));
httpPost.setEntity(new UrlEncodedFormEntity(list,HTTP.UTF_8));
String result="";
HttpResponse response=new DefaultHttpClient().execute(httpPost);
if(response.getStatusLine().getStatusCode()==200){
HttpEntity entity=response.getEntity();
result=EntityUtils.toString(entity, HTTP.UTF_8);
}
return result;
}
则会泄露name
和pwd
值到网络中,可以被第三方截取。
2、检测方法
查看是否使用https通信。
3、漏洞危害
泄露敏感信息。
4、修复方案
-
使用https连接并合理的校验证书链。
-
自定义协议请合理使用加密算法,正确保护或者分发秘钥。
0x04 不安全的加密方式
1、漏洞原理
使用AES/DES/DESede
加密算法进行加密时,如果使用ECB模式,DES默认是56位加密密钥,已经不安全。容易受到攻击风险,造成信息泄露。
2、检测方法
查找调用Cipher
类的getInstance
方法,判断是否使用AES/DES/DESede
加密算法(加密算法API默认使用ECB模式)。
3、相关设置
-
继承关系
- java.lang.Object
- java.crypto.Cipher
-
主要方法
-
getInstance(String transformation)
-
getInstance(String transformation, String provider)
-
getInstance(String transformation, Provider provider)
-
4、漏洞危害
使用弱加密算法会大大增加黑客攻击的概率,黑客可能会破解隐私数据、猜解密钥、中 间人攻击等,造成隐私信息的泄漏,甚至造成财产损失。
5、修复方案
- 使用对称加密算法时避免使用DES算法;
- 使用RSA算法加密时不使用
NoPadding
; - IvParameterSpec初始化时,不使用常量
vector
; - 在选择加密模式时避免使用
ECB
模式; - 使用RSA加密时,建议密钥长度大于
1024bit
。 - 使用AES/DES/DESede加密算法时,应显示指定使用CBC或CFB加密模式
0x05 使用硬编码密钥加密
1、漏洞原理
为了增加安全,部分的应用会在http或者https层上再套一层进行加密,一般使用DES或者AES算法。
部分代码为了开发方便,直接将秘钥明文写入代码之中,通过逆向就可以直接得到秘钥。
2、检测方法
先定位到SecretKeySpec()
初始化方法 ,在方法内定位String.getBytes()
,查看String对应的变量。
例如如下的代码:
private static final String key = "shenzhoucar123123";
public CryptAESNew(){
super();
this.aes = null;
this.iv = new byte[]{
10,1,11,5,4,15,7,9,23,3,1,6,8,12,13,91}; //泄露IV
String v5 = "shenzhoucar123123"; //泄露秘钥
byte[] v0 = new byte[16];
try{
byte[]v4 = v5.getBytes("UTF-8");
int v2;
for(v2 = 0; v2 < v5.length(); ++v2){
if(v2 >= v0.length){
break;
}
v0[v2] = v4[v2];
}
}
IvParameterSpec v3 = new IvParameterSpec(this.iv);
this.sKey = new SecretKeySpec(v0,"AES");
this.eCipher = Ciper.getInstance("AES/CBC/PKCS7Padding"); //泄露加解密方式
this.eCipher.init(1,this.sKey,((AlgorithmParameterSpec)v3));
this.dCipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
this.dCipher.init(2,this.sKey,((AlgorithmParameterSpec)v3));
return;
}
可以直接看到v5就是秘钥值,进行流量的解密。
3、相关设置
-
继承关系
- java.lang.Object
- javax.crypto.spec.SecretKeySpec
-
主要方法
-
SecretKeySpec(byte[ ] key, String algorithm)
4、漏洞危害
在通信中使用硬编码秘钥加密通信,攻击者可以通过逆向程序的方法拿到硬编码秘钥,造成威胁。
5、修复方案
- 尽量避免使用硬编码秘钥,合理使用秘钥交换协议分配秘钥。
- 必须使用硬编码秘钥的情况下,使用Trustzone或者白盒秘钥保护秘钥。
0x06 参考
https://blog.csdn.net/lanceleo/article/details/48828367
https://blog.csdn.net/u013107656/article/details/52066446
https://blog.csdn.net/u013107656/article/details/51997957