Statement: At the beginning I would like to state, that I'm well aware (and want to inform others) that this is not the proper way of doing things. If soultion is found, use it as last resort.
My problem is Weak Algorithm. And can't find a way to skip checks.
Company which exposes me endpoint states it is secure and they're not going to upgrade SSL Certificate. I know it's insecure, but can't do anything and must obey their decision.
Error i get file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14082174:SSL routines:ssl3_check_cert_and_algorithm:dh key too small
and file_get_contents(): Failed to enable crypto in...
My code is:
$context = stream_context_create([
'http' => [
'timeout' => 5,
],
'ssl' => [
// set some SSL/TLS specific options
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]);
var_dump(file_get_contents($wsdl, false, $context));
In browser i ge SSL_ERROR_WEAK_SERVER_EPHEMERAL_DH_KEY and information about weak Diffie Hellman key.
I'm looking for a way to disable this check.
Most preferably via streamContext which I can use in SoapClient
You need disable Diffie Hellman validation:
$context = stream_context_create(array(
'ssl' => array(
'ciphers' => 'DEFAULT:!DH',
...
If need disable the validation of the certificate you need:
$context = stream_context_create(array(
'ssl' => array(
'ciphers' => 'DEFAULT:!DH',
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
)
);
Related
I hope this question won't be marked as duplicate as I read many related questions and answers on the site: although I tried most of the suggestions out there I still couldn't resolve my problem.
My codebase : (I left comments on purpose to give an idea of what I have been trying so far, based on my browsing)
try {
$opts = array(
//~mrossw 'http' => array(
//~mrossw 'user_agent' => 'PHPSoapClient'
//~mrossw ),
//~mrossw 'socket' => array('bindto' => '158.69.189.149')
'socket' => array('bindto' => '127.0.0.1')
//~mrossw ,
//~mrossw 'ssl' => [
//~mrossw 'verify_peer' => true,
//~mrossw 'verify_peer_name' => true,
//~mrossw 'allow_self_signed' => true
//~mrossw ]
);
$context = stream_context_create($opts);
$client = new SoapClient("https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl",
//~mrossw $client = new SoapClient($doc_root.'OpCotizadorVehiculoExtReqABCS.xml',
array(
'location' => "https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl",
'uri' => "https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones",
// Stuff for development.
'trace' => 1,
'exceptions' => true,
'keep_alive' => true,
'connection_timeout' => 120,
'stream_context' => $context,
'cache_wsdl' => WSDL_CACHE_NONE,
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE,
//~mrossw 'local_cert' => $certRequest_param['sslcertfile'],
//~mrossw 'login'=>'username',
//~mrossw 'password' => 'password'
)
);
} catch (Exception $e) {
echo \"<h2>Exception Error!</h2>\";
echo $e->getMessage();
// print_r($e);
}
The WS provider has an dev environment on port xxxx and a prod env on port yyyy. Hostname and path request are the same.
SoapClient instanciation and operation call work perfect in dev env.
When i change the port to fetch against prod env I get the following error:
SOAP-ERROR: Parsing WSDL: Couldn't load from 'https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl' : failed to load external entity "https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl"
Provider says my public web server's IP is correctly set as allowed in their firewall. It looks right because when I tried to run the code from a different server with different IP and it fails with the same error in both dev and prod env.
When I run that code from a server inside a private network, it works in both
environment ! I don't know much about security, but this sounds to me like a security breach. I mention it here though, in case it can give a clue. I guess this is because this server has a private ip and the provider's firewall don't filter it.
When I go to https://ws_provider_hostname:xxxx/foo/bar/blah/Operaciones/OpFooBarBlahReqABCS?wsdl in my PC browser i get the correct wsdl's xml.
Do you have an idea of what can prevent the code to work form my public web server ?
Or maybe what else can I check ?
For example I couldn't find a way to check the ws server's http response code from outside my browser.
I could neither get a curl request form bash to return the wsdl xml, but that should be another question maybe.
Also let me know if i can provide any other relevant test or data.
My website is https://www.mystylequest.com. We provide answers to fashion related questions like "can I find this dress in Yellow?". Answering a question involves submitting a link to a website with the dress, then my website scraps the neccessary images from the submitted link. However, we keep getting this error: file_get_contents(): SSL: Success upon submitting a valid image link (eg: https://poshmark.com/listing/Blue-and-White-Striped-Palazzo-Pants-5cf5ccaf6a7fbadddcaf2f07).
Here is the code:
if (isset($_POST['SubmitAnswersWithImage'])) {
$image_url = trim($_POST['AnswerImg']);
$url = trim($_POST['AnswerUrl']);
$postId = (int)$_POST['PostId'];
// This is to bypass websites that block our ip
$aContext = array(
'http' => array(
'proxy' => 'tcp://138.68.161.60:8080',
'request_fulluri' => true,
),
);
$cxContext = stream_context_create($aContext);
$image_data = file_get_contents($image_url, false, $cxContext); // Error occurs
$web_url = GoogleStorageManager::uploadBlob('quest_answers', $image_data)->webUrl();
<!-- irrelevant code -->
Any solutions will be greatly appreciated
Thanks in anticipation.
try
// This is to bypass websites that block our ip
$aContext = array(
'http' => array(
'proxy' => 'tcp://138.68.161.60:8080',
'request_fulluri' => true,
),
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
),
);
https://www.php.net/manual/en/migration56.openssl.php
An official document describing the changes made to open ssl in PHP 5.6 From here I learned of one more parameter I should have set to false: "verify_peer_name"=>false
Note: This has very significant security implications. Disabling
verification potentially permits a MITM attacker to use an invalid
certificate to eavesdrop on the requests. While it may be useful to do
this in local development, other approaches should be used in
production.
I created the following helper function:
function mainSoap(){
return new SoapClient('https://soap.url',[
'stream_context' => stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]);
]);
}
and I'm using it like $result=mainSoap()->GetSometing($parameters);
Everything works fine, but in terms of performance, I would like to know if is better to close the soap connection or not.
UPDATE
I created another function in order to close the connection after getting the response, but I still could't find a close method for SoapClient.
function mainSoap(string $call=null, array $vars=[]){
$url="https://soap.url";
$wsdl=new SoapClient($url,[
'trace' => false,
'keep_alive' => false,
'stream_context' => stream_context_create([
'ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true
]
]),
'compression' => SOAP_COMPRESSION_ACCEPT | SOAP_COMPRESSION_GZIP | SOAP_COMPRESSION_DEFLATE
]);
$response=$wsdl->__soapCall($call,$vars);
//Looking for something like $wsdl->close();
return $response;
}
and I'm using it like $result=mainSoap('GetSometing',[$parameters]);
The SoapClient follows the normal HTTP Request life cycle,
That is to say, your SoapClient does not maintain a constant connection to the server, it will only connect out and receive data when called, similarly to how your browser does not maintain a connection to a server once a request completes, as the request is terminated, unless you set keep_alive to true.
So, in short, you can't "close" a SoapClient because there's nothing to close after you've called it, it's already closed the connection.
Relevant Links:
Wikipedia article on Http (Persistent Connections Section)
MDN Documentation on Keep-Alive header
I have installed WAMP 3.0.4 and am trying to write a PHP script that connects to an external HTTPS web service. But this returns the error:
Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
I have written a short script that demonstrates the issue:
<?php
$auth = base64_encode('username:password');
$aContext = array(
'http' => array(
'proxy' => 'tcp://proxyip:proxyport',
'request_fulluri' => true,
'header' => 'Proxy-Authorization: Basic $auth'
),
'SSL' => array(
'verify_peer' => false,
'verify_peer_name' => false,
'allow_self_signed' => true,
'cafile' => 'C:/wamp/certificates/cacert.pem'
)
);
$cxContext = stream_context_create($aContext);
$sFile = file_get_contents("https://www.google.com", False, $cxContext);
echo $sFile;
?>
It is a requirement to use a proxy server.
As can be seen, I have tried installing a root certificates bundle and also adding verify_peer to false (not that I would do that in production) but still I receive this error.
As can be clearly seen from the above, I am something of an Apache / WAMP novice. Can someone perhaps explain what I am missing?
If you want to disable the verification of the SSL connection you can use:
'verify_peer' => false
And inside your code:
<?php
$auth = base64_encode('username:password');
$aContext = array(
'http' => array(
'proxy' => 'tcp://proxyip:proxyport',
'request_fulluri' => true,
'header' => "Proxy-Authorization: Basic $auth"
),
'ssl' => array(
'verify_peer' => false,
),
);
$cxContext = stream_context_create($aContext);
$sFile = file_get_contents("https://www.google.com", False, $cxContext);
echo $sFile;
?>
However note that this means that no-one is guarantee you that the data you get is authentic (since the ssl certificate is NOT verified).
If you want to verify the certificate, you should use the root certificates as in your question, however, you said you work with WAMP so the path to your cafile should be something like:
"cafile" => "c:/wamp/certificates/cacert.pem",
More important - you said nothing regarding the proxy in your question. Is it something that you need or is it something you found somewhere and just trying to use?
If you don't need the proxy just remove if from your request.
While on MAMP on macOS, simply restarting MAMP server solved this issue for me.
I was working with older version of OpenSSL(OpenSSL 0.9.8o) and I was forced to use newer OpenSSL 1.0.1e-fips as the result I was unable to connect to WSDL:
Message: SoapClient::SoapClient(): SSL operation failed with code 1. OpenSSL Error messages: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
I need to disable SSL certification check, I tried:
$client = new SoapClient("https://IP:443/sdk/vimService?wsdl",
array(
"trace" => 1,
"location" => "https://IP:443/sdk/",
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'allow_self_signed' => true,
)
)
)
)
);
`
And it throw:
Message: SoapClient::SoapClient(): Peer certificate CN=localhost.localdom' did not match expected CN=SAME IP AS IN SoapClient()'
Then I added 'peer_name'=> 'localhost.localdom', in stream_context and then it says XML file is empty:
Fatal error: Uncaught SoapFault exception: [Client] looks like we got no XML document
PHP 5.5
Okey, I was able to found issue.
You can avoid this mess using stable PHP 5.5 version
Recently I learned that error: "looks like we got no XML document" is caused because of PHP version - PHP 5.6 in 5.5 working like a charm.
How to fix it in PHP 5.6
1) Remove SSL certificate check in PHP 5.6:
In 5.6 version SSL certification was enabled by default, so if you want to disabled it you must pass context stream:
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)
2) Deleted ?wsdl and added .wsdl instead (with ?wsdl, it didn't worke for me)
<?php
$client = new SoapClient("https://IP:443/sdk/vimService.wsdl",
array(
"trace" => 1,
"location" => "https://IP:443/sdk/",
'exceptions' => 1,
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)
)
);
$soapmsg["_this"] = array( "_" => "ServiceInstance", "type" => "ServiceInstance");
$result = $client->RetrieveServiceContent($soapmsg);
$ServiceContent = $result->returnval;
$soapmsg = NULL;
$soapmsg["_this"] = $ServiceContent->sessionManager;
$soapmsg["userName"] = "USERNAME";
$soapmsg["password"] = "PASSWORD";
$result = $client->Login($soapmsg);
$UserSession = $result->returnval;
echo "User, " . $UserSession->userName . ", successfully logged in!\n";
$soapmsg = NULL;
$soapmsg["_this"] = $ServiceContent->sessionManager;
$result = $client->Logout($soapmsg);
In my case stream_context_create didn't worked.
So I download this file here : https://curl.haxx.se/ca/cacert.pem
and placed it in my localhost as : F:\xampp\apache\cert.pem
and gave the same path for
openssl.cafile=F:\xampp\apache\cert.pem in my phpini
This made the localhost to acquire certificate and things worked great...!!
Posting this in case this may help some one going through my situation.
In my case was needed to add the crypt_method
"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => true,
'verify_peer_name' => true,
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
)
)
)
In my case "stream_context" did the magic, i've just added the code :
`"stream_context" => stream_context_create(
array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
)
)
)`