1.1 漏洞描述
越權漏洞是比較常見的漏洞類型,越權漏洞可以理解爲,一個正常的用戶A通常只能夠對自己的一些信息進行增刪改查,但是由於程序員的一時疏忽未對信息進行增刪改查的時候沒有進行一個判斷,判斷所需要操作的信息是否屬於對應的用戶,可以導致用戶A可以操作其他人的信息。
權限攻擊可以分爲水平權限攻擊和垂直權限攻擊。
水平權限攻擊,也叫作訪問控制攻擊。Web應用程序接收到用戶請求,修改某條數據時,沒有判斷數據的所屬人,或者在判斷數據所屬人時從用戶提交的表單參數中獲取了userid。導致攻擊者可以自行修改userid修改不屬於自己的數據。所有的更新語句操作,都可能產生這個漏洞。
1.2 漏洞危害
顯而易見,越權操作會導致站點的數據不安全,用戶可以操作本不屬於自己操作範圍的數據。
1.3 漏洞演示
1.3.1 水平權限 | 攻擊
我們來看看攻擊案例,Web應用在修改用戶個人信息時,從用戶提交的表單中獲取userid,執行修改操作:
<form action="/struts1/edituser.htm" method="post">
<input name="userid" type="hidden" value="<%=userid%>">
<table border="1">
<tr>
<td>username:</td>
<td><%=rs.getString("name")%></td>
</tr>
<tr>
<td>passwd:</td>
<td><input name="pass" value="<%=rs.getString("pass")%>"></td>
</tr>
</table>
<html:submit/>
</form>
表單中,將用戶的userid作爲隱藏字段,提交給處理修改個人信息的應用。
下面是修改個人信息的後臺代碼:
int userid=Integer.valueOf( request.getParameter("userid"));
String pass=request.getParameter("pass");
JdbcConnection conn = null;
try {
conn = new JdbcConnection();
Object[] params = new Object[2];
params[0] = pass;
params[1] = userid;
final String sql = "update user set pass=? where userid=?";
conn.execUpdate(sql,params);
conn.closeConn();
這段代碼從表單參數列表中獲取userid,修改userid對應的用戶數據。
攻擊者可以隨意修改表單的userid:
修改userid後,提交表單,就可能修改了其他用戶的數據。
1.3.2 垂直權限 | 攻擊
垂直權限攻擊又叫做權限提升攻擊。其原理是由於Web應用沒有做權限控制,或僅僅在菜單上做了權限控制,導致惡意用戶只要猜測其他管理頁面的URL,就可以訪問或控制其他角色擁有的數據或頁面,達到權限提升的目的。
我們來看看攻擊案例,下面是一個僅僅做了菜單控制的代碼:
<tr>
<td><a href="/user.jsp">管理個人信息</a></td>
</tr>
<%if (power.indexOf("administrators")>-1){%>
<tr>
<td><a href="/userlist.jsp">管理所有用戶</a></td>
</tr>
<%}%>
攻擊者只需要猜中管理所有用戶的頁面url就可以越權操作了。
1.4 修復方案
1.4.1 水平權限攻擊 | 防禦
這種情況似乎很容易被忽略,包括我現在着手的一個項目也是才發現這樣的一個問題。那麼應該如何解決呢?其實也很容易。就是從用戶的加密認證cookie中獲取當前用戶id,並且在執行的sql語句中加入當前用戶id作爲條件語句。由於cookie是加密的,所以攻擊者無法修改加密信息。
int userid=Integer.valueOf( GetUseridFromCookie(request));
String pass=request.getParameter("pass");
JdbcConnection conn = null;
try {
conn = new JdbcConnection();
Object[] params = new Object[2];
params[0] = pass;
params[1] = userid;
final String sql = "update user set pass=? where userid=?";
conn.execUpdate(sql,params);
conn.closeConn();
代碼中通過GetUseridFromCookie方法,從加密的cookie中獲取當前用戶的id,並加入判斷。
1.4.2 垂直權限攻擊 | 防禦
這種攻擊很容易防禦,只需要在每個頁面的加載之前進行權限驗證即可。一個普通的權限系統,菜單是通過數據庫中對應權限和角色來進行字符串拼接形成的,而不是靜態的通過在頁面上進行權限判斷決定的。