(SAST 检测规-5)不良授权和身份验证
(SAST 检测规-5)不良授权和身份验证
严重等级:高危
缺陷详解:
不良或缺失的身份验证方案允许攻击者匿名或以不恰当的权限执行移动应用程序或其后端服务器的功能。由于移动设备的输入模式和网络连接问题,移动应用程序的身份验证功能可能与传统的Web身份验证方案有所不同。
- Web应用与移动应用身份验证差异: 在传统Web应用中,用户需要在线并依赖后端服务器进行实时身份验证。由于传统互联网连接稳定且可预测,用户会持续保持连接。 然而,在移动应用中,用户可能并非在整个会话期间都在线。由于移动互联网连接更不可靠或不可预测,移动应用可能具有必须支持离线验证的需求。这种需求对开发人员实施身份验证和授权方案时的思考产生了深远影响。
问题来源:
- 身份验证问题:由于移动应用可能具有离线运行的需求,开发人员可能在应用代码中实现本地身份验证检查。然而,如果没有妥善的验证,攻击者可以通过逆向工程绕过这些验证,伪造或绕过身份验证,甚至执行不该允许的功能。
- 授权问题:如果授权方案没有强制在服务器端进行验证,而是将授权逻辑保存在客户端,攻击者可以轻松修改会话令牌,甚至绕过客户端的检查,通过后端提交请求来执行特权功能。
导致的结果和风险:
- 绕过身份验证:如果攻击者了解身份验证机制的弱点,他们可能通过伪造会话令牌或绕过身份验证来访问移动应用程序的后端功能。
- 未经授权访问:攻击者可能利用低权限会话令牌在后端服务器中执行本应限制访问的敏感功能,或绕过离线身份验证进行未授权操作。
缓解和预防措施:
- 在服务器端强制身份验证和授权控制:开发人员应假设恶意用户能够绕过客户端的身份验证和授权机制。因此,所有身份验证和授权操作必须在服务器端执行,而不是依赖客户端执行。
- 离线身份验证:如果需要在移动应用中执行离线身份验证,开发人员必须确保所有的身份验证机制都有本地完整性检查,防止未经授权的代码篡改。
- 代码完整性检查:如果应用支持离线模式并需要本地执行验证或授权检查,开发人员应在应用代码中嵌入本地完整性检查机制,检测任何未经授权的代码更改或篡改。
- 会话管理:确保所有会话令牌都经过加密处理,且具有严格的生命周期管理策略。避免将会话管理和授权逻辑交给客户端。
- 最小权限原则:移动应用中的身份验证应遵循最小权限原则,只有经过身份验证的用户才能执行敏感操作。使用服务器端的权限验证机制,避免在客户端直接授权。
- 日志和监控:在服务端实施详细的日志记录和监控机制,监控不寻常的授权请求和身份验证活动。
修复前的测试用例代码示例:
1. 绕过离线身份验证(修复前):
在没有适当验证的情况下,攻击者可以绕过离线模式中的身份验证。以下代码示例没有执行离线身份验证检查,因此攻击者可以直接访问需要身份验证的功能。
public class InsecureOfflineAuthentication {
public static void main(String[] args) {
// 离线模式下,应用程序没有进行身份验证
// 如果没有进行身份验证,攻击者可以绕过身份验证
System.out.println("访问需要身份验证的功能");
// 直接执行不经过验证的敏感操作
performSensitiveOperation();
}
private static void performSensitiveOperation() {
// 敏感操作:没有身份验证检查
System.out.println("执行敏感操作");
}
}
漏洞分析:
- 问题:在离线模式下,应用程序直接执行了敏感操作,没有进行身份验证检查。
- 风险:攻击者可以利用离线模式绕过身份验证并执行敏感操作。
2. 绕过客户端身份验证(修复前):
在以下代码中,客户端未对身份验证令牌进行有效检查,攻击者可以修改令牌并绕过身份验证。
public class InsecureClientAuthentication {
public static void main(String[] args) {
// 假设用户提供了一个会话令牌
String sessionToken = "invalid_token"; // 假设令牌无效
// 客户端没有验证令牌的有效性
if (sessionToken != null) {
// 未检查令牌有效性,直接执行敏感操作
performSensitiveOperation();
} else {
System.out.println("令牌无效");
}
}
private static void performSensitiveOperation() {
// 敏感操作:没有对令牌进行有效性检查
System.out.println("执行敏感操作");
}
}
漏洞分析:
- 问题:客户端没有验证会话令牌的有效性,攻击者可以修改或伪造令牌绕过身份验证。
- 风险:攻击者可以伪造有效的令牌或篡改令牌,绕过身份验证,执行不该执行的操作。
3. 使用低权限会话令牌执行特权功能(修复前):
在以下代码中,低权限的用户会话令牌被用于执行应仅限于管理员的操作,没有强制的服务器端权限检查。
public class InsecureAuthorization {
public static void main(String[] args) {
// 假设我们有一个低权限的会话令牌
String sessionToken = "low_privilege_token"; // 低权限令牌
// 低权限令牌直接执行特权操作
if (sessionToken != null) {
// 没有验证用户权限,直接执行特权功能
performAdminFunction();
} else {
System.out.println("无效会话");
}
}
private static void performAdminFunction() {
// 执行特权功能:没有检查用户是否具有足够权限
System.out.println("执行管理员特权功能");
}
}
漏洞分析:
- 问题:应用程序没有验证会话令牌的权限,低权限用户可以执行管理员功能。
- 风险:攻击者可以通过伪造低权限令牌,访问本应仅限管理员执行的操作。
4. 会话令牌的可重用性(修复前):
以下代码示例中,服务器端未验证会话令牌的完整性,导致攻击者可以重用过期或伪造的令牌。
public class InsecureSessionManagement {
public static void main(String[] args) {
// 获取一个会话令牌
String sessionToken = "session_token"; // 假设这是一个有效令牌
// 令牌可能已被攻击者篡改
// 客户端直接使用令牌,无需验证令牌有效性
if (sessionToken != null) {
// 没有验证令牌的完整性,直接执行敏感操作
performSensitiveOperation();
} else {
System.out.println("令牌无效");
}
}
private static void performSensitiveOperation() {
// 执行敏感操作:没有验证令牌的有效性和完整性
System.out.println("执行敏感操作");
}
}
漏洞分析:
- 问题:客户端没有验证会话令牌是否过期或被篡改,攻击者可以使用伪造的会话令牌。
- 风险:攻击者可以重用已过期或伪造的会话令牌绕过身份验证,执行敏感操作。
5. 篡改后端请求中的权限数据(修复前):
在以下代码示例中,攻击者可以修改后端请求中的权限数据,从而获得未经授权的访问。
public class InsecurePermissionHandling {
public static void main(String[] args) {
// 模拟POST请求中的权限信息
String role = "user"; // 普通用户权限
String action = "admin_action"; // 管理员功能
// 攻击者修改请求数据,篡改权限角色
role = "admin"; // 篡改为管理员角色
// 请求应检查权限,但此处没有任何检查
if (role.equals("admin")) {
performAdminAction();
} else {
System.out.println("权限不足");
}
}
private static void performAdminAction() {
// 执行管理员操作:没有进行权限验证
System.out.println("执行管理员操作");
}
}
漏洞分析:
- 问题:请求中的权限数据没有进行验证,攻击者可以修改请求,伪造自己为管理员。
- 风险:攻击者可以通过篡改请求数据来提升权限,执行管理员操作。
修复后的测试用例:
// 假设我们在修复时确保使用服务器端的身份验证和授权
public class SecureAuthentication {
public static void main(String[] args) {
// 使用离线模式时需要本地验证,并进行完整性检查
if (!isValidOfflineSession()) {
System.out.println("离线验证失败,请确保设备安全");
return;
}
// 确保会话令牌有效,并且不能被篡改
String sessionToken = getSessionToken();
if (!isValidSessionToken(sessionToken)) {
System.out.println("会话令牌无效");
return;
}
// 进行授权检查,确保当前用户具有执行操作的权限
if (!hasPermission(sessionToken, "access_sensitive_function")) {
System.out.println("权限不足,无法执行该操作");
return;
}
// 继续执行敏感操作
performSensitiveOperation();
}
private static boolean isValidOfflineSession() {
// 本地完整性检查,确保应用未被篡改
return true; // 假设本地验证成功
}
private static boolean isValidSessionToken(String token) {
// 服务器端验证会话令牌的有效性
return token != null && token.length() > 0; // 伪代码
}
private static boolean hasPermission(String token, String action) {
// 服务器端验证用户权限
return true; // 伪代码
}
private static void performSensitiveOperation() {
// 执行敏感操作
System.out.println("敏感操作已执行");
}
}
参考标准:
- CWE-259:缺失的身份验证
- OWASP Mobile Top 10:M5 - Insufficient Cryptography
总结:
- 通过强化服务器端验证,增加离线身份验证完整性检查,并且采取最小权限原则来严格控制权限,可以有效防止攻击者绕过身份验证和授权,避免未授权操作。
--------------------------------------------------------------------------------------------------------------------------------
工作:SAST工具推介、评测、代码审计、培训资料、应用安全咨询、SAST检测规则、安全漏洞数据处理、许可证数据处理、组件数据处理等。