I'm trying to post new user signup to the data using getParam, I used RestClient to test if value is retrieved or not turns out to be null every time:
this is the json data I put in the body, and I do add a content type header based on application/json:
{
"email" : "test#test.com",
"username" : "test",
"password" : "123",
}
This is the code for posting user (note that var_dump($email) and die I used it just to check $email does contain a value or not, will be removed when it is fixed):
//add new user
$app->post('/user/add', function(Request $request, Response $response){
$email = $request->getParam('email');
$username = $request->getParam('username');
$password = $request->getParam('password');
$sql = "INSERT INTO users (email, username, password) VALUES (?, ?, ?)";
var_dump($email);
die ("end");
$conn = new Database();
$conn = $conn->createConnection();
$stmt = $conn->prepare($sql);
$stmt->bind_param('sss', $email, $username, $password);
$check = $stmt->execute();
$error = $stmt->error;
if ($check){
echo 'Added Successful';
}
if ($error != ''){
echo $error;
}
});
I did the same thing for posting appoinment by /calendar/add and it work prefectly, bot post method are the same but why post user is not getting the value?
getParam() is only used for query parameters like: yoururl.com?param1=value1
You have to use
$body = $request->getParsedBody();
echo $body['email'];
instead
DZDomi's answer is not quite accurate because getParam() of Request class does call getParsedBody() method internally. It should work with query strings or data from POST body.
If you get NULL when sending POST request, make sure that you setup client to use application/x-www-form-urlencoded or multipart/form-data.
I do not know about RestClient, but if you use Postman, you can define this information on Body tab on Postman UI.
Related
I'd like to know why OWASP ZAP detect potential SQL injection on my login page. I call an API to connect my users.
PHP slim API code:
$sql = "SELECT id, idGroup, idTeam,lastName, firstName, isLogged, login, phoneNumber, webrtc FROM users WHERE enable = 1 AND login = :login AND password = :password";
$db = new db();
$db = $db->connect();
$stmt = $db->prepare($sql);
$userPass = md5($password);
$stmt->bindParam(':login', $login);
$stmt->bindParam(':password', $userPass);
$stmt->execute();
$user = $stmt->fetchAll(PDO::FETCH_OBJ);
Login page:
$login = $_POST['username'];
$password = $_POST['password'];
$client = new GuzzleHttp\Client();
$response = $client->request('POST', $apiUrl . 'agent/login', [
'form_params' => [
'login' => $login,
'password' => $password,
'ipAddress' => $_SERVER['REMOTE_ADDR'],
]
]);
$data = json_decode($response->getBody(), true);
if (isset($data[0]['id']) && $data[0]['id'] > 0) {
$_SESSION['fullName'] = $data[0]['firstName'] . ' ' . $data[0]['lastName'];
$_SESSION['idGroup'] = $data[0]['idGroup'];
$_SESSION['idTeam'] = $data[0]['idTeam'];
$_SESSION['idUser'] = $data[0]['id'];
$_SESSION['login'] = $data[0]['login'];
$_SESSION['phoneNumber'] = $data[0]['phoneNumber'];
$_SESSION['webrtc'] = $data[0]['webrtc'];
//Get roles for user
$response = $client->request('GET', $apiUrl . 'web/permissions/' . $login);
$data = json_decode($response->getBody(),true);
foreach ($data as $roles) {
$_SESSION['roles'][$roles['bit']] = $roles['name'];
}
echo "<script>window.open('index.php','_self')</script>";
}
All my APIs use prepared statements and parameterized queries.
Here's the OWASP ZAP alert:
The page results were successfully manipulated using the boolean
conditions [ZAP" AND "1"="1" -- ] and [ZAP" AND "1"="2" -- ] The
parameter value being modified was NOT stripped from the HTML output
for the purposes of the comparison Data was returned for the original
parameter.
This may happen if the response page for the form submission contains the value of a form field as it was specified by a user. For instance if you are logging in your user and use the value of 'username' field to greet the user but pull it not from the DB but from the request variables. SQL injection does not take place but the scanning script assumes that you stored the value unsanitized in the DB while you just using the value provided by a user and not the value that you have stored in the DB. Hope this makes sense.
I am able to consume the php endpoint from postman. I try to do the same from angular post, I get this error - Http failure during parsing for. Even though everything looks perfect to me, the problem is surprising. Here is my snippet
php file
<?php
header('Access-Control-Allow-Origin: *');
// check for post
if ($_SERVER['REQUEST_METHOD']=='POST') {
$name = $_POST['name'];
$email = $_POST['email'];
$subject = $_POST['subject'];
$message = $_POST['message'];
// include db connect class
require_once __DIR__ . '/db_connect.php';
// connecting to db
$conn = new db_CONNECT();
$cone=$conn->con;
//escpae the strings to be inserted to DB
$escapedname = mysqli_real_escape_string($cone, $name);
$escapedemail = mysqli_real_escape_string($cone, $email);
$escapedsubject= mysqli_real_escape_string($cone, $subject);
$escapedmessage = mysqli_real_escape_string($cone, $message);
// mysql inserting a new row
$sql = "INSERT INTO contacts(name, email, subject, message) VALUES ('$escapedname', '$escapedemail', '$escapedsubject', '$escapedmessage')";
// $result= $cone -> query($sql);
// $affected = $cone -> affected_rows;
if (mysqli_query($cone,$sql)) {
echo "Information saved successfully.";
} else {
echo "Not successful";
}
} else {
echo "Some field missing.";
}
?>
here is the angular snippet
saveContactDetails = function () {
this.proceed = true;
this.success = false;
const myheader = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
data.append('name', this.contactDeJson.name);
data.append('email', this.contactDeJson.email);
data.append('subject', this.contactDeJson.subject);
data.append('message', this.contactDeJson.message);
this.http
.post('http://localhost:80/'+'api/create_contact.php', data.toString(), {headers: myheader})
Please why am I getting this error
{"headers":{"normalizedNames":{},"lazyUpdate":null},"status":200,"statusText":"OK","url":"http://localhost/api/create_contact.php","ok":false,"name":"HttpErrorResponse","message":"Http failure during parsing for http://localhost/api/create_contact.php",
I believe the issue is that your angular script is expecting a json response (the default responseType), but not receiving the correct headers or data. In stead of just echoing out your result in php, I would make a function that can handle sending the response. Something like this:
function sendJsonResponse(data, status = 200) {
header('Content-Type: application/json', true, status);
echo json_encode($data);
exit();
}
In stead of of doing this:
echo "Not successful";
You can now do this:
sendJsonResponse("Not successful", 500);
This should give you more valuable information in the frontend. And the response should now be formatted correctly, and no longer produce the parse error in angular that you are getting now.
I believe you are trying to send some query parameters using data variable. You could actually send a JS object as the parameters. Try the following
private saveContactDetails() {
this.proceed = true;
this.success = false;
const myheader = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
const data = {
'name': this.contactDeJson.name,
'email': this.contactDeJson.email,
'subject': this.contactDeJson.subject,
'message': this.contactDeJson.message
}
this.http.post('http://localhost:80/'+'api/create_contact.php', { params: data }, { headers: myheader })
}
I have been building a private web based app for my shopify store that caters more towards our business needs. While i am able to do a dump of "all-orders", or "all-products", etc to Mysql, i haven't been able to figure out executing the shopify order creation webhook to insert a new order when created in Shopify to a Mysql database.
Instead i would need to run my script every "x" times to see if there is a new order (This could if i'm not mistaken lead to exceeding my API limit if i am running other API calls concurrently).
I understand the process of events however i am struggling to execute!
1. New order created in Shopify by Customer &or Admin.
2. Triggers webhook and sends Json to desired url i.e(https://mydomain//new-order.php). -> [Struggling]
3. When this happens the Json is decoded. -> [Struggling]
4. Assigned to a variable. -> [This i can do]
5. Inserted into a Mysql database. -> [This i can do]
=> Question:
How do you once you have created the webhook (in Shopify) get it to trigger your code to run thereafter and execute?
below is the code that i have put together, but when i sent a test hook the database isn't being updated.
All in the [new-orders.php] file (Broken up to show my train of thought):
[1] Private app credentials for connecting to Shopify store.
<?php
$api_url = https://apikey:password#my-store.shopify.com';
$shopify = $api_url . '/admin/webhooks.json';
[2] Create an array for the webhook argumnets when the webhook is triggered & assign to variable $webhooks.
$arguments = array(
'topic' => 'order/creation',
'address' => 'https://mydomain//new-order.php'
);
$webhooks = $api_url . '/admin/webhooks.json', $arguments;
[3] Decode the webhook data.
$webhook_content = '';
$webhook = fopen('php://input' , 'rb');
while(!feof($webhook)){ //loop through the input stream while the end of file is not reached
$webhook_content .= fread($webhook, 4096); //append the content on the current iteration
}
fclose($webhook); //close the resource
$orders = json_decode($webhook_content, true); //convert the json to array
[4] Add the new order to the Mysql database table.
// not sure if a foreach loop is necessary in this case?
foreach($orders as $order){
$servername = "mysql.servername.com";
$database = "database_name";
$username = "user_name";
$password = "password";
$sql = "mysql:host=$servername;dbname=$database;";
// Create a new connection to the MySQL database using PDO, $my_Db_Connection is an object
try {
$db = new PDO($sql, $username, $password);
//echo "<p> DB Connect = Success.</p>";
} catch (PDOException $error) {
echo 'Connection error: ' . $error->getMessage();
}
$order_id = $order['id'];
$order_number = $order['name'];
$f_name = $order['billing_address']['name'];
$payment_gateway = $order['gateway'];
$financial_status = $order['financial_status'];
$order_value = $order['total_price'];
$order_status = $order['#'];
$shipping_province = $order['shipping_address']['province'];
$created_at = $order['created_at'];
$updated_at = $order['updated_at'];
$shipping_method = $order['shipping_lines'][0]['title'];
$stmt = $db->query("INSERT INTO orders(order_id, order_number, cust_fname, payment_gateway, financial_status, order_value, order_status, ship_to, created_at, updated_at, shipping_method)
VALUES ('$created_at', '$order_id', '$order_number', '$f_name', '$payment_gateway', '$financial_status', '$order_value', '$order_status', '$shipping_province', '$created_at', '$updated_at', '$shipping_method')");
}
?>
Any help would be greatly appreciated and i hope i have given enough context to the issue i am currently facing. If any other information is required i will try my best to explain why i have done something the way i have.
Regards,
Update, managed to figure this out and for those of you potentially struggling with the following this is how i solved.
There are 2 aspect here!
1. Setting up the webhook [Shopify -> Notifications -> webhooks].
2. The php file that processes the webhook.
1. -> Create Webhook in shopify and point to where you php url [example.com/Process-webhook.php]
2. -> Process-webhook.php
php code
// Load variables
$webhook_content = NULL;
// Get webhook content from the POST
$webhook = fopen('php://input' , 'rb');
while (!feof($webhook)) {
$webhook_content .= fread($webhook, 4096);
}
fclose($webhook);
// Decode Shopify POST
$webhook_content = json_decode($webhook_content, TRUE);
$servername = "server_name";
$database = "database";
$username = "user_name";
$password = "password";
$sql = "mysql:host=$servername;dbname=$database;";
// Create a new connection to the MySQL database using PDO, $my_Db_Connection is an object
try {
$db = new PDO($sql, $username, $password);
//echo "<p> DB Connect = Success.</p>";
} catch (PDOException $error) {
echo 'Connection error: ' . $error->getMessage();
}
//Assign to variable
$order_id = $webhook_content['id'];
$order_number = $webhook_content['name'];
$f_name = $webhook_content['billing_address']['name'];
$payment_gateway = $webhook_content['gateway'];
$financial_status = $webhook_content['financial_status'];
$pick_status = $webhook_content['NULL'];
$pack_status = $webhook_content['NULL'];
$fulfill_status = $webhook_content['NULL'];
$order_value = $webhook_content['total_price'];
$order_status = $webhook_content['NULL'];
$shipping_province = $webhook_content['shipping_address']['province'];
// I wanted to insert the variant_id's and quantity as a string in one column. With this i can unserialise and use when needed
$items = [];
foreach($webhook_content["line_items"] as $item) {
$items[$item["variant_id"]]['quantity'] = $item["quantity"];
}
$items = serialize($items);
$created_at = $webhook_content['created_at'];
$updated_at = $webhook_content['updated_at'];
$shipping_method = $webhook_content['shipping_lines'][0]['title'];
$stmt = $db->query("INSERT INTO orders(order_id,
order_number,
cust_fname,
payment_gateway,
financial_status,
order_value,
order_status,
ship_to,
items,
created_at,
updated_at,
shipping_method)
VALUES ('$order_id',
'$order_number',
'$f_name',
'$payment_gateway',
'$financial_status',
'$order_value',
'$order_status',
'$shipping_province',
'$items',
'$created_at',
'$updated_at',
'$shipping_method')");
?>
This code gets values from a database and forms a sms template and then passes the moble number and message to webservice to send the sms. It's part of a function wall().....
$name = $resultarr['name'];
$amount = $resultarr['amount'];
$transaction_id = $resultarr['trans_id'];
$date = $resultarr['time_paid'];
//message template
$message = "Dear $name we have received $amount from you. MPESA transaction Id $transaction_id on $date.";
$mobilenumber = $resultarr['msisdn']; // get mobile number from array
$message_sent = $message;
$serviceArguments = array(
"mobilenumber" => $mobilenumber,
"message" => $message_sent
);
$client = new SoapClient("http://59.38.606.10:8080/smsengine/smsws?WSDL");
$result = $client->process($serviceArguments);
grabdetails($message_sent, $mobilenumber);
return $result;
}
//I call the function wall() to send sms
wall();
$perm = wall();
$status = $sperm->return; //outputing the status
// Here I want to capture the $status variable and put it in a db below
echo "$status";
function grabdetails($messagee, $mobno)
{
$message_sent = $messagee;
$mobilenumber = $mobno;
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "smsdb";
// Create connection
// Check connection
$sql = "INSERT INTO smsdb (sms_text, receiver_number, time_sent, status)
VALUES
('$message_sent', '$mobilenumber', NOW(), $status )";
Question is how do I grab $status ind insert it into the db since its not in the function? Kindly. help, anyone?
The code above is not complete, but I assume that the function on top where you do $client = new SoapClient("http://59.38.606.10:8080/smsengine/smsws?WSDL"); is actually the wall function. If so, then what that function returns, i.e. $result actually has the status you need. So with this code snippet (assuming $sperm is a typo and should actually be $perm, the response from the wall function), you get the response from wall(), which is an object and has the status you need.
$perm = wall();
$status = $sperm->return; //outputing the status
// Here I want to capture the $status variable and put it in a db below
echo "$status";
If that's right, then before calling grabdetails in the wall function, you actually have the status and you can send it to the function like this:
grabdetails($message_sent, $mobilenumber, $result->return);
And then change the definition of the grabdetails to receive the status as well and use it in the DB insert.
So I've been up all night trying to figure this out (literally). But Im stumped. What I want to do is, simply, to save access tokens for future use and to allow users to not have to "Allow" the app each time. When I use the access tokens in "done.php" that I stored and retrieved, the "GET" action works but the "POST" doesnt.
addblogs.php (This script, ran right after registration, snags the access tokens and stores them... right now it isn't salted, but it will be)
include('functions.php');
require_once('tumblroauth/tumblroauth.php');
require_once('config.php');
session_start();
sec_session_start();
$tumblrblog = $_SESSION['tumblrblog'];
$connection = new TumblrOAuth(CONSUMER_KEY, CONSUMER_SECRET, $_SESSION['oauth_token'], $_SESSION['oauth_token_secret']);
$access_token = $connection->getAccessToken($_REQUEST['oauth_verifier']);
unset($_SESSION['oauth_token']);
unset($_SESSION['oauth_token_secret']);
if (200 == $connection->http_code) {
$at = implode(",",$access_token);
$insert_stmt = $mysqli->prepare("INSERT INTO tumblogs (tumblrblog, access_token) VALUES ( ?, ?)");
$insert_stmt->bind_param('ss', $tumblrblog, $at);
$insert_stmt->execute();
print_r ($access_token);
} else {
header('Location: ./clearsessions.php');
}
done.php (Retreive and Use the saved access tokens)
include('functions.php');
session_start();
sec_session_start();
require_once('tumblroauth/tumblroauth.php');
require_once('config.php');
$tumblrblog = $_SESSION['tumblrblog'];
$stmt = $mysqli->prepare('SELECT access_token FROM `tumblogs` WHERE tumblrblog=? LIMIT 1');
$stmt->bind_param("s", $tumblrblog);
$stmt->execute();
$stmt->bind_result($at);
$stmt->fetch();
$access_token = explode(",", $at);
$connection = new TumblrOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token['0'], $access_token['1']);
print_r($access_token['0']);
$hostname = "$tumblrblog.tumblr.com";
$connection = new TumblrOAuth(CONSUMER_KEY, CONSUMER_SECRET, $access_token['0'], $access_token['1']);
$userinfo = $connection->get('http://api.tumblr.com/v2/user/info');
print_r($userinfo);
$pic_path = "dir/$tumblrblog/good/icon.png";
$pic = file_get_contents($pic_path);
$connection->post('api.tumblr.com/v2/blog/$hostname/post', array('type' => 'text', 'body' => 'this is a test of Tumbloadr v2'));
Thank you all for taking a look!
Brandon
In done.php I would verify that you're also retrieving the correct access token secret by printing $access_token[1] as well. Also, I would remove one of the $connections, theres no need to do it twice. To be a bit more dynamic, you can get the $hostname using this
$hostname = parse_url($blog->url,PHP_URL_HOST);
This clearly isn't a fix, but hopefully it helps a bit.
Why not serialize accessToken before inserting to database? I think it will be the correct way to store tokens in database. You can never know if the token contains "," chars then would your explode destroy the whole access token.
When I store tokens for Dropbox I had to serialize and unserialize when using it.