mirror of
				https://github.com/sqlmapproject/sqlmap.git
				synced 2025-11-04 09:57:38 +03:00 
			
		
		
		
	Parse and build the response block
This commit is contained in:
		
							parent
							
								
									0d756a8823
								
							
						
					
					
						commit
						fae965f8b6
					
				| 
						 | 
					@ -6,7 +6,10 @@ See the file 'doc/COPYING' for copying permission
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from BaseHTTPServer import BaseHTTPRequestHandler
 | 
					from BaseHTTPServer import BaseHTTPRequestHandler
 | 
				
			||||||
 | 
					from httplib import HTTPResponse
 | 
				
			||||||
from StringIO import StringIO
 | 
					from StringIO import StringIO
 | 
				
			||||||
 | 
					import base64
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from lib.core.data import logger
 | 
					from lib.core.data import logger
 | 
				
			||||||
from lib.core.settings import VERSION
 | 
					from lib.core.settings import VERSION
 | 
				
			||||||
| 
						 | 
					@ -122,18 +125,68 @@ class Request:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Response:
 | 
					class Response:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __init__(self):
 | 
					    extract_status = re.compile(r'\((\d{3}) (.*)\)')
 | 
				
			||||||
        pass
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, httpVersion, status, statusText, headers, content, raw=None, comment=None):
 | 
				
			||||||
 | 
					        self.raw = raw
 | 
				
			||||||
 | 
					        self.httpVersion = httpVersion
 | 
				
			||||||
 | 
					        self.status = status
 | 
				
			||||||
 | 
					        self.statusText = statusText
 | 
				
			||||||
 | 
					        self.headers = headers
 | 
				
			||||||
 | 
					        self.content = content
 | 
				
			||||||
 | 
					        self.comment = comment
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def parse(cls, raw):
 | 
					    def parse(cls, raw):
 | 
				
			||||||
        return cls()
 | 
					        altered = raw
 | 
				
			||||||
 | 
					        comment = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if altered.startswith("HTTP response ["):
 | 
				
			||||||
 | 
					            io = StringIO(raw)
 | 
				
			||||||
 | 
					            first_line = io.readline()
 | 
				
			||||||
 | 
					            parts = cls.extract_status.search(first_line)
 | 
				
			||||||
 | 
					            status_line = "HTTP/1.0 %s %s" % (parts.group(1), parts.group(2))
 | 
				
			||||||
 | 
					            remain = io.read()
 | 
				
			||||||
 | 
					            altered = status_line + "\n" + remain
 | 
				
			||||||
 | 
					            comment = first_line
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        response = HTTPResponse(FakeSocket(altered))
 | 
				
			||||||
 | 
					        response.begin()
 | 
				
			||||||
 | 
					        return cls(httpVersion="HTTP/1.1" if response.version == 11 else "HTTP/1.0",
 | 
				
			||||||
 | 
					                   status=response.status,
 | 
				
			||||||
 | 
					                   statusText=response.reason,
 | 
				
			||||||
 | 
					                   headers=response.msg,
 | 
				
			||||||
 | 
					                   content=response.read(-1),
 | 
				
			||||||
 | 
					                   comment=comment,
 | 
				
			||||||
 | 
					                   raw=raw)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def toDict(self):
 | 
					    def toDict(self):
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
 | 
					            "httpVersion": self.httpVersion,
 | 
				
			||||||
 | 
					            "status": self.status,
 | 
				
			||||||
 | 
					            "statusText": self.statusText,
 | 
				
			||||||
 | 
					            "headers": [dict(name=key, value=value) for key, value in self.headers.items()],
 | 
				
			||||||
 | 
					            "content": {
 | 
				
			||||||
 | 
					                "mimeType": self.headers.get('Content-Type'),
 | 
				
			||||||
 | 
					                "encoding": "base64",
 | 
				
			||||||
 | 
					                "text": base64.b64encode(self.content),
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            "comment": self.comment,
 | 
				
			||||||
 | 
					            "_raw": self.raw,
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class FakeSocket:
 | 
				
			||||||
 | 
					    # Original source:
 | 
				
			||||||
 | 
					    # https://stackoverflow.com/questions/24728088/python-parse-http-response-string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, response_text):
 | 
				
			||||||
 | 
					        self._file = StringIO(response_text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def makefile(self, *args, **kwargs):
 | 
				
			||||||
 | 
					        return self._file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class HTTPRequest(BaseHTTPRequestHandler):
 | 
					class HTTPRequest(BaseHTTPRequestHandler):
 | 
				
			||||||
    # Original source:
 | 
					    # Original source:
 | 
				
			||||||
    # https://stackoverflow.com/questions/4685217/parse-raw-http-headers
 | 
					    # https://stackoverflow.com/questions/4685217/parse-raw-http-headers
 | 
				
			||||||
| 
						 | 
					@ -171,7 +224,7 @@ if __name__ == '__main__':
 | 
				
			||||||
            self.assertEqual("HTTP/1.0", req.httpVersion)
 | 
					            self.assertEqual("HTTP/1.0", req.httpVersion)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        def test_with_request_as_logged_by_sqlmap(self):
 | 
					        def test_with_request_as_logged_by_sqlmap(self):
 | 
				
			||||||
            raw = "HTTP request [#75]:\nPOST /create.php HTTP/1.1\nHost: 240.0.0.2\nAccept-encoding: gzip,deflate\nCache-control: no-cache\nContent-type: application/x-www-form-urlencoded; charset=utf-8\nAccept: */*\nUser-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10\nCookie: PHPSESSID=65c4a9cfbbe91f2d975d50ce5e8d1026\nContent-length: 138\nConnection: close\n\nname=test%27%29%3BSELECT%20LIKE%28%27ABCDEFG%27%2CUPPER%28HEX%28RANDOMBLOB%28000000000%2F2%29%29%29%29--&csrfmiddlewaretoken=594d26cfa3fad\n"  # noqa
 | 
					            raw = "HTTP request [#75]:\nPOST /create.php HTTP/1.1\nHost: 127.0.0.1\nAccept-encoding: gzip,deflate\nCache-control: no-cache\nContent-type: application/x-www-form-urlencoded; charset=utf-8\nAccept: */*\nUser-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/534.10 (KHTML, like Gecko) Chrome/8.0.552.215 Safari/534.10\nCookie: PHPSESSID=65c4a9cfbbe91f2d975d50ce5e8d1026\nContent-length: 138\nConnection: close\n\nname=test%27%29%3BSELECT%20LIKE%28%27ABCDEFG%27%2CUPPER%28HEX%28RANDOMBLOB%280.0.10000%2F2%29%29%29%29--&csrfmiddlewaretoken=594d26cfa3fad\n"  # noqa
 | 
				
			||||||
            req = Request.parse(raw)
 | 
					            req = Request.parse(raw)
 | 
				
			||||||
            self.assertEqual("POST", req.method)
 | 
					            self.assertEqual("POST", req.method)
 | 
				
			||||||
            self.assertEqual("138", req.headers["Content-Length"])
 | 
					            self.assertEqual("138", req.headers["Content-Length"])
 | 
				
			||||||
| 
						 | 
					@ -204,4 +257,36 @@ if __name__ == '__main__':
 | 
				
			||||||
                "text": "name=test&csrfmiddlewaretoken=594d26cfa3fad\n",
 | 
					                "text": "name=test&csrfmiddlewaretoken=594d26cfa3fad\n",
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ResponseParseTest(unittest.TestCase):
 | 
				
			||||||
 | 
					        def test_parse_standard_http_response(self):
 | 
				
			||||||
 | 
					            raw = "HTTP/1.1 404 Not Found\nContent-length: 518\nX-powered-by: PHP/5.6.30\nContent-encoding: gzip\nExpires: Thu, 19 Nov 1981 08:52:00 GMT\nVary: Accept-Encoding\nUri: http://127.0.0.1/\nServer: Apache/2.4.10 (Debian)\nConnection: close\nPragma: no-cache\nCache-control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\nDate: Fri, 23 Jun 2017 16:18:17 GMT\nContent-type: text/html; charset=UTF-8\n\n<!doctype html>\n<html>Test</html>\n"  # noqa
 | 
				
			||||||
 | 
					            resp = Response.parse(raw)
 | 
				
			||||||
 | 
					            self.assertEqual(resp.status, 404)
 | 
				
			||||||
 | 
					            self.assertEqual(resp.statusText, "Not Found")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        def test_parse_response_as_logged_by_sqlmap(self):
 | 
				
			||||||
 | 
					            raw = "HTTP response [#74] (200 OK):\nContent-length: 518\nX-powered-by: PHP/5.6.30\nContent-encoding: gzip\nExpires: Thu, 19 Nov 1981 08:52:00 GMT\nVary: Accept-Encoding\nUri: http://127.0.0.1/\nServer: Apache/2.4.10 (Debian)\nConnection: close\nPragma: no-cache\nCache-control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0\nDate: Fri, 23 Jun 2017 16:18:17 GMT\nContent-type: text/html; charset=UTF-8\n\n<!doctype html>\n<html>Test</html>\n"  # noqa
 | 
				
			||||||
 | 
					            resp = Response.parse(raw)
 | 
				
			||||||
 | 
					            self.assertEqual(resp.status, 200)
 | 
				
			||||||
 | 
					            self.assertEqual(resp.statusText, "OK")
 | 
				
			||||||
 | 
					            self.assertEqual(resp.headers["Content-Length"], "518")
 | 
				
			||||||
 | 
					            self.assertIn("Test", resp.content)
 | 
				
			||||||
 | 
					            self.assertEqual("HTTP response [#74] (200 OK):\n", resp.comment)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class ResponseRenderTest(unittest.TestCase):
 | 
				
			||||||
 | 
					        def test_simple_page_encoding(self):
 | 
				
			||||||
 | 
					            resp = Response(status=200, statusText="OK",
 | 
				
			||||||
 | 
					                            httpVersion="HTTP/1.1",
 | 
				
			||||||
 | 
					                            headers={"Content-Type": "text/html"},
 | 
				
			||||||
 | 
					                            content="<html><body>Hello</body></html>\n")
 | 
				
			||||||
 | 
					            out = resp.toDict()
 | 
				
			||||||
 | 
					            self.assertEqual(200, out["status"])
 | 
				
			||||||
 | 
					            self.assertEqual("OK", out["statusText"])
 | 
				
			||||||
 | 
					            self.assertIn({"name": "Content-Type", "value": "text/html"}, out["headers"])
 | 
				
			||||||
 | 
					            self.assertEqual(out["content"], {
 | 
				
			||||||
 | 
					                "mimeType": "text/html",
 | 
				
			||||||
 | 
					                "encoding": "base64",
 | 
				
			||||||
 | 
					                "text": "PGh0bWw+PGJvZHk+SGVsbG88L2JvZHk+PC9odG1sPgo=",
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    unittest.main(buffer=False)
 | 
					    unittest.main(buffer=False)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user