登录个人账号后,点击基本资料。有更新资料的功能。
查看这个页面的html源码,进行代码审计。(这点怎么通过源码怎么找到的就不提了,写上实在啰嗦了。)
代码jsp页面源码如下,查看这个表单信息
注意:hidden 属性---这是一会越权的伏笔
<div class="u-account-box">
<form method="post" id="updateForm">
<input type="hidden" name="user.userId" value="${user.userId}" />
<ol class="u-account-li">
<li>
<label class="u-a-title">
<span class="fsize16 c-999">邮 箱</span>
</label>
<input type="text" class="u-a-inpt" name="${user.email}" value="${user.email}" placeholder="" readonly="readonly" disabled="disabled">
<!-- <span class="u-a-error"><em class="u-a-zq icon16"> </em></span> -->
</li>
<li>
<label class="u-a-title">
<span class="fsize16 c-999">手机号</span>
</label>
<input type="text" class="u-a-inpt" name="user.mobile" value="${user.mobile }" placeholder="" readonly="readonly" disabled="disabled">
<!-- <span class="u-a-error"><em class="u-a-zq icon16"> </em></span> -->
</li>
<li>
<label class="u-a-title">
<span class="fsize16 c-999">姓 名</span>
</label>
<input type="text" class="u-a-inpt" name="user.userName" value="${user.userName }" placeholder="" >
<!-- <span class="u-a-error"><em class="u-a-cw icon16"> </em>请输入正确的账 号</span> -->
</li>
<li>
<label class="u-a-title">
<span class="fsize16 c-999">昵 称</span>
</label>
<input type="text" class="u-a-inpt" name="user.showName" value="${user.showName}" placeholder="">
<!-- <span class="u-a-error"><em class="u-a-cw icon16"> </em>请输入正确的昵称</span> -->
</li>
<li>
<label class="u-a-title">
<span class="fsize16 c-999">性 别</span>
</label>
<input type="radio" name="user.sex" <c:if test="${user.sex==1}">checked="checked"</c:if> value="1"/><span class="vam fsize14 c-666">男</span>
<input type="radio" name="user.sex" <c:if test="${user.sex==2}">checked="checked"</c:if> value="2"/><span class="vam fsize14 c-666">女</span>
<!-- <span class="u-a-error"><em class="u-a-zq icon16"> </em></span> -->
</li>
<li>
<label class="u-a-title">
<span class="fsize16 c-999">年 龄</span>
</label>
<select name="user.age">
<option value="0">0岁</option>
<c:forEach var="age" begin="1" end="110">
<option <c:if test="${user.age==age}">selected</c:if> value="${age}">${age}岁</option>
</c:forEach>
</select>
<!-- <span class="u-a-error"><em class="u-a-cw icon16"> </em></span> -->
</li>
</ol>
</form>
<div class="ml50 mt50 pl50">
<a href="javascript:void(0)" title="" class="comm-btn c-btn-7" onclick="updateUserInfo()">提 交</a>
</div>
</div>
找到提交触发的js代码
user.js
/**
* 修改用户信息
* @param userId 用户ID
*/
function updateUserInfo(userId){
var params='';
$("#updateForm input,#updateForm select").each(function(){
params+=$(this).serialize()+"&";
});
$.ajax({
url:baselocation+'/uc/updateUser',
type:'post',
dataType:'json',
data:params,
success:function(result){
if(result.success==true){
showUserInfo();
dialog('提示信息',result.message,0);
}else{
dialog('提示信息',result.message,1);
}
}
});
}
这段代码是使用 jQuery 来收集表单中的输入字段(input)和选择字段(select),并将其序列化为 URL 参数字符串的示例。
具体来说,代码首先声明了一个变量
params
,用于存储最终生成的参数字符串。然后使用 jQuery 的.each()
方法遍历了#updateForm input
和#updateForm select
两个选择器选中的元素。在遍历过程中,对于每个选中的元素,调用了
.serialize()
方法来序列化该元素,将其转换为 URL 编码的参数字符串。然后将得到的参数字符串添加到params
变量中,通过字符串拼接的方式进行累加。最后,在每个字段之间添加了&
字符串作为分隔符。通过这段代码的执行,你可以得到一个类似于
param1=value1¶m2=value2¶m3=value3
的参数字符串。它包含了表单中所有输入字段和选择字段的名称和值的对应关系。
这段代码使用了 jQuery 的
$.ajax()
方法来向服务器发送一个 AJAX 请求,并处理服务器返回的结果。具体来说,代码中的
$.ajax()
方法包含了一个对象参数,其中包括以下属性:
url: baselocation+'/uc/updateUser'
:指定了请求的 URL 地址,这里的baselocation
是一个变量或常量,表示基本的请求地址。
type: 'post'
:指定了请求的 HTTP 方法为 POST。
dataType: 'json'
:指定了期望的服务器响应数据类型为 JSON,这样 jQuery 会自动解析响应结果并将其转换为 JavaScript 对象。
data: params
:指定了请求的数据内容,这里的params
是之前生成的参数字符串。
success: function(result) { ... }
:指定了当请求成功完成后的回调函数。其中,result
是服务器返回的响应数据。在
success
回调函数中,首先判断result.success
是否为真(即true
)。若为真,则调用showUserInfo()
函数展示用户信息,并通过dialog()
函数显示一个提示信息框,其中result.message
是成功消息内容。若result.success
不为真,则同样通过dialog()
函数显示一个提示信息框,其中result.message
是失败消息内容。整个代码的作用是向
baselocation+'/uc/updateUser'
发送一个带有参数的 POST 请求,然后根据服务器返回的结果动态更新页面上的内容和显示提示信息。请注意,在运行此代码之前,确保引入了 jQuery 库,并在页面加载完毕后执行代码,或将代码放置在合适的事件处理程序中。
如果你需要进一步的帮助,请提供更多上下文或相关代码。
根据post提交的接口,/uc/updateUser,/uc 为指定的拦截器 ,
站点spring-mvc.xml文件
<mvc:interceptor>
<mvc:mapping path="/uc/*"/>
<mvc:mapping path="/uc/**/*"/>
<mvc:exclude-mapping path="/uc/tologin"/>
<mvc:exclude-mapping path="/uc/getloginUser"/>
<mvc:exclude-mapping path="/uc/register"/>
<mvc:exclude-mapping path="/uc/createuser"/>
<mvc:exclude-mapping path="/uc/login"/>
<mvc:exclude-mapping path="/uc/passwordRecovery"/>
<mvc:exclude-mapping path="/uc/sendEmail"/>
<bean class="com.inxedu.os.common.intercepter.IntercepterWebLogin">
</bean>
</mvc:interceptor>
IntercepterWebLogin继承HandlerInterceptorAdapter类
class IntercepterWebLogin extends HandlerInterceptorAdapter
具体来说,
HandlerInterceptorAdapter
类可以实现以下功能:
preHandle
方法:在请求处理之前执行的方法。可以用来进行登录状态验证、权限检查、日志记录等操作。如果该方法返回true
,则表示允许进入下一步的处理(比如调用控制器方法),如果返回false
,则表示拦截该请求。
postHandle
方法:在请求处理之后、视图渲染之前执行的方法。可以用来修改请求的响应或处理其他后续操作。
afterCompletion
方法:在整个请求完成后执行的方法。可用于进行一些资源清理或处理善后工作。
/updateUser 就为我们响应的方法了,一定位于某个controller中。底层用反射机制实现的方法调用。
定位的到响应的RequestMapping,也可以全局搜索updateUser定位到该方法。
/**
* 修改用户信息
*/
@RequestMapping("/updateUser")
@ResponseBody
public Map<String,Object> updateUserInfo(HttpServletRequest request){
Map<String,Object> json = new HashMap<String,Object>();
try{
String userName=request.getParameter("userName");//姓名
if(userName==null||userName.trim().equals("")){
json=this.setJson(false, "姓名不能为空", null);
return json;
}
String showName=request.getParameter("showName");//昵称
if(showName==null||showName.trim().equals("")){
json=this.setJson(false, "昵称不能为空", null);
return json;
}
String sex=request.getParameter("sex");//性别 1男 2女
if(sex==null||sex.trim().equals("")){
json=this.setJson(false, "性别不能为空", null);
return json;
}
String age=request.getParameter("age");//年龄
if(age==null||age.trim().equals("")){
json=this.setJson(false, "年龄不能为空", null);
return json;
}
String userId=request.getParameter("userId");//用户Id
if(userId==null||userId.trim().equals("")){
json=this.setJson(false, "用户Id不能为空", null);
return json;
}
User user=new User();
user.setUserId(Integer.parseInt(userId));//用户Id
user.setUserName(userName);//姓名
user.setShowName(showName);//昵称
user.setSex(Integer.parseInt(sex));//性别
user.setAge(Integer.parseInt(age));//年龄
userService.updateUser(user);//修改基本信息
json = this.setJson(true, "修改成功", user);
}catch (Exception e) {
json=this.setJson(false, "异常", null);
logger.error("updateUserInfo()---error",e);
}
return json;
}
}
@ResponseBody 不用管,这是底层为维护方法返回的json数据所增加的注解。
这段代码是一个用于更新用户信息的方法。具体功能如下:
通过
HttpServletRequest
对象获取请求参数,包括userName
(姓名)、showName
(昵称)、sex
(性别)、age
(年龄)和userId
(用户Id)等信息。对每个参数进行非空判断,如果有任何一个参数为空或空字符串,则返回一个包含错误信息的
json
对象。如果所有参数都不为空,则根据获取的参数创建一个
User
对象,并设置相应的属性值。调用
userService.updateUser(user)
方法来更新用户的基本信息。如果更新成功,返回一个包含成功信息和更新后的
user
对象的json
对象;如果出现异常,则返回一个包含异常信息的json
对象。
user对象没有对用户输入的数据做验证,平且所有的数据字段我们都可以控制。直接set传进来的参数,执行updateUser,这就非常像越权漏洞了。
正确的做法应该是,登录的用户只能修改自己的相关信息,用户Id(唯一键值)应该是固定自己的。
这里就没有必要往下看了,因为之后在updateUser中做本用户的验证几率不大。
如果不放心可以追进这个方法里,看看有没有对输入的数据做验证!是不是按照流程将指定的user参数进行更新。
........
小彩蛋:仔细思考这个表单是否存在CRSF漏洞呢!................