Hackerone

https://hackerone.com/reports/920285
《CodeQL query to detect missing origin validation in cross-origin communication via postMessage》

issues

https://github.com/github/securitylab/issues/118
CVE-2020-8127
CVE-2019-10779

Missing validation of the MessageEvent.origin allows any window to send arbitrary messages to the postMessage handler from any origin.


If the MessageEvent.data is used in some DOM sink and is used in an unsafe way, the missing check of the origin could lead to a DOM-based XSS or other unexpected behaviors.


This query detects if the MessageEvent.origin is checked or if methods like indexOf, startsWith are used to validate the origin.


Link to the now merged PR: PR github/codeql#3646

pull

https://github.com/github/codeql/pull/3646

ql

https://github.com/github/codeql/blob/baaa31665a545b65843fa9e6b4b0e69d53c64fa8/javascript/ql/src/experimental/Security/CWE-020/PostMessageNoOriginCheck.ql

  1. /**
  2. * @name Missing `MessageEvent.origin` verification in `postMessage` handlers
  3. * @description Missing the `MessageEvent.origin` verification in `postMessage` handlers, allows any windows to send arbitrary data to the `MessageEvent` listener.
  4. * This could lead to unexpected behaviour, especially when `MessageEvent.data` is used in an unsafe way.
  5. * @kind problem
  6. * @problem.severity warning
  7. * @precision high
  8. * @id js/missing-postmessageorigin-verification
  9. * @tags correctness
  10. * security
  11. * external/cwe/cwe-20
  12. */
  13. import javascript
  14. import semmle.javascript.security.dataflow.DOM
  15. /**
  16. * 调用不安全的方法校验 `MessageEvent.origin`.
  17. */
  18. class InsufficientOriginChecks extends DataFlow::Node {
  19. InsufficientOriginChecks() {
  20. exists(DataFlow::Node node |
  21. this.(StringOps::StartsWith).getSubstring() = node or
  22. this.(StringOps::Includes).getSubstring() = node or
  23. this.(StringOps::EndsWith).getSubstring() = node
  24. )
  25. }
  26. }
  27. /**
  28. * A function handler for the `MessageEvent`.
  29. */
  30. class PostMessageHandler extends DataFlow::FunctionNode {
  31. PostMessageHandler() { this.getFunction() instanceof PostMessageEventHandler }
  32. }
  33. /**
  34. * The `MessageEvent` parameter received by the handler
  35. */
  36. class PostMessageEvent extends DataFlow::SourceNode {
  37. PostMessageEvent() { exists(PostMessageHandler handler | this = handler.getParameter(0)) }
  38. /**
  39. * Holds if an access on `MessageEvent.origin` is in an `EqualityTest` and there is no call of an insufficient verification method on `MessageEvent.origin`
  40. */
  41. predicate hasOriginChecked() {
  42. exists(EqualityTest test |
  43. this.getAPropertyRead(["origin", "source"]).flowsToExpr(test.getAnOperand())
  44. )
  45. }
  46. /**
  47. * Holds if there is an insufficient method call (i.e indexOf) used to verify `MessageEvent.origin`
  48. */
  49. predicate hasOriginInsufficientlyChecked() {
  50. exists(InsufficientOriginChecks insufficientChecks |
  51. this.getAPropertyRead("origin").getAMethodCall*() = insufficientChecks
  52. )
  53. }
  54. }
  55. from PostMessageEvent event
  56. where not event.hasOriginChecked() or event.hasOriginInsufficientlyChecked()
  57. select event, "Missing or unsafe origin verification."