Project

General

Profile

Actions

Bug #4797

closed

mysql sql injection

Added by Drus Kor about 8 years ago. Updated almost 8 years ago.

Status:
Closed
Priority:
High
Assignee:
Target version:
Start date:
03/08/2016
Due date:
% Done:

0%

Estimated time:

Description

#include <Wt/Dbo/Dbo>
#include <Wt/Dbo/WtSqlTraits>
#include <Wt/Dbo/backend/MySQL>
#include <Wt/Dbo/FixedSqlConnectionPool>
#include <Wt/Dbo/Session>
#include <Wt/Utils>
#include <iostream>

using namespace Wt;
class TestTable : public Dbo::Dbo<TestTable>
{
public:
  TestTable() : somestring( "" ) {}
  TestTable( const std::string &str ) : somestring( str ) {}
  virtual ~TestTable(){}
  std::string somestring;
  template<class Action>
  void persist( Action& a )
  {
    Wt::Dbo::field    ( a, somestring, "somestring" );
  }
};

Dbo::FixedSqlConnectionPool glob_pool( new Dbo::backend::MySQL( "db", "user", "pass" ), 3 );

void setConnection( Dbo::Session &ses )
{
  ses.setConnectionPool( glob_pool );
  ses.mapClass<TestTable>  ( "test" );
}

int main()
{
  const std::string try_write = "Hello World!" + Utils::sha1( "Hello World!" );

  std::cout << try_write << std::endl;

  // create db
  try
  {
    Dbo::Session session;
    setConnection( session );
    Dbo::Transaction transaction( session );
    session.createTables();
    transaction.commit();
  }
  catch( std::exception &e )
  {
    std::cout << e.what() << std::endl;
  }

  // write
  try
  {
    Dbo::Session session;
    setConnection( session );
    Dbo::Transaction transaction( session );

    Dbo::ptr<TestTable> text( new TestTable( try_write ) );
    session.add( text );

    transaction.commit();
  }
  catch( std::exception &e )
  {
    std::cout << e.what() << std::endl;
  }

  // read
  try
  {
    Dbo::Session session;
    setConnection( session );
    Dbo::Transaction transaction( session );

    Dbo::collection<Dbo::ptr<TestTable> > collection = session.find<TestTable>();
    for( Dbo::collection<Dbo::ptr<TestTable> >::iterator it = collection.begin(); it != collection.end(); it++ )
    {
      std::cout << (*it)->somestring << std::endl;
    }
    transaction.commit();
  }
  catch( std::exception &e )
  {
    std::cout << e.what() << std::endl;
  }

//  Hello World!.����T�}_/���#(q
//  Hello World!.
//  sql injection vulnerability ^^^
//

//  NOT TESTED!
//
//  virtual void bind(int column, const std::string& value)
//  {
//    if (in_pars_ == 0)
//      throw MySQLException(std::string("Try to bind too much?"));

//    DEBUG(std::cerr << this << " bind " << column << " "
//          << value << std::endl);

//    unsigned long * len = (unsigned long *)malloc(sizeof(unsigned long));

//    char * data;
//    //memset(&in_pars_[column], 0, sizeofin_pars_[column]);// Check
//    in_pars_[column].buffer_type = MYSQL_TYPE_STRING;

//->  unsigned long bufLen = value.length() * 2 + 1;
//    data = (char *)malloc(bufLen);
//->  *len = mysql_real_escape_string(stmt_,data,value.c_str(),value.length());
//    freeColumn(column);
//    in_pars_[column].buffer = data;
//    in_pars_[column].buffer_length = bufLen;
//    in_pars_[column].length = len;
//    in_pars_[column].is_null = 0;
//  }
//
//  virtual void bind(int column, const std::vector<unsigned char>& value)


  return 0;
}
Actions #1

Updated by Drus Kor about 8 years ago

sorry for format

Actions #2

Updated by Koen Deforche about 8 years ago

  • Description updated (diff)
Actions #3

Updated by Koen Deforche about 8 years ago

  • Status changed from New to Feedback
  • Assignee set to Koen Deforche

Hey, I think this is a character encoding issue rather than a vulnerability. Since we use a prepared statement + parameter binding there's no need for escaping strings using 'mysql_real_escape_string()'.

Utils::sha1() however returns binary data, and you cannot simply save a binary string in a string database field: you'll need to properly encode the binary data into some printable string.

E.g.:

  const std::string try_write = "Hello World!" + Utils::hexEncode(Utils::sha1( "Hello World!" ));
Actions #4

Updated by Drus Kor about 8 years ago

i'm really little known about sql injections.

i'm not shure what i can safety pass user input in db.

Hex usage means what every user input must be hex encoded?

It may be sufficient to make the function for escaping? And place it to mysql backend.

std::string escapeMyString ( const std::string &str );

not necessarily pass through each line by mysql_real_escape_string, only for strings, which programmer can't garantee safty.

Actions #5

Updated by Wim Dumon about 8 years ago

  • Status changed from Feedback to Resolved

Hey,

The std::string that you use in Dbo classes should be valid UTF-8. The mysql connector will interpret it as such, and converts it as needed. The random binary data that you pass as string is probably not valid UTF-8, therefore you see weird results. From your result, it looks like mysql truncates the string when it encounters the first invalid character. Adding mysql_real_escape_string() to the code would simply store wrong values in the database.

Wim.

Actions #6

Updated by Drus Kor about 8 years ago

thx, did't know about utf8 strings in Mysql.

move binary data to std::vector.

it seems to work.

Actions #7

Updated by Koen Deforche almost 8 years ago

  • Status changed from Resolved to Closed
  • Target version set to 3.3.6
Actions

Also available in: Atom PDF