发现自己看雪还是临时会员。
ALICTF无线安全第一题我的解答,发到这里了。献丑了。
ALICTF2014 无线安全题目1解答:
1 程序漏洞
1.1 漏洞1: 存在一个"exported"的Activity组件
漏洞1描述:
com.tg.ali.testapp.TBActivity是“exported”的,“exported”表示组件可以被其他App使用,TBActivity是登录后显示的页面,属性不能是exported,否则存在着危险。
![](upload/attach/201409/600491_fa1dd1127cbbd3b1.png)
漏洞1验证:
证明1:在电脑的Drozer控制台里面输入以下命令可以远程打开TBActivity:
run app.activity.start --component com.tg.ali.testapp com.tg.ali.testapp.TBActivity
证明2:查看程序的AndroidManifest.xml文件,TBActivity设置exported属性是“true”:
漏洞1修复方案:
建议在Androidmanifest.xml显示声明.TBActivity组件的“exported”属性为“false”。
1.2 漏洞2:程序是"debuggable",可调试的
漏洞2描述:
程序是可调试的,可以用gdb,andbug进行调试,存在着信息泄漏。
漏洞2验证:
证明1: 用andbug可以附件到com.tg.ali.testapp的进程进行调试,如图所示:
证明2:使用dex2jar和jd-gui反汇编ws_t2.apk程序,查看反编译源码,在com.tg.ali.testapp包的BuidConfig类的DEBUG是true
漏洞2修复方案:
在编译发行版时:将com.tg.ali.testapp包的BuidConfig类的DEBUG改为false,即:
public static final boolean DEBUG = true;
改为:public static final boolean DEBUG = false;
1.3 漏洞3:日志输出用户名和加密后的密码
漏洞3描述:
应用的输出日志中输出了用户名和加密后的密码,造成信息泄漏。
漏洞3验证:
证明1:在adb shell中输入以下命令,可看到上图中的内容。
adb shell logcat | grep 1641
1641是com.tg.ali.testapp的进程号。
证明2:查看反编译的源码,在com.tg.ali.testapp包的MainActivity类里发现了日志输出语句:
Log.v("test", "userNameText=" + str3 + "\tencryptPassword" + str4);
漏洞3修复方案:
删除在com.tg.ali.testapp包的MainActivity类日志输出语句:
Log.v("test", "userNameText=" + str3 + "\tencryptPassword" + str4);
或者改为Log.d()只在调试模式下输出日志,发行模式下不输出。
1.4 漏洞4:用户名密码存储在本地数据库
漏洞4描述:
用户名和加密后的密码信息,直接存在了设备的/data/data/com.tg.ali.testapp/databases/目录下的userdb.db文件中,可被下载和打开。
漏洞4验证:
使用以下命令可将userdb.db文件下载到电脑中,然后用sqlite数据库相关工具可以轻松打开。
adb pull /data/data/com.tg.ali.testapp/databases/userdb.db
![](upload/attach/201409/600491_6f97d12efa8d12f7.png)
上图是我Kubuntu 14.04系统下使用的Sqliteman软件。
漏洞4修复方案:
建议用户信息不要本地存储,存储在远端服务器,传输时使用Https加密通信。
1.5 漏洞5:RSAKey存储在本地
漏洞5描述:
用于加密用户密码的RSAKey直接存储在/data/data/com.tg.ali.testapp/shared_prefs/目录的RsaKey.xml文件中。经分析知,puStr标签内容是公钥,prStr标签内容是私钥。而分析反编译的方法知道,密码的加密是用RSA公钥加密。
漏洞5验证:
如上图所示。
漏洞5修复方案:
将密钥存储在密钥库中,同时密钥库要加上密码。
1.6漏洞6:存在WebView漏洞
漏洞6描述:
在com.tg.ali.testapp包的TBActivity类里面,WebView组件调用了addJavascriptInterface方法,主要用于将Java类或方法导出以供JavaScript调用。但是,JavaScript在调用导出的Java类时,可通过反射执行任意JAVA代码。
漏洞6修复方案:
1、确保只在访问可信页面数据时才使用addJavascriptInterface。
2、在调用Java对象方法前对参数进行检查,避免执行恶意操作。
3、在载入页面时对URL进行白名单判定,只有存在白名单中的域才允许导出或调用相关的Java类或方法。
4、本程序使用的SDK版本是10,已经比较老了,建议使用SDK版本17以上的,用JavascriptInterface代替addJavascriptInterface。
1.7 漏洞7:相同用户名可以重新注册,变相修改用户密码
漏洞7描述:
直接用相同的用户名,可以重新输入密码注册用户,并且可以登录,等于是变相任意修改用户的密码。数据库中存在着相同用户名的不同密码。
修复方案
在注册用户,往数据库里面添加用户时,检查用户名是否重复,如果重复,则添加失败。
2 逻辑缺陷
2.1 逻辑缺陷1:注册时用户名、密码输入为空时也可以成功注册,并且空用户和密码也能登录成功
逻辑缺陷1描述:
在注册界面,直接点击注册按钮,可以成功注册,原因是com.tg.ali.testapp包的RegisterActivity类的saveNewUserInfo()方法里面的判断为用户名、密码为空条件用的是用==null,而这个是判断String对象是否为空,而应用需要要判断String对象的内容是否为空,应该用String类的equals()方法。并且为空的时候saveNewUserInfo()应该停止往下执行,返回false。
逻辑缺陷1修复方案:
将为com.tg.ali.testapp包的RegisterActivity类的saveNewUserInfo()中的语句:
if (paramString1 == null)
Toast.makeText(this, "用户名不能为空!", 0).show();
if ((paramString2 == null) || (paramString3 == null))
Toast.makeText(this, "密码不能为空!", 0).show();
改为:
if (paramString1 == null || paramString1.equals(""))
{
Toast.makeText(this, "用户名不能为空!", 0).show();
return false;
}
if ((paramString2 == null) || (paramString2.equals(""))
|| (paramString3 == null) || (paramString3.equals("")))
{
Toast.makeText(this, "密码不能为空!", 0).show();
return false;
}
2.2 逻辑缺陷2:注册时没有检查前后两次输入的密码是否一致
逻辑缺陷2描述:
注册时没有检查前后两次输入的密码是否一致,即使不一致也能注册成功,存储的密码是第一次输入的密码。
逻辑缺陷2修复方案:
将为com.tg.ali.testapp包的RegisterActivity类的saveNewUserInfo()判断密码是否为空的if语句后添加判断两个密码是否相同的if语句,如果不相同,则用Toast提示前后输入的两个密码不一致,并返回false,即在判断输入密码是否为空的语句后面新添加以下语句:
if (!paramString2.equals(paramString3))
{
Toast.makeText(this, "输入的密码不一致,请重新输入", 0).show();
return false;
}
2.3 逻辑缺陷3:为com.tg.ali.testapp包的RegisterActivity类的saveNewUserInfo()方法中的while()循环存在问题
逻辑缺陷3描述:
saveNewUserInfo()方法中的while()循环在执行时,中间有return bool语句,直接就从中循环语句里面返回了,return bool后面的语句
String str4 = localSharedPreferences.getString("puStr", null);
String str5 = localSharedPreferences.getString("prStr", null);
localPublicKey = RsaUtil.getPublicKeyFromString(str4);
RsaUtil.getPrivateKeyFromString(str5);
根本不会执行。并且while循环中的new HashMap()根本没有任何作用。
逻辑缺陷3修复方案:
需将while循环去掉,同时将原while循环里面return bool后面的语句写在前面,即由:
while (true)
{
String[] arrayOfString = { paramString1, RsaUtil.encrypt(paramString2, localPublicKey) };
bool = new UserInfoDao(this).addUser(arrayOfString);
new HashMap();
return bool;
String str4 = localSharedPreferences.getString("puStr", null);
String str5 = localSharedPreferences.getString("prStr", null);
localPublicKey = RsaUtil.getPublicKeyFromString(str4);
RsaUtil.getPrivateKeyFromString(str5);
}
改为:
String str4 = localSharedPreferences.getString("puStr", null);
String str5 = localSharedPreferences.getString("prStr", null);
localPublicKey = RsaUtil.getPublicKeyFromString(str4);
RsaUtil.getPrivateKeyFromString(str5);
String[] arrayOfString = { paramString1, RsaUtil.encrypt(paramString2, localPublicKey) };
bool = new UserInfoDao(this).addUser(arrayOfString);
return bool;
3 设计问题
3.1 问题1:代码没有进行混淆
可能攻击:
应用没有经过混淆,很容易用dex2jar和jd-gui工具恢复出源码,容易遭受逆向工程。
修复方案:
使用ProGuard对应用进行混淆打包。
3.2 问题2:客户端没有进行完整性校验,可被注入代码
可能攻击:
应用被逆向,然后重新被注入恶意代码,进行二次打包。
修复方案:
增加完整性校验逻辑,生成应用的签名,程序运行时,先对自己做完整性检测,生成的签名与原签名做对比,或者将生成的签名发送给服务器,让服务器判断是否被二次打包,如果是程序提示用户软件被篡改,并推出。
3.3 问题3:用户名、加密后的密码、RSAKey等敏感信息在本地存储
可能攻击:
造成信息泄漏。
修复方案:
3.4 问题4:与服务器通信没有使用https
可能攻击:
与服务器的通信内容容易泄漏,容易遭受中间人攻击。
修复方案:
使用Https与服务器进行通信。
3.5 问题5:注册时没有过滤检查简单密码
可能攻击:
如果用简单密码注册,容易被暴力破解。
修复方案:
在设计时应该设计密码检查逻辑,过滤过短、纯数字或者纯字母的简单密码。
3.6 问题6:密码输入时明文显示
可能攻击:
被恶意软件截屏,获得用户名和密码
修复方案:
在activity_mian.xml和register.xml等UI文件中,涉及密码输入的EditText添加属性android:inputType="textPassword"。
3.7 问题7:注册用户或者填写密码时不能输入“~”和“ ` ”
3.7 用户名注册时没有过滤一些特殊符号
可能攻击:
容易被Fuzz。
修复方案:
增加过滤过滤用户名使用的逻辑。
3.8 问题8:注册时用户名密码没有长度限制
可能攻击:
缓冲区溢出。
修复方案:
对用户名密码的长度范围进行限制。
3.9 问题9:登录或者注册时输入过长的用户名或者密码导致“登录”、“注册”等按钮移动到屏幕以外
可能攻击:
纯设计问题,没有可攻击方法。
修复方案:
1 同3.8。
2 限制输入框的大小。
3.10 问题10:用户信息数据表userinfo设计过于简单,没有主键,没有用户名重复检查
可能攻击:
同漏洞1.7。
修复方案:
在数据库设计时,设计用户信息表时指定用户名为主键,并且不可重复。或者指定唯一的ID。
3.11 问题11:登录时从数据库获取用户信息只返回true或者false
可能攻击:
可给应用注入代码,使com.tg.ali.testapp包里的UserInfoDao类中的getUserInfo()一直返回true,直接暴力破解应用。
修复方案:
1 做加固或完成性校验,防止暴力破解
2 使getUserInfo()真正返回一些有用的用户信息,而不是只检查用户从存在与否。
3.12 问题11:原始的公钥私钥只有了BASE64编码算法进行加密,BASE64字符映射表公开,不能有效保护密钥
可能攻击:
根据存储的RsaKey.xml中可以还原出原始的RSA公钥私钥。
修复方案:
建议使用RSA算法再对加密密码的的RSA原始密钥进行加密。
3.13 问题12:加密解密算法的实现都包括在了应用中,没有充分利用RSA的非对称加密特点
可能攻击:
根据应用中存在的公钥私钥,和反编译出来的源码,完成可以重构本应用的加密算法,然后制作破解词典,可以进行暴力破解。
修复方案:
要充分利用RSA加密算法的特点,并在服务器端也做相应的措施,
3.14 问题14:登录后缺乏会话管理
[招生]科锐逆向工程师培训(2025年3月11日实地,远程教学同时开班, 第52期)!