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 垂直权限攻击 | 防御
这种攻击很容易防御,只需要在每个页面的加载之前进行权限验证即可。一个普通的权限系统,菜单是通过数据库中对应权限和角色来进行字符串拼接形成的,而不是静态的通过在页面上进行权限判断决定的。