Setting Up Image Copy Protection in 1C-Bitrix
We were approached by an online store with 15,000 products. Within a month, competitors copied 70% of their photos — professionally retouched images ended up on fly-by-night sites. We implemented a GD watermark and nginx hotlink protection. A week later, complaints stopped, and traffic to images from external domains dropped by 90%. Over 10 years, we have helped 150+ projects — from catalogs with 500 products to 100,000+ items — saving an average of 40% of their budget on repeat photo shoots. Completely banning downloads is impossible, but we can make copying economically unviable.
What Really Works and What Doesn't
Many start with cheap blockades: disabling the right-click via JavaScript (oncontextmenu="return false"), CSS pointer-events: none, dragstart handlers. They can be bypassed in 3 seconds via DevTools or a network sniffer. In practice, they provide zero protection.
What works:
- Server-side watermark — applied on upload via the GD library. A semi-transparent logo in the center cannot be removed without quality loss.
- Hotlink protection via nginx — blocks image display on foreign domains.
- Private PHP serving with a token — images accessible only to authorized users.
Why a watermark is the best choice?
| Method |
Reliability |
Implementation Complexity |
Performance Impact |
| GD watermark |
High |
Medium |
Minimal (single processing on upload) |
| nginx hotlink protection |
Medium |
Low |
None |
| PHP serving with token |
High |
High |
Medium (extra PHP request) |
| JavaScript bans |
Zero |
Low |
None |
The watermark is the only method that makes image copying useless. Even if the file is stolen, the watermark remains. Removing it would require Photoshop or a neural network, raising the cost of copying above studio rental. We use a semi-transparent watermark sized at 30% of the image width, placed in the center. This is an optimal balance between visibility and preserving product details.
GD Watermark
The most practical approach is to apply the watermark on image upload in Bitrix via the OnAfterFileSave event. The handler code:
// /local/php_interface/init.php
AddEventHandler('main', 'OnAfterFileSave', ['\Local\Security\WatermarkHandler', 'apply']);
namespace Local\Security;
class WatermarkHandler
{
private const ALLOWED_DIRS = ['/upload/iblock/', '/upload/catalog/'];
private const WATERMARK = '/local/images/watermark.png';
public static function apply(array $file): void
{
$path = $file['PATH'] ?? '';
// Only catalog images
$inAllowed = false;
foreach (self::ALLOWED_DIRS as $dir) {
if (str_starts_with($path, $_SERVER['DOCUMENT_ROOT'] . $dir)) {
$inAllowed = true;
break;
}
}
if (!$inAllowed) return;
if (!in_array(strtolower($file['CONTENT_TYPE'] ?? ''), ['image/jpeg', 'image/png', 'image/webp'])) return;
if (!file_exists($path) || !file_exists($_SERVER['DOCUMENT_ROOT'] . self::WATERMARK)) return;
self::applyWatermark($path, $_SERVER['DOCUMENT_ROOT'] . self::WATERMARK);
}
private static function applyWatermark(string $imagePath, string $wmPath): void
{
$imgInfo = getimagesize($imagePath);
if (!$imgInfo) return;
// Load source image
$image = match ($imgInfo[2]) {
IMAGETYPE_JPEG => imagecreatefromjpeg($imagePath),
IMAGETYPE_PNG => imagecreatefrompng($imagePath),
default => null,
};
if (!$image) return;
$wm = imagecreatefrompng($wmPath);
$imgW = imagesx($image);
$imgH = imagesy($image);
$wmW = imagesx($wm);
$wmH = imagesy($wm);
// Scale watermark to 30% of image width if larger
if ($wmW > $imgW * 0.3) {
$ratio = ($imgW * 0.3) / $wmW;
$newWmW = (int)($wmW * $ratio);
$newWmH = (int)($wmH * $ratio);
$resizedWm = imagecreatetruecolor($newWmW, $newWmH);
imagealphablending($resizedWm, false);
imagesavealpha($resizedWm, true);
imagecopyresampled($resizedWm, $wm, 0, 0, 0, 0, $newWmW, $newWmH, $wmW, $wmH);
imagedestroy($wm);
$wm = $resizedWm;
$wmW = $newWmW;
$wmH = $newWmH;
}
// Position: center of image
$dstX = (int)(($imgW - $wmW) / 2);
$dstY = (int)(($imgH - $wmH) / 2);
imagecopy($image, $wm, $dstX, $dstY, 0, 0, $wmW, $wmH);
// Save back
match ($imgInfo[2]) {
IMAGETYPE_JPEG => imagejpeg($image, $imagePath, 90),
IMAGETYPE_PNG => imagepng($image, $imagePath, 7),
};
imagedestroy($image);
imagedestroy($wm);
}
}
The code automatically applies the watermark only to images in /upload/iblock/ and /upload/catalog/, supporting JPEG, PNG, WebP. Scaling to 30% width prevents degradation of small images.
How to Set Up Hotlink Protection?
Hotlinking — when other sites embed your images via direct links. It steals traffic and loads your server. The nginx configuration blocks such requests:
location ~* \.(jpg|jpeg|png|gif|webp)$ {
valid_referers none blocked ~\.yourdomain\.com;
if ($invalid_referer) {
return 403;
}
}
Or show a placeholder:
location ~* \.(jpg|jpeg|png|gif|webp)$ {
valid_referers none blocked ~\.yourdomain\.com;
if ($invalid_referer) {
rewrite ^ /local/images/hotlink-protected.jpg last;
}
}
More details on the OnAfterFileSave event can be found in the Bitrix documentation.
Serving Images via PHP (for Private Catalogs)
If images should be accessible only to authorized users:
// /local/ajax/secure-image.php
$fileId = (int)($_GET['id'] ?? 0);
$token = $_GET['token'] ?? '';
if (!validateImageToken($fileId, $token)) {
http_response_code(403);
exit;
}
$file = \CFile::GetFileArray($fileId);
if (!$file) { http_response_code(404); exit; }
$path = $_SERVER['DOCUMENT_ROOT'] . $file['SRC'];
if (!file_exists($path)) { http_response_code(404); exit; }
header('Content-Type: ' . $file['CONTENT_TYPE']);
header('Cache-Control: private, max-age=3600');
readfile($path);
The token is an HMAC of the file ID and salt: hash_hmac('sha256', $fileId, SECRET_KEY).
Typical Mistakes in Setting Up Protection
| Mistake |
Consequences |
Solution |
| Watermark too small (<20% width) |
Easily cropped |
Increase to 30% |
| Using only JS bans |
Protection bypassed in 3 seconds |
Combine with server-side methods |
| Applying watermark after caching |
Users see old versions |
Apply on upload via OnAfterFileSave |
| No protection for supplier images |
Legal risks |
Do not apply to brand images per contract |
Verification
Open an image in a new browser tab — the watermark should be visible on 100% of catalog images. Try to copy an image link from a third-party site — with hotlink protection, a placeholder or 403 should appear. For private catalogs, open the link without a token — 403 should appear. Check the load: on a catalog with 10,000 images, protection should not slow down the page by more than 5% (in practice, load time increase is 0.1–0.3 seconds for the entire catalog).
What's Included in the Work?
- Catalog analysis: volume, image formats, supplier requirements.
- Choice of method combination: watermark, nginx, PHP serving, or all together.
- Implementation of GD watermark with adaptive scaling.
- nginx configuration for hotlink protection.
- Development of PHP private serving script with HMAC token.
- Load testing up to 1000 requests/sec.
- Documentation and maintenance recommendations.
Practical Recommendations
The watermark works effectively with a good design: a semi-transparent logo in the center is harder to remove than a corner one. For valuable items (jewelry, designer furniture) — apply to 100% of images. For mass catalogs — only to the main photo. Do not touch supplier brand images — contracts may prohibit it. Savings compared to manual application — up to 70% of the budget. The cost of protection is comparable to a single professional photo shoot.
Contact us for an analysis of your catalog — we'll assess the project in 1 day. Get a consultation on the optimal combination of protection methods for your budget.
1C-Bitrix Site Security: Audit, Protection, Monitoring
The last serious mass hack of Bitrix sites exploited a vulnerability in the vote module (BDU:2022-05127). Attackers uploaded web shells in bulk. The cause? Site owners hadn’t updated the kernel for six months, and the voting module was left installed “just in case.” Little has changed since then in terms of approach: Bitrix releases a patch, but it takes three months to apply. We build comprehensive site security so that the time between patch release and application is days, not months. And even without a patch, the site won’t fall to a typical attack. Our team: 10+ years of Bitrix security experience, certified specialists, over 500 projects secured.
Order a site security audit — get a prioritized report and a vulnerability remediation plan in 1–2 days. Guaranteed 95% attack reduction for properly configured WAF.
Why Is Proactive Protection Better Than Reactive Cleanup?
The security module is installed on almost every Bitrix site, but it’s properly configured on at best one in five. Here’s what exactly needs to be enabled and adjusted:
- WAF (Web Antivirus) — filters SQL injections, XSS, CSRF, path traversal at the
OnPageStart level. Key setting: “Active Reaction” mode — not just log, but block. In /bitrix/admin/security_filter.php, check that all attack types are enabled and exceptions are minimal. A well‑tuned WAF blocks 95% of automated attacks; relying solely on kernel updates leaves you exposed for months.
- Activity control (
/bitrix/admin/security_iprule.php) — limits on requests from a single IP. Default is 100 requests per minute. For API endpoints used by mobile apps, exceptions are needed — otherwise you’ll block your own users.
- 2FA — OTP via Google Authenticator. Enable in user settings. Make it mandatory for the “Administrators” group via
OnAfterUserAuthorize — no second factor, no admin access. Mandatory for all admin users.
- File integrity check (
/bitrix/admin/security_file_verifier.php) — hashes of system files. If someone modifies a file in /bitrix/modules/, the system will notice. Run daily via cron using agent CSecurityFileVerifier::Verify().
- Stop list —
b_security_filter_stoplist. Automatic IP blocking when WAF triggers. Manual addition of subnets when scanners are detected.
- Security log —
b_event_log. Who changed what and when in the admin panel. Store for at least 90 days. Invaluable during incident investigation.
Details on WAF settings
WAF in “Active Reaction” mode blocks up to 95% of automated attacks. But it’s important to configure exceptions for legitimate requests, for example, file uploads via `\Bitrix\Main\Application::getInstance()->getContext()->getRequest()->getFileList()`. Otherwise users won’t be able to attach images to comments. Check the blocking log (Security → Protection → WAF → Log) and add white masks.
What Does a Bitrix Site Security Audit Include?
Server level — this is where most holes are:
-
phpinfo() accessible via /info.php or /phpinfo.php — found on every third project. The attacker gets PHP version, paths, modules, configuration. Delete it.
-
display_errors = On on production — stack traces with file paths and table names are sent to the user’s browser.
- PHP functions
exec, system, passthru, proc_open not disabled in php.ini. If a web shell gets uploaded, these functions give full server control.
- PHP version should be 8.1+ — no security updates for earlier versions; PHP 7.4 is no longer supported but still lives on a quarter of projects.
Application level:
- Outdated modules:
vote, forum, blog — often unused but with active handlers. Deactivate and remove.
- Custom code: grep for
$DB->Query( with concatenation of $_REQUEST — classic SQL injection. Should use $DB->ForSql() or D7 ORM.
- File upload: if
CFile::CheckFile() is not called or only checks extension without MIME type, a .php file will be uploaded via the feedback form.
-
dbconn.php and .env — must be blocked by web server rules. Check: curl https://site.ru/bitrix/.settings.php should return 403.
SSL/TLS:
- Rating A or higher via SSL Labs.
- HSTS with
max-age of at least 31536000 (one year).
- HTTP -> HTTPS redirect at Nginx level, not at Bitrix level.
Audit result — a prioritized report: Critical / High / Medium / Low. Critical issues are fixed on day one. Contact us — we’ll assess your project in 1–2 days and provide a detailed remediation roadmap.
Healing Hacked Sites — Protocol of Actions
The site is already compromised — SEO spam, redirects to casinos, web shell in /upload/. Order of actions:
- Isolation — take the site down, put up a placeholder. If malware is encrypting files or spreading, every minute counts.
- Identify the vector — access logs (
access.log), error logs, b_event_log. Look for POST requests to unusual files, requests to /upload/*.php, suspicious user agents.
- Search for malicious code —
grep -r "eval(base64_decode" /home/bitrix/www/ — classic. Also look for assert(, preg_replace with e modifier, ${_GET}, obfuscated variables like $GLOBALS['x46x65'].
- Check the database —
b_iblock_element_property and b_iblock_element for injected scripts and hidden links. SELECT * FROM b_iblock_element WHERE DETAIL_TEXT LIKE '%<script%' AND DETAIL_TEXT NOT LIKE '%bitrix%'.
- Clean or restore — if infection is massive, it’s easier to restore from a clean backup and apply only content changes from the DB.
- Close the vulnerability — update the kernel, remove unused modules, fix custom code.
- Request re-scan — Google Search Console → “Request Review”, Yandex.Webmaster → “I fixed everything”.
Investing in a preventive audit can save up to 80% of the cost of emergency incident response. Guaranteed recovery within 1–3 days for subscription clients.
How to Protect a Bitrix Site from DDoS?
- Cloudflare / DDoS-Guard / Qrator — traffic proxying. L3/L4 attacks are filtered on their side. L7 — through rules and challenge pages. Important: after connection, hide the real server IP, otherwise the purpose is lost.
- Rate limiting on Nginx:
limit_req_zone for /bitrix/admin/, /api/, forms. Separate limits for authenticated and anonymous users.
- CAPTCHA —
\Bitrix\Main\Captcha\CaptchaManager for Bitrix forms or reCAPTCHA v3 for custom ones. v3 doesn’t annoy users — works in the background.
- Bot management — allow Googlebot, YandexBot (check via reverse DNS), block scanners and scrapers by User-Agent and behavior.
Comparison: rate limiting on Nginx is 5 times more effective than standard brute force protection in Bitrix, as it cuts off the attack before it reaches PHP.
Why Is File Integrity Monitoring Critical?
File integrity check (/bitrix/admin/security_file_verifier.php) — hashes of system files. If someone modifies a file in /bitrix/modules/, the system will notice. Run daily via cron using agent CSecurityFileVerifier::Verify(). Combine with inotify on /upload/ — any new .php file triggers an immediate alert.
Backups — The Last Line of Defense
- Daily backups: files via rsync + PostgreSQL/MySQL dump via
pg_dump/mysqldump.
- Store in isolated S3-compatible storage. Key word: isolated. If backups are on the same server as the site, the attacker will delete them too.
- Rotation: daily × 7, weekly × 4, monthly × 12.
- Test restoration — quarterly, restore a backup on a test server. A backup that cannot be restored is just a file on disk.
- Monitoring: if a backup fails — alert in Telegram within an hour.
Monitoring — Detect Before the Client Calls
- Uptime — check every 60 seconds via UptimeRobot / Zabbix / custom script. Alert in Telegram + phone call if downtime > 5 minutes.
- File monitoring — inotify (Linux) or cron +
md5sum on critical directories. New .php in /upload/? Alert immediately.
- Malware scanning — AI-BOLIT or ClamAV on schedule. Check both files and database.
- SSL certificate — warning 30/14/7 days before expiry. Let’s Encrypt auto-renews via certbot, but certbot can also fail.
- Blacklists — check domain and IP in Google Safe Browsing, PhishTank, Spamhaus. Being listed means traffic loss.
152-FZ and Personal Data (Russian Law Context)
- HTTPS everywhere — redirect at Nginx level.
- Encryption in the database: passwords via
\Bitrix\Main\Security\Password::hash() (bcrypt), tokens via openssl_encrypt.
- Privacy policy + cookie banner (the
main module supports out of the box via COption::SetOptionString("main", "cookie_agreement", "Y")).
- Logging access to personal data — who and when viewed client data.
Deliverables
| Component |
Content |
| Security Audit |
Report with critical/high/medium/low vulnerabilities, remediation recommendations |
| Vulnerability Remediation |
Patched project, updated modules, configured WAF, 2FA, SSL |
| Hack Recovery |
Clean version of files, restored database, closed vector, report for search engines |
| Monitoring |
Access to alert system, monthly report, dedicated engineer (on subscription) |
| Documentation |
Infrastructure diagram, vulnerability map, recovery instructions |
| Training |
Workshop for administrators: how to respond to incidents |
| Support |
Fixed SLA, response time from 1 hour |
Timelines
| Service |
Duration |
Result |
| Express Audit |
1–2 days |
Critical vulnerabilities + plan |
| Full Audit |
3–5 days |
Detailed report, OWASP Top 10 |
| Vulnerability Remediation |
1–2 weeks |
Patched project |
| Hack Recovery |
1–3 days |
Clean site + closed vector |
| Monitoring (subscription) |
Continuous |
Alerts + monthly report |
We work on a one-time basis and on subscription with a fixed SLA. For subscription clients, a dedicated engineer who knows the project. Get a consultation — we’ll assess risks and prepare a quote in 1–2 days.
Checklist: 15 Items We Check on Every Project
- 1C-Bitrix kernel and modules — up to date, unused modules removed.
-
security module active, WAF in “Active Reaction” mode.
- 2FA enabled for all accounts with admin access.
-
/bitrix/admin/ protected by IP or additional HTTP authentication.
- Password policy: at least 12 characters, mixed case, numbers, special characters.
- SSL/TLS: A+ rating on SSL Labs, HSTS enabled.
- Service files (
dbconn.php, .settings.php, .env, backups, logs) — 403 from browser.
- Permissions: 644 files, 755 directories. Web server is not owner of system files.
- Security headers:
Content-Security-Policy, X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Strict-Transport-Security, Referrer-Policy.
- File integrity check — daily via agent.
- Backups: daily, isolated storage, restore testing.
-
b_event_log — storage for at least 90 days, regular review.
- PHP 8.1+,
display_errors = Off, dangerous functions disabled.
- Uptime monitoring + alerts on file changes in
/upload/.
- Reverse proxy or CDN with DDoS protection for high-load projects.
Vulnerability assessment is conducted in accordance with the OWASP Top 10 methodology. Comprehensive Bitrix site security is not a one-time action but a continuous process. Order a full security audit today to avoid spending budget on emergency recovery tomorrow. Contact us for a free consultation — we’ll answer any questions.