Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ruby: support sprintf formatted string with modulo operator #15945

Open
MaxSchlueter opened this issue Mar 16, 2024 · 0 comments
Open

Ruby: support sprintf formatted string with modulo operator #15945

MaxSchlueter opened this issue Mar 16, 2024 · 0 comments
Labels
question Further information is requested Ruby

Comments

@MaxSchlueter
Copy link
Contributor

MaxSchlueter commented Mar 16, 2024

I noticed that dataflow in Ruby isn't propagated to Kernel.sprintf formatted strings, e.g. the stored xss query should flag this code in an ERB template:

<%# BAD: Kernel.sprintf modulo operator syntax %>
<%= "Welcome %{user}".html_safe % { user: @user.handle } %>

The string literal is parsed as a a single Ast::StringTextComponent, where it should probably also contain a Ast::StringInterpolationComponent. I tried to work around this problem using an additional taint step:

  predicate isAdditionalSprintfTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
    exists(ModuloExpr expr, HashLiteral hash, StringLiteral str |
      hash.getParent*() = expr.getRightOperand() and
      str.getParent*() = expr.getLeftOperand() and
      hash.getAKeyValuePair().getValue() = node1.asExpr().getExpr() and 
      str = node2.asExpr().getExpr()
    )
  }

which works for the code snippet above, but doesn't work when the dataflow gets a bit more complex:

<% sink = "Welcome %{user}".html_safe %>
<%= sink % { user: @user.handle } %>

I tried the following, but it doesn't work:

  predicate isAdditionalSprintfTaintStep(DataFlow::Node node1, DataFlow::Node node2) {
    exists(ModuloExpr expr, HashLiteral hash, StringLiteral str |
      DataFlow::localExprFlow(hash.getAControlFlowNode(), expr.getRightOperand().getAControlFlowNode()) and
      DataFlow::localExprFlow(str.getAControlFlowNode(), expr.getLeftOperand().getAControlFlowNode()) and
      hash.getAKeyValuePair().getValue() = node1.asExpr().getExpr() and 
      str = node2.asExpr().getExpr()
    )
  }

How do I catch the insecure code snippet above using local dataflow?

@MaxSchlueter MaxSchlueter added the question Further information is requested label Mar 16, 2024
@sidshank sidshank added the Ruby label Mar 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested Ruby
Projects
None yet
Development

No branches or pull requests

2 participants