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

SQLi progress feedback #19092

Open
h00die opened this issue Apr 15, 2024 · 12 comments
Open

SQLi progress feedback #19092

h00die opened this issue Apr 15, 2024 · 12 comments
Labels
suggestion-feature New feature suggestions

Comments

@h00die
Copy link
Contributor

h00die commented Apr 15, 2024

@red0xff and I had previously discussed someway of giving feedback for SQLi where the output isn't near instant. So a blind SQLi for instance. I LOVE how sqlmap will give you _________ then fill it in like a_mini___a_or. It's a neat gui trick. Now obviously we can't do that with MSF, but when you have to dump 400+ characters and it takes 30+ minutes, its pretty boring just looking at a blank screen w/ no feedback.

I'd like to suggest a new feature of the SQLi libraries where there is a configurable percentage for feedback.
So for instance, it defaults to 10 (aka every 10% completed, give feedback on progress).

Output would look similar to the command stagers:

[*] SQLi progress -  10% done (40/400 characters)
[*] SQLi progress -  20% done (80/400 characters)

Thoughts?

@h00die h00die added the suggestion-feature New feature suggestions label Apr 15, 2024
@adfoster-r7
Copy link
Contributor

It's a neat gui trick. Now obviously we can't do that with MSF

Why not? 👀

Maybe I don't understand the full context, but we definitely do that here:

print "%bld%blu[*]%clr Collecting exploit #{index + 1} / #{exploit_refnames.count}\r"

As well as for the MSF spinner thread on console boot that spits out the intro message

[*] Starting the Metasploit Framework console...|
[*] sTarting the Metasploit Framework console...|
[*] stArting the Metasploit Framework console...|

...etc...

@red0xff
Copy link
Contributor

red0xff commented Apr 15, 2024

I also think that displaying data before the end of the attack would have a lot of value. Had - thought about it, @adfoster-r7 the issue was that logging APIs didn't offer a portable way to move the cursor on the screen, or to print without a newline and send backspaces. The console "starting metasploit" message is displayed through $stderr.print (https://github.com/rapid7/metasploit-framework/blob/master/lib%2Fmetasploit%2Fframework%2Fcommand%2Fconsole.rb). My understanding is that it would not be portable, and that the library should only use print_XXX from the Msf::Module::UI::Message mixin, but that would be something to improve on the logging library side if that's the case.

For @h00die's suggestion, I agree that it would help, perhaps based on the size of new data that gets retrieved? (Because 10% of the data can be very insignificant, if for example, the whole data is 20 bytes, you wouldn't print 10 progress lines, or, if it's too large, printing 10% can output information that can't be easily viewed on a terminal, and 10% can take a lot of time, printing more progress lines would be better I think for this case).

@nrathaus
Copy link
Contributor

nrathaus commented Apr 16, 2024

@h00die which script are you referring to? that is not giving output

@h00die
Copy link
Contributor Author

h00die commented Apr 16, 2024

@h00die which script are you referring to? that is not giving output

└─$ grep -r "include Msf::Exploit::SQLi" *
docs/metasploit-framework.wiki/SQL-Injection-Libraries.md:include Msf::Exploit::SQLi
lib/msf/core/exploit/sqli/postgresqli/time_based_blind.rb:  include Msf::Exploit::SQLi::TimeBasedBlindMixin
lib/msf/core/exploit/sqli/postgresqli/boolean_based_blind.rb:  include Msf::Exploit::SQLi::BooleanBasedBlindMixin
lib/msf/core/exploit/sqli/mssqli/boolean_based_blind.rb:  include Msf::Exploit::SQLi::BooleanBasedBlindMixin
lib/msf/core/exploit/sqli/sqlitei/boolean_based_blind.rb:  include Msf::Exploit::SQLi::BooleanBasedBlindMixin
lib/msf/core/exploit/sqli/mysqli/boolean_based_blind.rb:  include Msf::Exploit::SQLi::BooleanBasedBlindMixin
modules/exploits/linux/http/eyesofnetwork_autodiscovery_rce.rb:  include Msf::Exploit::SQLi
modules/exploits/multi/http/cacti_pollers_sqli_rce.rb:  include Msf::Exploit::SQLi
modules/auxiliary/gather/suite_crm_export_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/gather/grandstream_ucm62xx_sql_account_guess.rb:  include Msf::Exploit::SQLi
modules/auxiliary/gather/wp_bookingpress_category_services_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/gather/peplink_bauth_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/gather/billquick_txtid_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/gather/piwigo_cve_2023_26876.rb:  include Msf::Exploit::SQLi
modules/auxiliary/sqli/dlink/dlink_central_wifimanager_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/sqli/openemr/openemr_sqli_dump.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_chopslider_id_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_modern_events_calendar_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_loginizer_log_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_secure_copy_content_protection_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_email_sub_news_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_learnpress_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_paid_membership_pro_code_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_registrationmagic_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/wp_abandoned_cart_sqli.rb:  include Msf::Exploit::SQLi
modules/auxiliary/scanner/http/vicidial_multiple_sqli.rb:  include Msf::Exploit::SQLi

It isn't necessarily a script problem, more of a library issue.

@adfoster-r7
Copy link
Contributor

My understanding is that it would not be portable, and that the library should only use print_XXX from the Msf::Module::UI::Message mixin, but that would be something to improve on the logging library side if that's the case.

The print method that the local exploit suggester uses comes from rex/ui/subscriber:

>> self.methods.grep(/print/).map { |x| [x, self.method(x).source_location] }
...
 [:print, ["/tmp/metasploit-framework/lib/rex/ui/subscriber.rb", 74]],
...

#
# Wraps user_output.print
#
def print(msg='')
user_output.print(msg) if (user_output)
end

I believe in terms of portability, I've confirmed 10.times { |x| print("#{x + 1}\r"); sleep 0.1 }; print_line works on unix and windows consoles, it should work on anything that uses a terminal emulator like Metasploit Pro etc; and if there's a portability issue that comes up - it's likely something that we can likely handle similar to the color detection logic that we've got baked into framework already

@nrathaus
Copy link
Contributor

Dev setup, use 5.0.0 openemr:

# Use admin/pass as user/password credentials to login to openemr (from OE_USER and OE_PASS below)
# MYSQL_HOST and MYSQL_ROOT_PASS are required for openemr
# MYSQL_USER, MYSQL_PASS, OE_USER, MYSQL_PASS are optional for openemr and
#   if not provided, then default to openemr, openemr, admin, and pass respectively.
version: '3.1'
services:
  mysql:
    restart: always
    image: mariadb:10.2
    command: ['mysqld','--character-set-server=utf8']
    volumes:
    - databasevolume:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: root
  openemr:
    restart: always
    image: openemr/openemr:5.0.0
    ports:
    - 80:80
    - 443:443
    volumes:
    - logvolume01:/var/log
    - sitevolume:/var/www/localhost/htdocs/openemr/sites
    environment:
      MYSQL_HOST: mysql
      MYSQL_ROOT_PASS: root
      MYSQL_USER: openemr
      MYSQL_PASS: openemr
      OE_USER: admin
      OE_PASS: pass
    depends_on:
    - mysql
volumes:
  logvolume01: {}
  sitevolume: {}
  databasevolume: {}

Metasploit setup:

use openemr_sqli_dump
set RHOSTS 127.0.0.1
set TARGETURI /
check

[*] Trying to detect installed version
[*] 127.0.0.1:80 - The target appears to be vulnerable.

run

@nrathaus
Copy link
Contributor

How about we add:

print("slice: #{slice}\r")

To the truncated_query function?

Or similar?

It will display the slices pulled from the SQLi (not decode them) make it immune to non-printable characters, issues of newline embedded, etc?

@nrathaus
Copy link
Contributor

Referring to this code:

    def truncated_query(query)
      result = [ ]
      offset = 1
      loop do
        slice = run_sql(query.sub(/\^OFFSET\^/, offset.to_s))
        offset += @truncation_length # should be same as @truncation_length for most cases
        result << slice
        print("slice: #{slice}\r")
        vprint_status "{SQLi} Truncated output: #{slice} of size #{slice.size}"
        print_warning "The block returned a string larger than the truncation size : #{slice}" if slice.length > @truncation_length
        break if slice.length < @truncation_length
      end
      result.join
    end

@nrathaus
Copy link
Contributor

BTW: there seems to be duplicate code here, not sure why there isn't a base class that has def that are shared and overrides where necessary

@nrathaus
Copy link
Contributor

Example of duplicate code:

def truncated_query(query)
def test_vulnerable

Actually... seems like there aren't that much duplicate code

@nrathaus
Copy link
Contributor

I don't see how truncated_query which is where the loop happens, knows anything about the progress, it knows of the offset but not of the maximum value of this offset

@nrathaus
Copy link
Contributor

@h00die I looked more into this, there is no way to show progress - as we don't know the amount out of a total we have collected

My only idea at the moment is to show the slice returned with a \r so that it updates, when there are no more slices it shows the outcome

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
suggestion-feature New feature suggestions
Projects
None yet
Development

No branches or pull requests

4 participants