curl_xxx是一套可定义发送请求的函数包装机,由于其高度自由性被大多数ctfer拿来当做编写poc或攻击脚本工具,函数包装机的运作流程如下:
curl_init #初始化
↓
curl_setopt / curl_setopt_array #配置参数与行为
↓
curl_exec #发送请求
↓
curl_getinfo / curl_errno / curl_error #接收响应信息或返回错误信息
↓
curl_close #结束协议链接并清理缓存。
从创建一个会话,到发送请求,接收信息,再到清理缓存。拥有一套完整的发收流程,且各阶段的行为与参数都可自定义:
-------------------------------------------------------------------------------------------------------------------
curl_init(); 开启一个url请求会话
建立一个新的会话,该函数会在当前的PHP进程提前分配好内存,保留给这个新会话,这个函数是必须的,没有该函数开启会话,后面的就无法进行,用法:
<?php
$ch=curl_init($url);
#或者
$ch=curl_init();
?>
$ch就可以作为一个伪客户端,进行接下来的行为与参数加工,最终发包。
-------------------------------------------------------------------------------------------------------------------
curl_setopt(); 自定义URL请求信息参数与行为。
该函数可以自定义访问某个url时所需要的参数,和python的request库是一个作用,但比较啰嗦,方法名较长:
两者对比:
|
行为 |
PHP cURL |
Python requests |
|
URL |
|
|
|
返回响应体 |
|
默认 |
|
请求头 |
|
|
|
Cookie |
|
|
|
POST 数据 |
|
/ |
|
跟随跳转 |
|
|
|
超时 |
|
|
|
SSL 校验 |
|
|
例子格式,python的request与PHP的curl_setopt()设置请求头与cookie:
Python:
res = requests.get(
url, #访问目标url
headers={'User-Agent': 'test-agent'}, #自定义请求头
cookies={'sid': '123'}, #自定义cookie
)
PHP:
<?php
curl_setopt($ch, CURLOPT_URL, $url); #访问目标url
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); #是否返回信息
curl_setopt($ch, CURLOPT_HTTPHEADER, [ #自定义请求头
'User-Agent: test-agent'
]);
curl_setopt($ch, CURLOPT_COOKIE, 'sid=123'); #自定义cookie
?>
-------------------------------------------------------------------------------------------------------------------
curl_setopt_array(); 批量设置参数
这个参数和curl_setopt();是一样的,给接下来的请求设置参数与行为,但curl_setopt();是一条一条设置的,curl_setopt();_array();可以批量设置,但内部其实还是一条一条赋值的。用法:
<?php
curl_setopt_array($ch, [
CURLOPT_URL => 'https://example.com',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_TIMEOUT => 10,
]);
?>
-------------------------------------------------------------------------------------------------------------------
curl_exec(); 发送请求
这一步就是发送请求包,具体内容就是上面自定义的参数,没有定义的参数全部走默认。
格式:
<?php
$result=curl_exec($ch);
?>
如果在上方设置了CURLOPT_RETURNTRANSFER为1或者true的话,就会返回响应包信息。储存在$result变量中。
-------------------------------------------------------------------------------------------------------------------
curl_getinfo(); 获取发送数据的过程数据。
该函数只能在curl_exec();函数发送数据包结束后才能被触发,没有curl_exec();作为前置条件就无信息。
可以获取的信息如下:
|
信息含义 |
常量 |
返回值类型 |
说明 / 实战价值 |
|
最终 HTTP 状态码 |
|
int |
最重要,判断请求是否逻辑成功 |
|
最终访问的 URL |
|
string |
判断 301/302 跳转、是否被送去登录/WAF |
|
响应 Content-Type |
|
string / null |
区分 HTML / JSON / 文件下载 |
|
实际连接的 IP |
|
string |
CDN / 负载均衡 / SSRF 分析 |
|
实际连接端口 |
|
int |
非标准端口判断 |
|
本地出口 IP |
|
string |
多网卡 / 出口验证 |
|
本地出口端口 |
|
int |
连接调试 |
|
请求总耗时 |
|
float |
时间盲注 / 性能判断 |
|
DNS 解析耗时 |
|
float |
DNS 是否异常 |
|
TCP 连接耗时 |
|
float |
网络质量分析 |
|
SSL 握手耗时 |
|
float |
TLS 行为差异 |
|
服务器响应耗时 |
|
float |
后端处理延迟 |
|
请求头字节数 |
|
int |
手动拆 header / body |
|
请求体字节数 |
|
int |
判断实际发送内容 |
|
跳转次数 |
|
int |
前提:开启 FOLLOWLOCATION |
|
跳转耗时 |
|
float |
跳转链路分析 |
|
是否验证 SSL 成功 |
|
int |
0 = 通过 |
|
文件最后修改时间 |
|
int |
文件下载场景 |
|
下载内容大小 |
|
float |
响应体大小 |
|
上传内容大小 |
|
float |
POST / PUT 体积 |
|
下载速度 |
|
float |
网络性能 |
|
上传速度 |
|
float |
网络性能 |
有两种方法获取信息,一种是直接获取最主要的信息
格式:
$info = curl_getinfo($ch);
print_r($info)
#输出:
Array
(
[url] => https://example.com
[content_type] => text/html; charset=UTF-8
[http_code] => 200
[header_size] => 512
[request_size] => 401
[filetime] => -1
[ssl_verify_result] => 0
[redirect_count] => 1
[total_time] => 0.432
[namelookup_time] => 0.021
[connect_time] => 0.055
[pretransfer_time] => 0.072
[starttransfer_time] => 0.201
[redirect_time] => 0.103
[primary_ip] => 93.184.216.34
[primary_port] => 443
[local_ip] => 192.168.1.10
[local_port] => 51234
[speed_download] => 15342
[speed_upload] => 0
[download_content_length] => 1256
[upload_content_length] => 0
[effective_url] => https://example.com/
)
还有一种是只获取一个键值的信息,格式:
$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
var_dump($http_code);
#输出:
int(200)
-------------------------------------------------------------------------------------------------------------------
curl_errno();与curl_error(); 获取内部错误码与可读错误原因
这是两个配套使用的函数,当发包流程出现错误时就会被触发,
curl_errno();返回的是 libcurl 内部错误码 如果没有错误则返回0
curl_error();返回的是程序员可理解的错误原因,两个函数配合使开发者调试代码更加直观便捷。
-------------------------------------------------------------------------------------------------------------------
curl_close(); 关闭当前会话
该函数可以关闭会话,清理内部缓存,释放所有资源,是整个会话流程的最后一环,值得注意的是,该函数必须放在整个流程的最后,在此函数后面的curl系列函数都不会再起任何作用,因为会话已经被关闭。
124

被折叠的 条评论
为什么被折叠?



