Authored by yyq

Merge branch 'hotfix/security' into release/security

@@ -77,7 +77,7 @@ exports.index = (req, res, next) => { @@ -77,7 +77,7 @@ exports.index = (req, res, next) => {
77 */ 77 */
78 exports.tags = (req, res, next) => { 78 exports.tags = (req, res, next) => {
79 79
80 - let query = req.query.query; 80 + let query = req.query.query = escape(req.query.query);
81 let page = req.query.page || 1; 81 let page = req.query.page || 1;
82 let pageSize = req.query.pageSize || 20; 82 let pageSize = req.query.pageSize || 20;
83 let type = req.query.type || 0; 83 let type = req.query.type || 0;
@@ -215,6 +215,13 @@ const renren = { @@ -215,6 +215,13 @@ const renren = {
215 const cancelBind = (req, res) => { 215 const cancelBind = (req, res) => {
216 let type = req.params.type; 216 let type = req.params.type;
217 217
  218 + if (!(req.get('Refer') || '').match(/yohobuy.com/)) {
  219 + return res.send({
  220 + code: 501,
  221 + message: '非法请求'
  222 + });
  223 + }
  224 +
218 if (!type) { 225 if (!type) {
219 res.status(400).json({ 226 res.status(400).json({
220 code: 400, 227 code: 400,
@@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
7 const Promise = require('bluebird'); 7 const Promise = require('bluebird');
8 const co = Promise.coroutine; 8 const co = Promise.coroutine;
9 const helpers = global.yoho.helpers; 9 const helpers = global.yoho.helpers;
  10 +const logger = global.yoho.logger;
10 const _ = require('lodash'); 11 const _ = require('lodash');
11 12
12 const crypto = global.yoho.crypto; 13 const crypto = global.yoho.crypto;
@@ -270,20 +271,29 @@ const auditCheckStatus = (uid, checkType, step) => { @@ -270,20 +271,29 @@ const auditCheckStatus = (uid, checkType, step) => {
270 * 校验进入第二步 271 * 校验进入第二步
271 * @param type $checkCode 272 * @param type $checkCode
272 * @param type $uid 273 * @param type $uid
  274 + * @param type MaxTime
273 * @return boolean 275 * @return boolean
274 */ 276 */
275 -const checkCode = (ckCode, uid) => {  
276 - // checkCode里空格用+替换  
277 - let code = decodeURIComponent(ckCode);  
278 - let checkStr = crypto.decrypt('yoho9646abcdefgh', code); 277 +const checkCode = (ckCode, uid, time) => {
  278 + time = parseInt(`0${time}`, 10) || 86400000;
279 279
280 - let checkInfo = checkStr.split('_'),  
281 - checkUid = checkInfo[0],  
282 - timeDiff = Date.parse(new Date()) - checkInfo[1]; // 时间差,秒 24h 86400 280 + try {
  281 + // checkCode里空格用+替换
  282 + let code = decodeURIComponent(ckCode);
  283 + let checkStr = crypto.decrypt('yoho9646abcdefgh', code);
  284 +
  285 + let checkInfo = checkStr.split('_'),
  286 + checkUid = checkInfo[0],
  287 + timeDiff = Date.parse(new Date()) - checkInfo[1]; // 时间差,秒 24h 86400000
  288 +
  289 + if (checkStr.indexOf('completeverify') > 0 && String(checkUid) === String(uid) && timeDiff <= time) {
  290 + return true;
  291 + } else {
  292 + return false;
  293 + }
  294 + } catch (e) { // eslint-disable-line
  295 + logger.error(`account checkCode decrypt error [checkCode]:${ckCode}`);
283 296
284 - if (checkStr.indexOf('completeverify') > 0 && String(checkUid) === String(uid) && timeDiff <= 86400) {  
285 - return true;  
286 - } else {  
287 return false; 297 return false;
288 } 298 }
289 }; 299 };
@@ -776,8 +786,25 @@ const identityMobile = (req) => { @@ -776,8 +786,25 @@ const identityMobile = (req) => {
776 const sendMobileMsg = (req, uid) => { 786 const sendMobileMsg = (req, uid) => {
777 return co(function*() { 787 return co(function*() {
778 let mobile = req.body.mobile || '', 788 let mobile = req.body.mobile || '',
  789 + _code = req.body.checkCode,
779 resqData = {code: 400}; 790 resqData = {code: 400};
780 791
  792 + // 发送验证码前置数据校验
  793 + if (!_code) {
  794 + let verifyInfo = yield accountApi.getVerifyInfo(uid);
  795 +
  796 + mobile = _.get(verifyInfo, 'data.mobile', '');
  797 + if (!mobile) {
  798 + return Object.assign(resqData, {
  799 + message: '数据验证错误'
  800 + });
  801 + }
  802 + } else if (!checkCode(_code, uid)) {
  803 + return Object.assign(resqData, {
  804 + message: '数据验证错误'
  805 + });
  806 + }
  807 +
781 let mobileInfo = handleMobile(mobile); 808 let mobileInfo = handleMobile(mobile);
782 809
783 resqData = yield accountApi.sendMobileMsg(uid, mobileInfo.mobile, mobileInfo.area); 810 resqData = yield accountApi.sendMobileMsg(uid, mobileInfo.mobile, mobileInfo.area);
@@ -792,22 +819,37 @@ const checkMobileMsg = (req, uid) => { @@ -792,22 +819,37 @@ const checkMobileMsg = (req, uid) => {
792 return co(function*() { 819 return co(function*() {
793 let mobile = req.body.mobile || '', 820 let mobile = req.body.mobile || '',
794 code = req.body.code || '', 821 code = req.body.code || '',
795 - resqData; 822 + _code = req.body.checkCode,
  823 + resqData = {code: 400};
  824 +
  825 + // 校验验证码前置数据校验
  826 + if (!_code) {
  827 + let verifyInfo = yield accountApi.getVerifyInfo(uid);
  828 +
  829 + mobile = _.get(verifyInfo, 'data.mobile', '');
  830 + if (!mobile) {
  831 + return Object.assign(resqData, {
  832 + message: '数据验证错误'
  833 + });
  834 + }
  835 + } else if (!checkCode(_code, uid)) {
  836 + return Object.assign(resqData, {
  837 + message: '数据验证错误'
  838 + });
  839 + }
796 840
797 if (mobile === '') { 841 if (mobile === '') {
798 - resqData = {  
799 - code: 400, 842 + Object.assign(resqData, {
800 message: '手机号为空', 843 message: '手机号为空',
801 data: '' 844 data: ''
802 - }; 845 + });
803 return resqData; 846 return resqData;
804 } 847 }
805 if (code === '') { 848 if (code === '') {
806 - resqData = {  
807 - code: 400, 849 + Object.assign(resqData, {
808 message: '验证码为空', 850 message: '验证码为空',
809 data: '' 851 data: ''
810 - }; 852 + });
811 return resqData; 853 return resqData;
812 } 854 }
813 let mobileInfo = handleMobile(mobile); 855 let mobileInfo = handleMobile(mobile);
@@ -817,7 +859,11 @@ const checkMobileMsg = (req, uid) => { @@ -817,7 +859,11 @@ const checkMobileMsg = (req, uid) => {
817 let ckCode = crypto.encryption('yoho9646abcdefgh', uid + '_' + Date.parse(new Date()) + '_' + 859 let ckCode = crypto.encryption('yoho9646abcdefgh', uid + '_' + Date.parse(new Date()) + '_' +
818 mobileInfo.mobile + mobileInfo.area + 'completeverify'); 860 mobileInfo.mobile + mobileInfo.area + 'completeverify');
819 861
820 - resqData.data = encodeURIComponent(ckCode); 862 +
  863 + Object.assign(resqData, {
  864 + code: 200,
  865 + data: encodeURIComponent(ckCode)
  866 + });
821 } 867 }
822 return resqData; 868 return resqData;
823 })(); 869 })();
@@ -833,6 +879,15 @@ const sendEmail = (req) => { @@ -833,6 +879,15 @@ const sendEmail = (req) => {
833 email = req.body.email || '', 879 email = req.body.email || '',
834 resqData = {code: 400}; 880 resqData = {code: 400};
835 881
  882 + let verifyInfo = yield accountApi.getVerifyInfo(uid);
  883 +
  884 + email = _.get(verifyInfo, 'data.email', '');
  885 + if (!email) {
  886 + return Object.assign(resqData, {
  887 + message: '数据验证错误'
  888 + });
  889 + }
  890 +
836 let ckCode = crypto.encryption('yoho9646abcdefgh', uid + '_' + Date.parse(new Date()) + 891 let ckCode = crypto.encryption('yoho9646abcdefgh', uid + '_' + Date.parse(new Date()) +
837 '_' + email + checkType + 'completeverify'); 892 '_' + email + checkType + 'completeverify');
838 893
@@ -864,7 +919,16 @@ const checkEmail = (req) => { @@ -864,7 +919,16 @@ const checkEmail = (req) => {
864 const modifyPwd = (req, params) => { 919 const modifyPwd = (req, params) => {
865 return co(function*() { 920 return co(function*() {
866 let uid = params.uid, 921 let uid = params.uid,
867 - newPwd = params.newPwd || ''; 922 + newPwd = params.newPwd || '',
  923 + _code = params.checkCode;
  924 +
  925 + // 前置数据校验
  926 + if (!_code || !checkCode(_code, uid, 600000)) {
  927 + return {
  928 + code: 400,
  929 + message: '数据验证错误'
  930 + };
  931 + }
868 932
869 let resqData = yield accountApi.modifyPwd(uid, newPwd); 933 let resqData = yield accountApi.modifyPwd(uid, newPwd);
870 934
@@ -879,8 +943,17 @@ const modifyMobile = (req, uid) => { @@ -879,8 +943,17 @@ const modifyMobile = (req, uid) => {
879 return co(function*() { 943 return co(function*() {
880 let mobile = req.body.mobile || '', 944 let mobile = req.body.mobile || '',
881 code = req.body.code || '', 945 code = req.body.code || '',
  946 + _code = req.body.checkCode,
882 resqData = {code: 400}; 947 resqData = {code: 400};
883 948
  949 + // 校验验证码前置数据校验
  950 + // 校验checkCode,有效时间10分钟(checkCode在调改接口前获取,考虑网络延时,服务器间的时间差,设置10分钟)
  951 + if (!_code || !checkCode(_code, uid, 600000)) {
  952 + return Object.assign(resqData, {
  953 + message: '数据验证错误'
  954 + });
  955 + }
  956 +
884 if (mobile === '') { 957 if (mobile === '') {
885 resqData = { 958 resqData = {
886 code: 400, 959 code: 400,
@@ -937,8 +1010,16 @@ const modifyEmail = (req) => { @@ -937,8 +1010,16 @@ const modifyEmail = (req) => {
937 return co(function*() { 1010 return co(function*() {
938 let uid = req.user.uid, 1011 let uid = req.user.uid,
939 email = req.body.email || '', 1012 email = req.body.email || '',
  1013 + _code = req.body.checkCode,
940 resqData = {code: 400}; 1014 resqData = {code: 400};
941 1015
  1016 + // 前置数据校验
  1017 + if (!_code || !checkCode(_code, uid, 600000)) {
  1018 + return Object.assign(resqData, {
  1019 + message: '数据验证错误'
  1020 + });
  1021 + }
  1022 +
942 let check = yield accountApi.checkVerifyEmail(uid, email); 1023 let check = yield accountApi.checkVerifyEmail(uid, email);
943 1024
944 if (check.code === 200) { 1025 if (check.code === 200) {
@@ -73,7 +73,7 @@ Dialog.prototype.packageInfo = function() { @@ -73,7 +73,7 @@ Dialog.prototype.packageInfo = function() {
73 key = $this.attr('name'); 73 key = $this.attr('name');
74 74
75 if (key) { 75 if (key) {
76 - data[key] = $.trim($this.val()); 76 + data[key] = $.trim($('<div/>').text($this.val()).html());
77 } 77 }
78 }); 78 });
79 79
@@ -21,9 +21,14 @@ var $checkUser = $('.check-user'), @@ -21,9 +21,14 @@ var $checkUser = $('.check-user'),
21 var sInt, 21 var sInt,
22 active; 22 active;
23 23
  24 +var baseQs;
  25 +
24 var captcha = new Captcha('.captcha-safe-form-r').init(); 26 var captcha = new Captcha('.captcha-safe-form-r').init();
25 27
26 require('../common'); 28 require('../common');
  29 +
  30 +baseQs = window.queryString();
  31 +
27 $.ajaxSetup({ 32 $.ajaxSetup({
28 async: false 33 async: false
29 }); 34 });
@@ -66,6 +71,9 @@ function checkFormAjax(ajaxData) { @@ -66,6 +71,9 @@ function checkFormAjax(ajaxData) {
66 71
67 $.post(ajaxData.url, ajaxData.data, function(data) { 72 $.post(ajaxData.url, ajaxData.data, function(data) {
68 if (typeof data.code !== 'undefined' && data.code === 200) { 73 if (typeof data.code !== 'undefined' && data.code === 200) {
  74 + if (ajaxData.cb && typeof ajaxData.cb === 'function') {
  75 + ajaxData.cb(data); // eslint-disable-line
  76 + }
69 res = successInfoAction(ajaxData.opt); 77 res = successInfoAction(ajaxData.opt);
70 } else { 78 } else {
71 ajaxData.txt = ajaxData.txt !== '' && ajaxData.txt !== null ? ajaxData.txt : data.message; 79 ajaxData.txt = ajaxData.txt !== '' && ajaxData.txt !== null ? ajaxData.txt : data.message;
@@ -174,9 +182,15 @@ function checkForm(dom) { @@ -174,9 +182,15 @@ function checkForm(dom) {
174 url: '/home/account/checkmobilemsg', 182 url: '/home/account/checkmobilemsg',
175 data: { 183 data: {
176 mobile: mobileValue, 184 mobile: mobileValue,
177 - code: $('#inputcode').val() 185 + code: $('#inputcode').val(),
  186 + checkCode: baseQs.checkCode || ''
178 }, 187 },
179 - txt: '验证码错误!' 188 + txt: '验证码错误!',
  189 + cb: function(data) {
  190 + if (data.code === 200) {
  191 + baseQs.checkCode = data.data;
  192 + }
  193 + }
180 }); 194 });
181 return checkFormAjax(ajaxData); 195 return checkFormAjax(ajaxData);
182 } 196 }
@@ -227,10 +241,15 @@ function code() { @@ -227,10 +241,15 @@ function code() {
227 function sendMobileMsg(mobileV) { 241 function sendMobileMsg(mobileV) {
228 var $code = $('#inputcode'), 242 var $code = $('#inputcode'),
229 $ccheckInfo = $code.parent().find('check-info'); 243 $ccheckInfo = $code.parent().find('check-info');
230 -  
231 - $.post('/home/account/sendmobilemsg', { 244 + var reqData = {
232 mobile: mobileV 245 mobile: mobileV
233 - }, function(data) { 246 + };
  247 +
  248 + if (baseQs.checkCode) {
  249 + reqData.checkCode = baseQs.checkCode;
  250 + }
  251 +
  252 + $.post('/home/account/sendmobilemsg', reqData, function(data) {
234 if (typeof data.code !== 'undefined' && data.code === 200) { 253 if (typeof data.code !== 'undefined' && data.code === 200) {
235 canSend = false; 254 canSend = false;
236 sInt = setInterval(function() { 255 sInt = setInterval(function() {
@@ -360,7 +379,8 @@ function submitForm() { @@ -360,7 +379,8 @@ function submitForm() {
360 url: '/home/account/checkmobilemsg', 379 url: '/home/account/checkmobilemsg',
361 data: { 380 data: {
362 mobile: $('#realAccount').val(), 381 mobile: $('#realAccount').val(),
363 - code: $('#inputcode').val() 382 + code: $('#inputcode').val(),
  383 + checkCode: baseQs.checkCode || ''
364 }, 384 },
365 hrefUrl: '/home/account/' + curType + '?step=2' 385 hrefUrl: '/home/account/' + curType + '?step=2'
366 }; 386 };
@@ -373,12 +393,15 @@ function submitForm() { @@ -373,12 +393,15 @@ function submitForm() {
373 data: $('#pwdform').serialize(), 393 data: $('#pwdform').serialize(),
374 hrefUrl: '/home/account/userpwd?step=3&success=true' 394 hrefUrl: '/home/account/userpwd?step=3&success=true'
375 }; 395 };
  396 +
  397 + opt.data.checkCode = baseQs.checkCode || '';
376 ajaxAction(opt); 398 ajaxAction(opt);
377 } else if (curType === 'email') { 399 } else if (curType === 'email') {
378 opt = { 400 opt = {
379 url: '/home/account/modifyemail', 401 url: '/home/account/modifyemail',
380 data: { 402 data: {
381 - email: $('#email').val() 403 + email: $('#email').val(),
  404 + checkCode: baseQs.checkCode || ''
382 }, 405 },
383 hrefUrl: '/home/account/sendemailsuccess?email=' + $('#email').val() + 406 hrefUrl: '/home/account/sendemailsuccess?email=' + $('#email').val() +
384 '&type=2&checkType=email' 407 '&type=2&checkType=email'
@@ -389,7 +412,8 @@ function submitForm() { @@ -389,7 +412,8 @@ function submitForm() {
389 url: '/home/account/modifymobile', 412 url: '/home/account/modifymobile',
390 data: { 413 data: {
391 mobile: $('#mobilevalue').val(), 414 mobile: $('#mobilevalue').val(),
392 - code: $('#inputcode').val() 415 + code: $('#inputcode').val(),
  416 + checkCode: baseQs.checkCode || ''
393 }, 417 },
394 hrefUrl: '/home/account/mobile?step=3&success=true' 418 hrefUrl: '/home/account/mobile?step=3&success=true'
395 }; 419 };