2008-08-24 19 views
20

Jeff thực sự đã đăng về điều này trong Sanitize HTML. Nhưng ví dụ của ông là trong C# và tôi thực sự quan tâm nhiều hơn đến một phiên bản Java. Có ai có một phiên bản tốt hơn cho Java? Ví dụ của anh ta có đủ tốt để chỉ chuyển đổi trực tiếp từ C# sang Java không?Regex tốt nhất để bắt tấn công XSS (Cross-site Scripting) (trong Java)?

[Cập nhật] Tôi đã đặt một tiền thưởng cho câu hỏi này vì SO không phổ biến khi tôi đặt câu hỏi như hôm nay (*). Đối với bất cứ điều gì liên quan đến an ninh, càng có nhiều người nhìn vào nó, thì càng tốt!

(*) Trong thực tế, tôi nghĩ rằng nó vẫn còn trong giai đoạn closed beta

+0

hơn những gì bạn cần? Câu trả lời có vẻ tốt với tôi. –

Trả lời

60

Không làm điều này với cụm từ thông dụng. Hãy nhớ rằng, bạn không bảo vệ chống lại HTML hợp lệ; bạn đang bảo vệ chống lại DOM mà trình duyệt web tạo ra. Các trình duyệt có thể bị lừa để tạo ra DOM hợp lệ từ HTML không hợp lệ khá dễ dàng.Ví dụ, xem danh sách này obfuscated XSS attacks. Bạn đã chuẩn bị để điều chỉnh một regex để ngăn chặn cuộc tấn công thế giới thực này trên Yahoo and Hotmail trên IE6/7/8?

<HTML><BODY> 
<?xml:namespace prefix="t" ns="urn:schemas-microsoft-com:time"> 
<?import namespace="t" implementation="#default#time2"> 
<t:set attributeName="innerHTML" to="XSS&lt;SCRIPT DEFER&gt;alert(&quot;XSS&quot;)&lt;/SCRIPT&gt;"> 
</BODY></HTML> 

Cuộc tấn công này hoạt động trên IE6 như thế nào?

<TABLE BACKGROUND="javascript:alert('XSS')"> 

Làm thế nào về các cuộc tấn công không được liệt kê trên trang web này? Vấn đề với cách tiếp cận của Jeff là nó không phải là một danh sách trắng, như tuyên bố. Khi ai đó trên that page adeptly ghi chú:

Vấn đề với nó, là html phải sạch. Có những trường hợp trong đó bạn có thể chuyển vào html bị tấn công và sẽ không khớp với nó, trong trường hợp này, nó sẽ trả về chuỗi html bị tấn công vì nó sẽ không khớp với bất kỳ thứ gì để thay thế. Điều này không phải là danh sách trắng đầy đủ.

Tôi sẽ đề xuất công cụ được xây dựng theo mục đích như AntiSamy. Nó hoạt động bằng cách phân tích cú pháp HTML thực sự, và sau đó duyệt qua DOM và xóa bất kỳ thứ gì không có trong danh sách trắng có thể định cấu hình. Điểm khác biệt chính là khả năng xử lý HTML không đúng định dạng.

Phần tốt nhất là nó thực sự đơn vị kiểm tra cho tất cả các cuộc tấn công XSS trên trang web trên. Bên cạnh đó, những gì có thể dễ dàng hơn cuộc gọi API này:

public String toSafeHtml(String html) throws ScanException, PolicyException { 

    Policy policy = Policy.getInstance(POLICY_FILE); 
    AntiSamy antiSamy = new AntiSamy(); 
    CleanResults cleanResults = antiSamy.scan(html, policy); 
    return cleanResults.getCleanHTML().trim(); 
} 
+0

AntiSamy sẽ rất tuyệt! Ngoài ra, việc sử dụng các chính sách khác nhau là một ý tưởng hay vì nó giữ các quy tắc làm sạch bên ngoài mã giúp việc duy trì dễ dàng hơn. Đây rõ ràng là một cách tiếp cận rất tốt đẹp. Thanh danh. – potyl

+1

+1. Bạn không thể xử lý HTML một cách đáng tin cậy bằng regex. Phân tích nó thành một DOM có thể lọc dễ dàng, sau đó sử dụng và tuần tự hóa tốt, là cách tiếp cận hợp lý hơn. – bobince

+0

Tôi thực sự thích câu trả lời này, vì nó không trả lời trực tiếp câu hỏi, nhưng thay vào đó giải quyết vấn đề! –

4

Các regex thể hiện trong ví dụ của bạn, nên làm việc bất kể ngôn ngữ.

Vì vậy, nó là regex bạn muốn, hoặc mã java để đặt logic này xung quanh regex?

0

Vấn đề lớn nhất bằng cách sử dụng Jeffs mã là @ mà hiện isnt sẵn.

tôi có lẽ chỉ cần đi "thô" regexp từ Jeffs mã nếu tôi cần nó và dán nó vào

http://www.cis.upenn.edu/~matuszek/General/RegexTester/regex-tester.html

và xem những điều cần thoát được trốn thoát và sau đó sử dụng nó.


Lấy việc sử dụng regex này trong tâm trí cá nhân tôi sẽ chắc chắn rằng tôi hiểu chính xác những gì tôi đang làm, tại sao và những gì hậu quả sẽ là nếu tôi didnt thành công, trước khi sao chép/dán bất cứ điều gì, giống như câu trả lời khác thử để giúp bạn.

(Thats lời khuyên propbably khá vững chắc cho bất cứ copy/paste)

4

Tôi không bị thuyết phục rằng việc sử dụng một biểu thức chính quy là cách tốt nhất cho việc tìm kiếm tất cả các mã nghi ngờ. Cụm từ thông dụng khá dễ lừa đặc biệt khi xử lý HTML bị hỏng. Ví dụ: biểu thức chính quy được liệt kê trong liên kết Sanitize HTML sẽ không xóa tất cả các phần tử 'a' có thuộc tính giữa tên phần tử và thuộc tính 'href':

< alt = "xss injection" href = "http://www.malicous.com/bad.php">

Cách mạnh mẽ hơn để xóa mã độc hại là dựa vào Trình phân tích cú pháp XML có thể xử lý tất cả các loại tài liệu HTML (Tidy, TagSoup, v.v ...) và chọn các phần tử cần xóa bằng biểu thức XPath. Khi tài liệu HTML được phân tích cú pháp thành tài liệu DOM, các phần tử cần xem lại có thể được tìm thấy dễ dàng và an toàn. Điều này thậm chí còn dễ dàng thực hiện với XSLT.

+0

+1, hãy xem câu trả lời của tôi cho một API Java thực tế thực hiện chính xác rằng –

0

[\s\w\.]*. Nếu nó không khớp, bạn đã có XSS. Có lẽ. Lưu ý rằng biểu thức này chỉ cho phép chữ cái, số và dấu chấm. Nó tránh tất cả các biểu tượng, ngay cả những biểu tượng hữu ích, vì sợ XSS. Khi bạn cho phép &, bạn đã lo lắng. Và chỉ thay thế tất cả các trường hợp của & với &amp; là không đủ. Quá phức tạp để tin tưởng: P. Rõ ràng điều này sẽ không cho phép rất nhiều văn bản hợp pháp (Bạn chỉ có thể thay thế tất cả các ký tự không khớp với một hoặc một cái gì đó), nhưng tôi nghĩ rằng nó sẽ giết chết XSS.

Ý tưởng chỉ phân tích cú pháp dưới dạng html và tạo html mới có lẽ tốt hơn.

1
^(\s|\w|\d|<br>)*?$ 

Điều này sẽ xác thực ký tự, chữ số, khoảng trắng và thẻ <br>. Nếu bạn muốn mạo hiểm hơn bạn có thể thêm các thẻ như

^(\s|\w|\d|<br>|<ul>|<\ul>)*?$ 
2

tôi chiết xuất từ ​​NoScript tốt nhất addon Anti-XSS, đây là Regex của nó: làm việc hoàn hảo:

<[^\w<>]*(?:[^<>"'\s]*:)?[^\w<>]*(?:\W*s\W*c\W*r\W*i\W*p\W*t|\W*f\W*o\W*r\W*m|\W*s\W*t\W*y\W*l\W*e|\W*s\W*v\W*g|\W*m\W*a\W*r\W*q\W*u\W*e\W*e|(?:\W*l\W*i\W*n\W*k|\W*o\W*b\W*j\W*e\W*c\W*t|\W*e\W*m\W*b\W*e\W*d|\W*a\W*p\W*p\W*l\W*e\W*t|\W*p\W*a\W*r\W*a\W*m|\W*i?\W*f\W*r\W*a\W*m\W*e|\W*b\W*a\W*s\W*e|\W*b\W*o\W*d\W*y|\W*m\W*e\W*t\W*a|\W*i\W*m\W*a?\W*g\W*e?|\W*v\W*i\W*d\W*e\W*o|\W*a\W*u\W*d\W*i\W*o|\W*b\W*i\W*n\W*d\W*i\W*n\W*g\W*s|\W*s\W*e\W*t|\W*i\W*s\W*i\W*n\W*d\W*e\W*x|\W*a\W*n\W*i\W*m\W*a\W*t\W*e)[^>\w])|(?:<\w[\s\S]*[\s\0\/]|['"])(?:formaction|style|background|src|lowsrc|ping|on(?:d(?:e(?:vice(?:(?:orienta|mo)tion|proximity|found|light)|livery(?:success|error)|activate)|r(?:ag(?:e(?:n(?:ter|d)|xit)|(?:gestur|leav)e|start|drop|over)?|op)|i(?:s(?:c(?:hargingtimechange|onnect(?:ing|ed))|abled)|aling)|ata(?:setc(?:omplete|hanged)|(?:availabl|chang)e|error)|urationchange|ownloading|blclick)|Moz(?:M(?:agnifyGesture(?:Update|Start)?|ouse(?:PixelScroll|Hittest))|S(?:wipeGesture(?:Update|Start|End)?|crolledAreaChanged)|(?:(?:Press)?TapGestur|BeforeResiz)e|EdgeUI(?:C(?:omplet|ancel)|Start)ed|RotateGesture(?:Update|Start)?|A(?:udioAvailable|fterPaint))|c(?:o(?:m(?:p(?:osition(?:update|start|end)|lete)|mand(?:update)?)|n(?:t(?:rolselect|extmenu)|nect(?:ing|ed))|py)|a(?:(?:llschang|ch)ed|nplay(?:through)?|rdstatechange)|h(?:(?:arging(?:time)?ch)?ange|ecking)|(?:fstate|ell)change|u(?:echange|t)|l(?:ick|ose))|m(?:o(?:z(?:pointerlock(?:change|error)|(?:orientation|time)change|fullscreen(?:change|error)|network(?:down|up)load)|use(?:(?:lea|mo)ve|o(?:ver|ut)|enter|wheel|down|up)|ve(?:start|end)?)|essage|ark)|s(?:t(?:a(?:t(?:uschanged|echange)|lled|rt)|k(?:sessione|comma)nd|op)|e(?:ek(?:complete|ing|ed)|(?:lec(?:tstar)?)?t|n(?:ding|t))|u(?:ccess|spend|bmit)|peech(?:start|end)|ound(?:start|end)|croll|how)|b(?:e(?:for(?:e(?:(?:scriptexecu|activa)te|u(?:nload|pdate)|p(?:aste|rint)|c(?:opy|ut)|editfocus)|deactivate)|gin(?:Event)?)|oun(?:dary|ce)|l(?:ocked|ur)|roadcast|usy)|a(?:n(?:imation(?:iteration|start|end)|tennastatechange)|fter(?:(?:scriptexecu|upda)te|print)|udio(?:process|start|end)|d(?:apteradded|dtrack)|ctivate|lerting|bort)|DOM(?:Node(?:Inserted(?:IntoDocument)?|Removed(?:FromDocument)?)|(?:CharacterData|Subtree)Modified|A(?:ttrModified|ctivate)|Focus(?:Out|In)|MouseScroll)|r(?:e(?:s(?:u(?:m(?:ing|e)|lt)|ize|et)|adystatechange|pea(?:tEven)?t|movetrack|trieving|ceived)|ow(?:s(?:inserted|delete)|e(?:nter|xit))|atechange)|p(?:op(?:up(?:hid(?:den|ing)|show(?:ing|n))|state)|a(?:ge(?:hide|show)|(?:st|us)e|int)|ro(?:pertychange|gress)|lay(?:ing)?)|t(?:ouch(?:(?:lea|mo)ve|en(?:ter|d)|cancel|start)|ime(?:update|out)|ransitionend|ext)|u(?:s(?:erproximity|sdreceived)|p(?:gradeneeded|dateready)|n(?:derflow|load))|f(?:o(?:rm(?:change|input)|cus(?:out|in)?)|i(?:lterchange|nish)|ailed)|l(?:o(?:ad(?:e(?:d(?:meta)?data|nd)|start)?|secapture)|evelchange|y)|g(?:amepad(?:(?:dis)?connected|button(?:down|up)|axismove)|et)|e(?:n(?:d(?:Event|ed)?|abled|ter)|rror(?:update)?|mptied|xit)|i(?:cc(?:cardlockerror|infochange)|n(?:coming|valid|put))|o(?:(?:(?:ff|n)lin|bsolet)e|verflow(?:changed)?|pen)|SVG(?:(?:Unl|L)oad|Resize|Scroll|Abort|Error|Zoom)|h(?:e(?:adphoneschange|l[dp])|ashchange|olding)|v(?:o(?:lum|ic)e|ersion)change|w(?:a(?:it|rn)ing|heel)|key(?:press|down|up)|(?:AppComman|Loa)d|no(?:update|match)|Request|zoom))[\s\0]*= 

Test: http://regex101.com/r/rV7zK8

Tôi nghĩ rằng nó chặn 99% XSS vì nó là một phần của NoScript, một addon được cập nhật thường xuyên

+0

không biên dịch trong java: Gây ra bởi: java.util.regex.PatternSyntaxException: Chuỗi thoát bát phân bất hợp pháp gần chỉ số 525 – KIC

+1

Tôi đã thử một bit XSS cực kỳ đơn giản trong chuỗi kiểm tra regex101 đó và đã phá vỡ nó trong lần thử đầu tiên của tôi. Không hoàn hảo. Tất cả những gì tôi đã làm là thêm một liên kết với một 'javascript:' href. –

Các vấn đề liên quan