‏הצגת רשומות עם תוויות mysql. הצג את כל הרשומות
‏הצגת רשומות עם תוויות mysql. הצג את כל הרשומות

יום שני, 13 ביולי 2015

MySql Proxy



מסדי נתונים חשופים להמון סוגים של התקפות וזליגת מידע, דרך לטפל בבעיה היא בעזרת Proxy שיושב בין מי שמבקש ולמסד עצמו ומאפשר לנתח את הבקשות והתשובות לפני שהן חוזרות בחזרה ללקוח, נניח שמשהו הצליח לבצע הזרקה של קוד זדוני שמחזיר את כל כרטיסי האשראי בטבלה, הפרוקסי יכול לתפוס את הבקשה ולהפיל אותה, או לעשות מיסוך על כרטיסי האשראי בצורה שלא יהיה ניתן לעשות איתם שימוש.

דרישות:

שימו לב!
  • המאמר נכתב על Windows 7 64 Bit
לפני שנתחיל לצלול פנימה יש להוריד את ולפרוס את קבצי MySql Proxy באיזה מקום שתרצו על השרת, לאחר מכן יש להוריד ולהתקין את Lua, שפת סקריפטים מאוד מהירה, היא פופלרית בעיקר ב Embedded ומשחקי מחשב, היה בה שימוש רחב ב World Of Warcraft.

לצורך הדוגמה ניצור טבלה שתכיל מספרי אשראי ונעמיס עליה נתונים,נבצע שאילתה פשוטה:

בקשה ישירה למסד הנתונים

התוצאות מכילות כרטיסי אשראי שניתן לראות אותם בבירור בתשובה שחוזרת, כמובן שהדרך המסורתית היא להצפין את המידע אבל הכלים שה Proxy נותן מאפשרים לך שליטה על כל נקודה מרגע ההתממשקות עד להחזרת התוצאות ללקוח כפי שנראה בהמשך.

Proxy

פעולת ה Proxy היא ברורה מאוד וכבר הספקתי לכתוב עליה בעבר, אבל במבט מהיר אפשר לראות שהמשתמשים לא באמת מגיעים למסד נתונים אלא לתחנת בניים שתחליט מה לעשות עם הבקשה והתשובה שחוזרת, בשונה מ Proxy "רגיל" שמעביר דרכו בקשות ומשנה אותם באופן בסיסי, ה MySql Proxy מאפשר לנתח את הפרוטוקול ולשנות אותו באופן פשוט למדי.


על מנת להפעיל את ה Proxy יש לכתוב את הפקודה הבאה:

C:\mySqlProxy\bin>mysql-proxy.exe --proxy-backend-addresses=127.0.0.1:3306 --proxy-address=127.0.0.1:4040 --proxy-lua-script=all-hooks.lua

הפקודה מחברת את שרת ה Proxy למסד הנתונים ובנוסף מוסיפים קריאה לקובץ סקריפט של Lua, מאותו רגע כל בקשה שתגיע לפורט 4040 תפעיל מספר פונקציות ונוכל לדוג אותן, לדוגמה ברגע שיבצעו שיאלתא, הפונקציה read_query תרוץ ונוכל להחליט אם להעביר את השאילתא או לא ובמקרה של תשובה מהשרת הפונקציה read_query_result תרוץ ובה נוכל לשנות את המידע שחוזר.

Hooks


-- all-hooks.lua
local access_ndx = 0

-- fired when client connect to server
function connect_server()
    print_access ('inside connect_server')
end

-- fired when starting the handshake
function read_handshake( auth )
    print_access ('inside read_handshake' )
end

-- fired when starting the authentication
function read_auth( auth )
    print_access ('inside read_auth ')
end

--fired when authentication finished
function read_auth_result( auth )
    print_access ('inside read_auth_result')
end

--fired when client disconnected
function disconnect_client()
    print_access('inside disconnect_client')
end

--fired when query requested
function read_query (packet)
proxy.queries:append(1, packet,{ resultset_is_needed = true })
return proxy.PROXY_SEND_QUERY
end

--fired when query result
function read_query_result (inj)

--create result set containes columns and rows
proxy.response.resultset = {fields = {}, rows = {}}

--checking if the query holding creditcard table name
if(string.match(inj.query,"creditcard")) then

for n = 1, #inj.resultset.fields do
-- insert column to table
table.insert(proxy.response.resultset.fields, {type
             =inj.resultset.fields[n].type,name = inj.resultset.fields[n].name})
end


for row in inj.resultset.rows do
if(row ~= nil) then
 for i,v in pairs(row) do
--looking for creditcard pattern
if string.match(v,'%d%d%d%d%-%d%d%d%d%
                                                                 -%d%d%d%d%-%d%d%d%d') then
print_access("found visa - column position: " .. i 
                                                                      .. " column value: " .. v)
row[i] = "mask credit card"
end
 end
table.insert(proxy.response.resultset.rows, row)
end
end

--overwrite results
proxy.response.type = proxy.MYSQLD_PACKET_OK
return proxy.PROXY_SEND_RESULT
end
end

-- simple print message
function print_access(msg)
    access_ndx = access_ndx + 1
    print( string.format('%3d %-30s',access_ndx,msg))
end



מייצרים טבלה ריקה, עוברים על הטבלה שחזרה מהמסד נתונים ושופכים אותה לטבלה שיצרנו, לפני שמכניסים שורה חדשה מחפשים אם יש ערך שתואם למבנה כרטיס אשראי ודורסים אותו.

התוצאות שחוזרות מה Proxy


סיכום

ראינו רק דרך פעולה אחת עם ה Proxy ש MySql  אבל אפשר להשתמש בו בתחומים נוספים כמו ניהול עומסים, שרידות ובקרה, בעזרתו ניתן להגדיל את הזמינות ואמינות המידע ולהדק את חגורת האבטחה סביב המידע שרגיש לכולנו.

לא תשתמש בו?

יום חמישי, 22 במרץ 2012

MySql Connection Flexibility




MySql הוא אחד ממסדי הנתונים הנחשבים בתעשייה ונהפך לסמל סטטוס, אין ספק שהוא אחד המובלים בתחום והיותו חינמי מאפשר לנו לבנות מאגרי מידע בעצמנו ביעילות ובמינימום הוצאות אבל זה לא נגמר בזה, היכולת שלו לעבוד על מערכות הפעלה שונות (Windows / Linux) מנחיתה מכת מוות ל Microsoft SQL שנמכר באלפי דולרים וכמובן שעובד על פלטפורמות Windows בלבד, לא באתי להלל אותו למרות שאולי צריך, אבל בהחלט היה פה מהפך, במאמר זה נעבור על ההתקנה של MySql ע"ג שרת Linux ואת דרכי התקשורות איתו ב 3 שפות :C ,C# ,Perl.

דרישות מקדימות:
שרת לינוקס - במקרה שלי Fedora.

התקנה:
#: yum install mysql  -  עבור התממשקות
#: yum install mysql-devel -  עבור התממשקות
#: perl -MCPAN- e "install DBD::mysql" - עבור התממשקות
#: yum install mysql-server

הקמה:
הפעלת ה Service:
#:service mysqld start

הגדרת סיסמא לשרת:
#:mysqladmin -u root password 'new-password'

התחברות לשרת:
#:mysql -u root -p

יצירת משתמש חדש:
mysql>CREATE USER root@'localhost' identified by 'new-password';

משהו קטן על הדרך - יצירת משתמש לחיבור מרוחק:
mysql>CREATE USER root@'%' identified by 'new-password';

נתינת הרשאות למשתמשים:
mysql> GRANT  alter, create, delete, drop, index, insert, select, 
            update on *.* to 'root'@'localhost';
יצירת Database חדש:
mysql> CREATE DATABASE db_new; 
יצירת טבלה חדשה:
mysql>CREATE TABLE example(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
 name VARCHAR(30),
 age INT)


בשלב זה אני יעצור עם ה Console כי אין לזה סוף אני ממליץ לעבוד עם אחד מ IDE's שקיימים בשוק ואם אתם לא מכירים ניתן להוריד את ה Workbench מאתר MySql , המאמר לא לא נוגע בכל הקשור לתחזוקה ונקודת המוצא היא שיש לכם רקע ב Sql ובשפות השונות, בעצם עד כאן הוא שלב בניית השרת עבור ההדגמה.

בכל צורות ההתחברות יש מכנה משותף,  האובייקטים שנעבוד איתם כמעט זהים בצורת העבודה ההבדל העיקרי הוא בשמות, ובכל שפה הם מוגדרים אחרת ודורשים ספריות אחרות אבל בגדול הם עושים אותו דבר, בחרתי דווקא בשפות אלו בגלל צורת השימוש , כלומר, שפת C נחשבת לשפה נמוכה , ואילו C# נחשבת לשפה עליונה ( ה Api עשיר יותר) ו Perl כשפת סקריפטים , בקיצור מגוון רחב של מימושים.

Connectors
לכל שפה יש את ה Connector שלה, שהוא בעצם ה Driver שמחבר אותנו למסד, באתר MySql תראו רשימה מרשימה של Connectors במגוון שפות ופלטפורמות, אנחנו נעבוד עם 3 צורות חיבור שונות , mysql-devel מכיל את כל קבצי ה Headers שאיתם נעבוד בשפת C , בעזרת ה Interface Module שנקרא DBI נעבוד עם Perl ובעזרת ה MySql.Data.dll נעבוד עם C#.

יאללה מספיק עם החרטה ונתחיל לכתוב!

Perl
Practical Extraction and Reporting Language היא שפת סקריפטים פופלרית מאוד וניתן להשתמש בה במערכות הפעלה שונות, סביבת הפיתוח שאני משתמש ב Perl נקראת Padre , אז כמו שאמרתי בהתחלה חייבים את המודול של DBD שהוא חלק מה DBI.


#!/usr/bin/perl

use DBI;
use DBD::mysql;


#Connection Parameters
$host = "localhost";
$database = "DataBaseName";
$tablename = "TableName";
$user = "UserName";
$pw = "PassWord";

my $dsn = 'dbi:mysql:DataBaseName:localhost:3306';

sub SendQuery($)
{
    $connect = DBI->connect($dsn, $user, $pw);
    my $sth = $connect->prepare($_[0]);
    $sth->execute();

    # Preview the return result of 
    while(@row = $sth->fetchrow_array()){
     print "$row[0]: $row[1] \n";  }
}

הפונקציה מאוד פשוטה, ככה זה בשפות סקריפטים.

#C
פה העסק כבר יותר מסובך וצריך מערך של פונקציות שבונים לנו שכבה בתוכנית שלנו שנקראת DAL - Data Access Layer , גם פה אסור לשכוח להוריד את ה Connector/.Net מאתר MySql, בנוסף נשתמש ב Class עזר שנקרא Api Response שמחזיר לנו את הנתונים, במקרה הזה ברור שנשתמש ב Visual Studio.


///---------------------------------------------DATA ACCESS LAYER---------------------------------
///---created by: Proxytype 17/3/2012 ------------------------------------------------------------------
///--- http://proxytype.blogspot.com ---------------------------------------------------------------------
///--- keep this info attach ----------------------------------------------------------------------THX------

using System;
using System.Collections.Generic;
using System.Web;
using MySql.Data.MySqlClient;

/// <summary>
/// DAL - Data Access Layer
/// </summary>
public class DAL
{

    MySqlConnection myconnection = new MySqlConnection("Server=127.0.0.1;
    Database= DataBaseName;Uid= UserName ;Pwd= PassWord ;charset=hebrew");
    MySqlCommand mycommand = new MySqlCommand();
    MySqlDataAdapter myadapter = new MySqlDataAdapter();

public DAL()
{
        //connecting the Command to the Connection
        mycommand.Connection = myconnection;
        //connecting the Adapter to the Command
        myadapter.SelectCommand = mycommand;
}

    /// <summary>
    /// execute query by sql statement
    /// </summary>
    /// <param name="sql">sql statement</param>
    /// <returns>api response of the operation</returns>
    public api_response execute_query(string sql)
    {
        //create new instance of api response
        api_response myresponse = new api_response();

        try
        {
            //attach the query command to the Command
            mycommand.CommandText = sql;
            myconnection.Open();
            mycommand.ExecuteNonQuery();

            myresponse.sucess = true;
         
        }
        catch (Exception ex)
        {
            myresponse.ex = ex.Message;
            myresponse.sucess = false;
        }
        finally
        {
            myconnection.Close();
            mycommand.CommandText = "";
        }

        //return api response for diagnose
        return myresponse;
    }

    /// <summary>
    /// execute query by sql statement using stored procedures
    /// </summary>
    /// <param name="sql">stored procedure name</param>
    /// <param name="myparam">parameter array for stored procedure</param>
    /// <returns>api response of the operation</returns>
    public api_response execute_query(string sql, MySqlParameter[] myparam)
    {
        //create new instance of api response
        api_response myresponse = new api_response();

        try
        {
            //adding the parameters to the Command
            for (int i = 0; i < myparam.Length; i++)
            { mycommand.Parameters.Add(myparam[i]); }

            //change command type of the Command
            mycommand.CommandType = System.Data.CommandType.StoredProcedure;
            mycommand.CommandText = sql;

            myconnection.Open();
            mycommand.ExecuteNonQuery();

            myresponse.sucess = true;
        }
        catch (Exception ex)
        {
            myresponse.sucess = false;
            myresponse.ex = ex.Message;
           
        }
        finally
        {
            myconnection.Close();

            //return the command type for text
            mycommand.CommandType = System.Data.CommandType.Text;
            mycommand.CommandText = "";
        }

        //return api response for diagnose
        return myresponse;
    }

    /// <summary>
    ///  execute scalar query by sql statement
    /// </summary>
    /// <param name="sql">sql statement</param>
    /// <returns>api response of the operation</returns>
    public api_response execute_scalar(string sql)
    {

        //create new instance of api response 
        api_response myresponse = new api_response();
        try
        {
            mycommand.CommandText = sql;
            myconnection.Open();

            //set the scalar object return from the execute
            myresponse.scalar_object = mycommand.ExecuteScalar();
            myresponse.sucess = true;

        }
        catch (Exception ex)
        {
            myresponse.ex = ex.Message;
            myresponse.sucess = false;
         
        }
        finally
        {
            myconnection.Close();
            mycommand.CommandText = "";
        }

        //return api response for diagnose
        return myresponse;
    }


    /// <summary>
    /// execute scalar query by sql statement using stored procedures
    /// </summary>
    /// <param name="sql">stored procedure name</param>
    /// <param name="myparam">parameter array for stored procedure</param>
    /// <returns>api response of the operation</returns>
    public api_response execute_scalar(string sql, MySqlParameter[] myparam)
    {
        //create new instance of api response
        api_response myresponse = new api_response();

        try
        {
            //adding the parameters to the Command
            for (int i = 0; i < myparam.Length; i++)
            { mycommand.Parameters.Add(myparam[i]); }

            //change command type of the Command
            mycommand.CommandType = System.Data.CommandType.StoredProcedure;
            mycommand.CommandText = sql;

            myconnection.Open();

            //set the scalar object return from the execute
            myresponse.scalar_object = mycommand.ExecuteScalar();
            myresponse.sucess = true;
       
        }
        catch (Exception ex)
        {
            myresponse.sucess = false;
            myresponse.ex = ex.Message;
        }
        finally
        {
            myconnection.Close();

            //return the command type for text
            mycommand.CommandType = System.Data.CommandType.Text;
            mycommand.CommandText = "";
        }

        //return api response for diagnose
        return myresponse;
    }


    /// <summary>
    /// return date by sql statement
    /// </summary>
    /// <param name="sql">sql statement</param>
    /// <returns>api response of the operation</returns>
    public api_response fill_adapter(string sql)
    {
        //create new instance of api response
        api_response myresponse = new api_response();

        try
        {
            //attach the query command to the Command
            mycommand.CommandText = sql;

            //set api response DataTable to the adapter for fill
            myadapter.Fill( myresponse.result_table);
            myresponse.sucess = true;
        }
        catch (Exception ex)
        {
            myresponse.sucess = false;
            myresponse.ex = ex.Message;
         
        }

        //return api response for diagnose
        return myresponse;
    }


    /// <summary>
    /// return date by sql statement using stored procedures
    /// </summary>
    /// <param name="sql">stored procedure name</param>
    /// <param name="myparam">parameter array for stored procedure</param>
    /// <returns>api response of the operation</returns>
    public api_response fill_adapter(string sql, MySqlParameter[] myparam)
    {
        //create new instance of api response
        api_response myresponse = new api_response();

        try
        {
            //adding the parameters to the Command
            for (int i = 0; i < myparam.Length; i++)
            { mycommand.Parameters.Add(myparam[i]); }

            //change command type of the Command
            mycommand.CommandType = System.Data.CommandType.StoredProcedure;
            mycommand.CommandText = sql;

            //set api response DataTable to the adapter for fill
            myadapter.Fill(myresponse.result_table);
        }
        catch (Exception ex)
        {
            myresponse.sucess = false;
            myresponse.ex = ex.Message;
        }
        finally
        {
            //return the command type for text
            mycommand.CommandType = System.Data.CommandType.Text;
            mycommand.CommandText = "";
        }

        //return api response for diagnose
        return myresponse;
    }
   
}

/// <summary>
/// api response object
/// </summary>
public class api_response
{
    public bool sucess;
    public string ex;
    public object scalar_object;
    public DataTable result_table = new DataTable();
}

///---------------------------------------------END COPY PASTE -----------------------------------

אז מה היה לנו פה? מערך של פונקציות לטיפול בסוגים שונים של שאילתות בשילוב Stored Procedure בנוסף אובייקט מרכזי שמנהל לנו את המידע ובקרה במקרה של תקלות, פשוט תעתיקו ותדביקו בפרוייקט שלכם, וקיבלתם DAL לעבודה שוטפת עם MySql.

C
התהליך ב C הוא קצת שונה, צריך להוריד את ה Headers של Mysql כמו שהסברתי בהתחלה, חשוב לי לציין שהקוד נוסה על מערכות לינוקס בלבד, יש פה גם קשר ישיר לסביבת העבודה, במקרה הזה הסביבה היא Eclipse ונעבוד מול MySql C API.

תחילה נגדיר מספר דברים בסביבה:

1. הגדרת ה Compiler 




2.הגדרת ה Linker



עכשיו אחרי ההכנות זה הזמן לכתוב הקוד:

//imported to keep this order 
#include <my_global.h>
#include <mysql.h>

void makequery(char * query)
{
 MYSQL *conn;
 
         //init the connection return ID 
         conn = mysql_init(NULL);
         
 if(conn == NULL){
  printf("Conn Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
     exit(1);
 }

 conn = mysql_real_connect(conn, "localhost", " UserName ", 
          " PassWord ", " DataBaseName ", 0, NULL, 0);

 if (conn == NULL) {
      printf("Real Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
      exit(1);
  }


 if (mysql_query(conn,  query)) {
       printf("Query Error %u: %s\n", mysql_errno(conn), mysql_error(conn));
       exit(1);
   }

 mysql_close(conn);

}

סיכום:
מה שניסיתי להדגים פה את הגמישות של MySql ובכלל להציג את היכולות שלו, זה היה באמת קצר...

ואוו...

יום שני, 16 באוגוסט 2010

ODBC 3.51 windows server 2008 64bit

אחרי כל הצרות שעברתי עם ה IIS 7 עכשיו נוצרו בעיות אחרות איך אני מתחבר לאפליקציות ישנות שמשתמשות בחיבור ODBC ישן כמו גרסה 3.51.

על מנת להפעיל את ה ODBC יש להוריד 2 גרסאות מהאתר של MYSQL:


1.את הגרסה ה 32 BIT


2.את הגרסה 64 BIT


יש להתקין את הגרסה 32 BIT ע"י קובץ ההתקנה המצורף.
אך עדיין לא נראה את הגרסה מותקנת Data Sources (ODBC).
את הגרסה 64 BIT יש לפתוח מה ZIP להפעיל CMD ולרשום:
C:\mysql-connetctor>install.bat 0
0 - מסמן התקנה של הגרסת RELEASE.
1 - מסמן התקנה של הגרסה DEBUG.

לאחר סיום ההתקנות יש להפעיל את ה IIS מחדש, ויש לכם ODBC גרסה 3.51.

בהצלחה.