Connecting to remote mysql database with API - c#

I am designing a desktop application in C#, which needs to be connected to my online mysql database. I tried to give access in control panel a "%" which means from any IP, but it is not working. May be the hosting provider (bigrock) not allowing that.
Alternatively, I am trying to write some code in online on PHP which will get the "sql" as parameter and returns the output as JSON format using json_encode.
Is there any alternate methods which is better approach.

What error do you get when you try to connect? Timeout = firewalled; Permission denied = permissions not right etc.
One solution is to create a proxy with pre-coded queries (let's call then "stored procedures") - you can then say "Run query 5, parameters A, B and C". As this would be server-server (not public) you just need to add some basic authentication system (e.g. shared rotating key, checksum using parameters etc), but also ensure the queries are not dangerous if any parameters are thrown at it.
Disclaimer: It's a solution, but I'm not actually recommending that I'd do it unless you're very sure it's safe!

Do you have Cpanel ? If yes, then try adding your host in remote MySQL.
Here the link http://www.liquidweb.com/kb/enable-remote-mysql-connections-in-cpanel/ if you are unsure on how to do that.

I'd advise that you do not create a wildcard user that can connect to the database from anywhere using embedded MySQL credentials in your application. This is a bad idea.
It would be extremely easy to determine the credentials used by your application and then a malicious user could directly connect to your DB server and begin issuing queries to your database.
They will be able to issue SELECT statements for any information in your tables, even info they shouldn't see. It then becomes much easier to exploit any known or unknown vulnerabilities in MySQL much easier since now they have console access and can send data directly to the server. If the account has the DELETE privilege, they can erase all the data in your table(s).
Also, having a PHP script that issues queries provided by the application/end-user is not ideal because one can still freely issue queries. While that option is better than giving blanket access to a remote user, it is still a bad idea.
The way to go would be to identify all of the information that the C# application needs to access, and how, and write a simple web service/API that will receive parameters and issue its own queries and return the results using XML, JSON, or even SOAP. Try to abstract the database access as much as possible from the outside world for the best security.
Hope that helps.

I would do the following:
Create a user with the host of your public ip (www.whatismyip.com).
If that doesn't work, create a user with your host as your public ARPA/PTR record:
>nslookup
> set q=ptr
> 8.8.8.8
Non-authoritative answer:
8.8.8.8.in-addr.arpa name = google-public-dns-a.google.com
8.in-addr.arpa nameserver = ns1.Level3.net
8.in-addr.arpa nameserver = ns2.Level3.net
The host would then be set to google-public-dns-a.google.com.
The second worked, and I am not sure why for me on a project I worked on in the past, where you would have thought the IP address to be sufficient.

I am not sure if you have root access or access to my.cfg. If you can edit it, make sure the line "skip-networking" is commented or removed and it contains line "bind-address = *". Restart mysql after editing config.

For security reasons you shouldn't access the database directly over the (public) network.
One way is to write a php script on the database server and access it via HTTP/POST.
You should authenticate the client via username and a hashed password. The data you are sending should be encrypted (eg with the users clear text password). Don't send complete queries, only what you want to do and the parameters. As example, you want the orders for the customer, you can send a post request with the following parameters
user=abc,password=9151440965cf9c5e07f81eee6241c042a7b78e9bb2dd4f928a8f6da5e369cdffdd2b70c70663ee30d02115731d35f1ece5aad9b362aaa9850efa99e3d197212a,data=EncryptedData
You can notice, that the password is an SHA512 Hash.
The data can be json or anything else:
{
"Command": "GetOrder",
"Limit": "10"
}
In your php code you do the following steps:
1. Authenticate the user, if the password is not correct, respond with error code etc
2. Decrypt the data
3. Execute a query
4. Return the result as encrypted data
If you don't want to store the clear text password in your database, you could store in your database the hashed value and use a double hashed value for authentication and single hashed value for encryption.
If you wan't to execute the queries with parameters from the request you should use prepared statements to prevent sql injection.
More information about en/decrypting in php see: http://php.net/manual/de/ref.mcrypt.php

Like some answers suggested, I think you are firewalled by bigrock.
Now if you want to use AJAX/PHP, you need three things:
- your C# class to send requests and receive the result
- your HTML/JS (or jQuery) file to receive the request and hand it over to your PHP. Then send you the result.
- your PHP file to query your DB.
The AJAX seems superfluous to me, you could just send your query passing it through POST or a GET parameter (i.e. example.com/query.php?req='SELECT * FROM clients')
The code would be as follow:
C# using this class made by Ali Ahsan Rana:
//create the constructor with post type and few data
MyWebRequest myRequest = new MyWebRequest("http://www.example.com/query.php","POST","req=");
//use System.Web.Script.Serialization and myRequest.GetResponse();
Some tutorial on System.Web.Script.Serialization.
On the PHP side:
<?php
$request=$_POST['req'];
$dsn = 'mysql:dbname=mydb;host=example.com';
$user = 'ajay';
$password = '0000';
try {
$dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage();
}
$response = $dbh->query($request);
while ($rep = $response->fetch())
{
$response_array[] = $rep;
}
$response->closeCursor();
$return = json_encode($rep);
return($return);
?>
That's a quick draft but should work AFAIK.

Related

Active Directory LDAP connection using System.DirectoryServices - The server is not operational

I'm working on an application that uses some kind of single sign on with Active Directory.
On my side, I'm trying to get some groups to see if the user is member of them.
Sometimes, I get the following error:
The server is not operational
The DirectoryEntry object is created like this:
using(DirectoryEntry ldapConnection = new DirectoryEntry(ldapDomain))
{ Path = ldapPath, AuthenticationType = AuthenticationTypes.Secure }
where ldapDomain is x.y.corp and the ldapPath is
LDAP://OU=someAppId,OU=someGroupName,OU=someClusterName,OU=someResourceName,DC=x,DC=y,DC=corp
After some analysis with the AD team we find out that the controller was removed from the x.y.corp domain but for some reason the Domain Controller is still redirecting to it but the server is down. This generates the error message shown above.
My questions are:
is there any possible retry mechanism or error handling on my side? (The exception is indeed catch now but is thrown further)
is there a way to tell the domain controller to not use the server anymore from backend code?
is there a problem with the construction of the DirectoryEntry? Is it possible to request the "DC" parameters one at a time and to redirect outside the domain...?
is there any cache on my side for domain controllers?
Thank you!
This is something your administrators need to fix. It sounds like DNS is still advertising the DC that is down. You can confirm this by typing this in the command line:
nslookup x.y.corp
The DNS lookup will show several IPs in a different order each time you do the lookup. Whichever one shows up first is the one that will be used.
If the IP address of the decommissioned DC still shows up in the list, then they need to fix that. Anything you do in code will just be a hack to get around something that shouldn't be happening in the first place.

What Is the Syntax for Including the Service Name in a Connection String?

I have a C# ASP.Net MVC web application. I am trying to successfully connect to an Oracle database.
I am getting a "ORA-12514: TNS:listener does not currently know of service requested in connect descriptor" error.
I do not have access to the server the database is on. But I do have access to Oracle SQL Developer, which I have installed on my machine.
In my C# code I am setting the connection string like this:
ConnectionString = "DataSource=XXX.XX.XXX.XXX/abcd,1521;User ID=userid;Password=password;";
abcd should be the service name. and 1521 is the port number.
I understand that my connection string might not be the cause of the error, but I want to rule it out. Also, I know the more proper way of doing things is probably to set the connection string in web.config and retrieve it as needed, but I am doing it this way just for ease of testing until I know I am able to connect to the database successfully.
What is weird to me, is that I was able to connect to the database using Oracle SQL Developer using the same IP address, port number, service name, username, and password I am using in my connection string.
Primarily, I would like help knowing if my connection string looks valid. If you have additional thoughts about what the issue could be, that would also be appreciated.
using this command in Oracle SQL Developer:
select sys_context('userenv','service_name') from dual;
I am able to determine that the service name I am using in my connection string is one that exists, although I guess this does not guarantee that the service is up.
I am not a DBA by any means. In fact, I am still new to .Net and web development in general, but I have been assigned to troubleshoot this issue. Any help is appreciated.
I don't recall seeing the following format
DataSource=XXX.XX.XXX.XXX/abcd,1521
as valid (which doesn't mean its not, I've just not seen it).
The more common ones I've seen are:
DataSource=XXX
where XXX is a reference to your tnsnames.ora file
DataSource=//nnn.nnn.nnn.nnn/service_name
DataSource=//nnn.nnn.nnn.nnn:port/service_name
So maybe try those variants and see how you go. There's also more definitive list of alternatives at https://www.c-sharpcorner.com/UploadFile/nipuntomar/connection-strings-for-oracle/
I ended up figuring this out. My connection string format I don't t think was correct. I changed it to be:
ConnectionString = "DataSource=XXX.XX.XXX.XXX/abcd;User ID=userid;Password=password;";
Basically, I just took off the port number. In my case, the default port was what I needed anyway. Not sure what I would have done had I needed to specify the port number.
As new to Oracle I struggled a few days finding solution to this
this article helped me alot
As of Oracle 21 c
This is my Connection string for C#
Password=dev;Persist Security Info=True;User ID=Dev;Data Source=localhost:1521/XEPDB1
Keep in mind Dev is Username which is also the Schema name for Oracle

Storing data on client side - How to protect against manipulation?

General/Introduction:
I work on a project where we have two parts of software. There is a client application that runs on the user's computer and a web application that manages a lot of things related to this project.
The client application reads a lot of different values via IPC from another program, that I don't have the source code of and I don't have the option to change anything in that other program I am reading from.
So, my application collects those values and stores them locally, since it is not always connected to the web application.
Since the web application builds statistics and more out of those values and since the values that are collected are quite important for the whole project, the user should not be able to change them (or at least it should be really hard - I am pretty sure you can't provide 100 % security for data on the client).
Just for the sake of full information: The client application is written in C#, while the web application is based on the Laravel Framework (PHP). But this question is more about theory than exactly how to code this.
My thoughts:
I was thinking about having asymmetric encryption. The client encrypts the data with the public key of the web application server. The data is now stored encrypted. But of course, the client has this public key. Hence, an attacker could just go ahead and encrypt his own manipulated values and store them in the file.
Another thought, that builds upon the encryption, was that I could not only encrypt the data, but the whole file and use a format that is not too obvious. But that is more like security through obscurity and should be avoided as far as I know. Plus one could just decompile the client application and instantly have the format that I am using.
My question:
Is there any way I can provide a decent level of integrity when sending that data to the server? If so, how can it be done?
There are two things you can do:
Give up, because client software authenticity is not the server's problem, and it's theoretically impossible to know for sure that the other end is running the software you intend in a way that isn't spoofable.
If you're using the client software as a data mule, use hash_hmac() and hash_equals() to authenticate the data so it's tamper-evident.
For example, you could store the MAC by prefixing it to the data:
$key = random_bytes(32); // Store me for long-term. Maybe per-client?
$data = "foo";
$mac = hash_hmac('sha256', $data, $key);
echo $data . $mac;
And then to validate it upon being returned by the client software:
if (mb_strlen($message, '8bit') < 64) {
throw new Exception("Invalid message length.");
}
$mac = mb_substr($message, 0, 64, '8bit');
$data = mb_substr($message, 64, null, '8bit');
$recalc = hash_hmac('sha256', $data, $key);
if (!hash_equals($recalc, $mac)) {
throw new Exception("Invalid MAC.");
}
// Now we know $data is legitimate.
It is important to use hash_equals() not == or === to prevent timing attacks.
Note that this renders any such data unavoidably read-only. If you want them to be able to edit data, you're stuck with option 1.

C# creating a database programmatically with SMO

I am trying to create a database, but once created, I cannot connect to it.
The server is Microsoft SQL Server 2008 and using .Net 4.5. We're creating the database with SMO, but we're usually using Dapper to connect and query the database.
This is the code I have so far, which works :
System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connectionString);
Microsoft.SqlServer.Management.Smo.Server srv = new Microsoft.SqlServer.Management.Smo.Server(new Microsoft.SqlServer.Management.Common.ServerConnection(con));
var database = new Microsoft.SqlServer.Management.Smo.Database(srv, dbName);
database.Create(false);
database.Roles["db_datareader"].AddMember(???);
database.Roles["db_datawriter"].AddMember(???);
database.Roles["db_backupoperator"].AddMember(???);
srv.Refresh();
Noce the ??? ? I have tried
System.Environment.UserDomainName + "\\" + System.Environment.UserName
and
System.Environment.UserName
but it fails (update) with the error Add member failed for DatabaseRole 'db_datareader'. with both values.
The problem is that when I create the database, I cannot coonect to it for some reason (using Dapper), from the same program. (update) I get the error message : Cannot open database \"<database_name>\" requested by the login. The login failed.\r\nLogin failed for user '<domain>\\<username>' (where <database_name> is the database name, <domain> my logon domain, and <username> my Windows logon).
Am I missing something? Am I doing th right thing? I've tried searching the web, but it seems no one creates database this way. The methods are there, it should work, no?
** Update **
If I comment the database.Roles["..."].AddMember(...) lines, and I add a break point at srv.Refresh(), resuming the program from there solves everything.
Why a break point solves everything? I can't just break the program in production... nor break the program when creating the database everytime.
It sounds like the Dapper connection issue is a problem with SQL Server doing some of the SMO operations asynchronously. In all likelihood, the new Database is not ready for other users/connections immediately, but requires some small time for SQL Server to prepare it. In "human-time" (in SSMS, or a Breakpoint) this isn't noticeable, but "program-time" it too fast, so you probably need to give it a pause.
This may also be the problem with the Role's AddMember, but there a a number of things that could be wrong here, and we do not have enough information to tell. (specifically, does AddMember work later on? and are the strings being passed correct or not?)
This is happening because you've created the user, but no login for that user. Though I don't know the exact syntax, you're going to have to create a Login. You'll want to set its LoginType to LoginType.WindowsUser. Further, you'll likely need to set the WindowsLoginAccessType to WindowsLoginAccessType.Grant and you'll need to set the Credential by building one, probably a NetworkCredential with the user name you want.
To put a visual on this, the Login is under the Security node for the Server in Management Studio whereas the User is under the Security node for the Database. Both need to exist for access to the SQL Server.

Hide sql query from packet sniffers

I've got a database login on a desktop application made in C#.
To check if the user exists, I do a WHERE clause and get the row returned. If row is returned...then user exists.
My problem is pack sniffers can see the strings being returned. They are encrypted and such but some people could use a auto mated response to fool the application into thinking it was right.
Is there a way to hide my DB stuff from packet sniffers?
Yes - you can do that by using an encrypted connection (SSL certificate based)... for details and some sample configuration/code see:
http://msdn.microsoft.com/en-us/library/ms189067.aspx
http://msdn.microsoft.com/en-us/library/ms191192.aspx
http://support.microsoft.com/kb/316898/en-us
http://blogs.msdn.com/b/sql_protocols/archive/2005/11/10/491563.aspx
https://serverfault.com/questions/351/how-to-enable-encrypted-connections-to-a-sql-server-instance
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring.aspx

Categories

Resources