Get ThttpRequest Content

Hi guys, i'm having a serious headache. My enemy is Sql Injection. I'm forced to use TRemoteDb, server is in the cloud.

The final purpose would be:

1) on client, get Request content in TRemoteDBDatabase.OnRequestSending, crypt in some way the Sql Statement, and then use
Req.SetContent(TEncoding.UTF8.GetBytes('Request content'));
to re-fill the content to send

2) on server, use a TCustomMiddleware to decrypt content, and then process the request

My problem is how to get Request content in OnRequestSending. Only way (for what i've discovered) is to use the PByte Request.ContentBuffer, but i'm stuck trying to convert this PByte to some other format (TBytes, Array of Bytes, string, ecc..).

Questions:
.
a) i'm mad, and i need a mental treatment ? I have to overcome the guys that, on client pc, try to intercept the traffic between my application and server, and prove that it's possible to inject something to server. I'm trying to find a way to solve this thing.

b) what is the best way to get content from THttpRequest, before it's sent to server ? I'm maybe missing some crucial thing ?

Thanks, ciao

Arnaldo

1 Like
  1. You can use a code like this:



    XDataClient.HttpClient.OnSendingRequest :=
      procedure(ARequest: THttpRequest)
      var
        pBytes: TBytes;
      begin
        if ARequest.ContentLength > 0 then
        begin
          pBytes := TBytes.FromBuffer(ARequest.ContentBuffer^, ARequest.ContentLength);
          EncryptBytesSomehow(pBytes);
          ARequest.SetContent(pBytes);
        end;
      end;


2) In the server-side middleware, you should do something like this:


    Bytes := DecryptFromStream(AContext.Request.ContentStream);
    AContext.Request.ContentStream.Free;
    AContext.Request.ContentStream := TBytesStream.Create(Bytes);


Or a similar approach.

a) Well, it's always laudable to try to increase security. But if your hacker has access to the computer where your application is running, he can simply reverse engineer your application and get the SQL statements from there, or even your encryption secret or authentication credentials to access the server. It really depends on the specifics of your scenario. Usually HTTPS (SSL) should protect from man-in-the-middle attacks so that your SQL statement is not inspected.

1 Like
Thank you Wagner, i will try this tomorrow morning.

At this moment, my problem is not to "hide" the request, but to avoid that a sql injection can be made by a team of penetration testers (they have my application, they intercept the request before is sent via HTTPS, and  they try to simulate an Sql Injection using a little modified request).

This morning i have applied this theory:

a) on client side (on requestsending) i have made this pseudocode (forgive me please, to simplify things i have moved FContentBytes from private to public)

code := THashSHA2.GetHMAC(TNetEncoding.Base64.EncodeBytesToString(Req.FContentBytes), "mypassword");
Req.Headers.SetValue('some-header-tag', code);

b) on server side, in a middleware, i make the same calculation of THashSHA2.GetHMAC, and then i compare

code == Req.Headers.GetValue('some-header-tag')

If it's not the same, i respond with a 401. In this way the request (sql) is visible for guys, but they can't send a modified request, if they don't find the way to modify accordingly the header tag.

It works. Tomorrow i will add your code, and then i will sophisticate the calculation of the header tag, and try a way to hide the secret keys, ecc.. I know that a real hacker could break the application and find secret things, but this is another story.

Thanks Wagner, i will come back with the news !

Ciao

Arnaldo


1 Like
Wagner, i think i'll look bad, i know....

Where did you find that "TBytes.FromBuffer" method ? why i don't have it, and i don't find nothing similar everywhere i look ?

Thanks, ciao

Arnaldo

1 Like

Sorry, here is the actual code:




  TBytesHelper = record helper for TBytes
  public
    class function FromBuffer(const ABuffer; const ACount: Integer): TBytes; static;
  end;


class function TBytesHelper.FromBuffer(const ABuffer; const ACount: Integer): TBytes;
begin
  Result.Length := ACount;
  System.Move(ABuffer, Result[0], ACount);
end;

1 Like