Skip to content

Commit e72e2dc

Browse files
jsfaurejaiminpanchal27
authored andcommitted
Add RSA validation to Criteo FastBid (prebid#3110)
* Pass Prebid version to Criteo direct bidder * Update Criteo profile IDs * Add RSA verification to Criteo FastBid * Update package-lock with jsencrypt and crypto-js * Replacing all arrow functions in Mocha function calls * Update Adapter Version to 14
1 parent 4797ea2 commit e72e2dc

File tree

4 files changed

+75
-5
lines changed

4 files changed

+75
-5
lines changed

modules/criteoBidAdapter.js

+45-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { registerBidder } from 'src/adapters/bidderFactory';
33
import { parse } from 'src/url';
44
import * as utils from 'src/utils';
55
import find from 'core-js/library/fn/array/find';
6+
import JSEncrypt from 'jsencrypt/bin/jsencrypt';
7+
import sha256 from 'crypto-js/sha256';
68

7-
const ADAPTER_VERSION = 11;
9+
const ADAPTER_VERSION = 14;
810
const BIDDER_CODE = 'criteo';
911
const CDB_ENDPOINT = '//bidder.criteo.com/cdb';
1012
const CRITEO_VENDOR_ID = 91;
@@ -17,6 +19,13 @@ const PROFILE_ID_PUBLISHERTAG = 185;
1719
// Unminified source code can be found in: https://github.com/Prebid-org/prebid-js-external-js-criteo/blob/master/dist/prod.js
1820
const PUBLISHER_TAG_URL = '//static.criteo.net/js/ld/publishertag.prebid.js';
1921

22+
export const FAST_BID_PUBKEY = `-----BEGIN PUBLIC KEY-----
23+
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDO1BjAITkFTtP0IMzmF7qsqhpu
24+
y1dGaTPHnjMU9mRZsrnfR3C0sEN5pYEzEcFRPnkJjJuhH8Rnh5+CE+LcKg0Z8ZZ7
25+
OmOSj0/qnYTAYCu0cR5LiyWG79KlIgUyMbp92ulGg24gAyGrVn4+v/4c53WlOEUp
26+
4YWvb82G0CD5NcDNpQIDAQAB
27+
-----END PUBLIC KEY-----`;
28+
2029
/** @type {BidderSpec} */
2130
export const spec = {
2231
code: BIDDER_CODE,
@@ -251,20 +260,52 @@ function createNativeAd(id, payload, callback) {
251260
</script>`;
252261
}
253262

263+
export function cryptoVerify(key, hash, code) {
264+
var jse = new JSEncrypt();
265+
jse.setPublicKey(key);
266+
return jse.verify(code, hash, sha256);
267+
}
268+
269+
function validateFastBid(fastBid) {
270+
// The value stored must contain the file's encrypted hash as first line
271+
const firstLineEnd = fastBid.indexOf('\n');
272+
const firstLine = fastBid.substr(0, firstLineEnd).trim();
273+
if (firstLine.substr(0, 9) !== '// Hash: ') {
274+
utils.logWarn('No hash found in FastBid');
275+
return false;
276+
}
277+
278+
// Remove the hash part from the locally stored value
279+
const fileEncryptedHash = firstLine.substr(9);
280+
const publisherTag = fastBid.substr(firstLineEnd + 1);
281+
282+
// Verify the hash using cryptography
283+
try {
284+
return cryptoVerify(FAST_BID_PUBKEY, fileEncryptedHash, publisherTag);
285+
} catch (e) {
286+
utils.logWarn('Failed to verify Criteo FastBid');
287+
return undefined;
288+
}
289+
}
290+
254291
/**
255292
* @return {boolean}
256293
*/
257294
function tryGetCriteoFastBid() {
258295
try {
259296
const fastBid = localStorage.getItem('criteo_fast_bid');
260297
if (fastBid !== null) {
261-
eval(fastBid); // eslint-disable-line no-eval
262-
return true;
298+
if (validateFastBid(fastBid) === false) {
299+
utils.logWarn('Invalid Criteo FastBid found');
300+
localStorage.removeItem('criteo_fast_bid');
301+
} else {
302+
utils.logInfo('Using Criteo FastBid');
303+
eval(fastBid); // eslint-disable-line no-eval
304+
}
263305
}
264306
} catch (e) {
265307
// Unable to get fast bid
266308
}
267-
return false;
268309
}
269310

270311
registerBidder(spec);

package-lock.json

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

100644100755
+2
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,9 @@
103103
"dependencies": {
104104
"babel-plugin-transform-object-assign": "^6.22.0",
105105
"core-js": "^2.4.1",
106+
"crypto-js": "^3.1.9-1",
106107
"gulp-sourcemaps": "^2.6.0",
108+
"jsencrypt": "^3.0.0-rc.1",
107109
"just-clone": "^1.0.2"
108110
}
109111
}

test/spec/modules/criteoBidAdapter_spec.js

+18-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect } from 'chai';
2-
import { spec } from 'modules/criteoBidAdapter';
2+
import { cryptoVerify, spec, FAST_BID_PUBKEY } from 'modules/criteoBidAdapter';
33
import * as utils from 'src/utils';
44

55
describe('The Criteo bidding adapter', function () {
@@ -294,4 +294,21 @@ describe('The Criteo bidding adapter', function () {
294294
expect(bids[0].height).to.equal(90);
295295
});
296296
});
297+
298+
describe('cryptoVerify', function () {
299+
const TEST_HASH = 'vBeD8Q7GU6lypFbzB07W8hLGj7NL+p7dI9ro2tCxkrmyv0F6stNuoNd75Us33iNKfEoW+cFWypelr6OJPXxki2MXWatRhJuUJZMcK4VBFnxi3Ro+3a0xEfxE4jJm4eGe98iC898M+/YFHfp+fEPEnS6pEyw124ONIFZFrcejpHU=';
300+
301+
it('should verify right signature', function () {
302+
expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test')).to.equal(true);
303+
});
304+
305+
it('should verify wrong signature', function () {
306+
expect(cryptoVerify(FAST_BID_PUBKEY, TEST_HASH, 'test wrong')).to.equal(false);
307+
});
308+
309+
it('should return undefined with incompatible browsers', function () {
310+
// Here use a null hash to make the call to crypto library fail and simulate a browser failure
311+
expect(cryptoVerify(FAST_BID_PUBKEY, null, 'test')).to.equal.undefined;
312+
});
313+
});
297314
});

0 commit comments

Comments
 (0)