# 云函数攻防

#### Serverless概述 <a href="#toc1816782803" id="toc1816782803"></a>

无服务器（Serverless）不是表示没有服务器，而是表示当您在使用Serverless时，您无需关心底层的资源，也无需登录服务器和优化服务器，只需关注最核心的代码片段，即可跳过复杂的、繁琐的基本工作。

Serverless 拥有近乎无限的扩容能力，空闲时，不运行任何资源。代码运行无状态，可以轻易实现快速迭代、极速部署。

#### 什么是云函数 <a href="#toc1746076975" id="toc1746076975"></a>

函数即服务提供了一种直接在云上运行无状态的、短暂的、由事件触发的代码的能力。

函数即服务和传统应用架构不同，函数服务提供的是事件触发式的运行方式，云函数不是始终运行的状态，而是在事件发生时由事件触发运行，并且在一次运行的过程中处理这一次事件。因此在云函数的代码中，仅需考虑针对一个事件的处理流程，而针对大量事件的高并发处理，由平台实现云函数的多实例并发来支持。

云函数（Serverless Cloud Function，SCF）是为企业和开发者们提供的无服务器执行环境，帮助您在无需购买和管理服务器的情况下运行代码。您只需使用平台支持的语言编写核心代码并设置代码运行的条件。

云函数无法长驻，调用的时候创建，执行完之后立即就销毁，所以无法直接保存状态。

云函数功能特性：

* &#x20;代码管理
* &#x20;支持多开发环境
* &#x20;自动伸缩
* &#x20;事件触发
* &#x20;监控和日志

以函数为扩展单位，虚拟化运行时环境（Runtime），是现有计算资源的最小单位，具有完全自动、一键部署、高度可扩展等

使用云函数时，您只需使用平台支持的语言（Python、Node.js、PHP、Golang、Java 及 Custom Runtime）编写代码。而云平台将完全管理底层计算资源，包括服务器 CPU、内存、网络和其他配置/资源维护、代码部署、弹性伸缩、负载均衡、安全升级、资源运行情况监控等。

Serverless 帮助用户脱离繁冗的开发配置工作，只需关注业务代码逻辑的编写，不用任何的基础设施建设、管理与运维开销。该服务模式降低了研发门槛，提升业务构建效率，获得了大量企业和开发者的支持。

<figure><img src="/files/aJ8i6IcLkD5xobZvSN49" alt=""><figcaption></figcaption></figure>

* &#x20;多种部署方式，适应各种环境
* &#x20;多样化触发，支持更多业务场景
* &#x20;自动化弹性执行，贴合调用曲线
* &#x20;按需付费，毫秒级计费模式

云函数（Serverless Cloud Function，SCF）提供代码部署、镜像部署两种部署方式，支持事件函数和 Web 函数两种函数类型。

SCF 事件函数有三个基本概念：执行方法、函数入参和函数返回。

**执行方法**

执行方法：对应项目的主函数，是程序执行的起点。

在调用云函数时，首先会寻找执行方法作为入口，执行用户的代码。用户需以文件名.执行方法名的形式进行设置。

用户设置的执行方法为 index.handler，则 SCF 平台会首先寻找代码程序包中的 index 文件，并找到该文件中的 handler 方法开始执行。

**函数入参**

函数入参，是指函数在被触发调用时所传递给函数的内容。

通常情况下，函数入参包括 event 和 context 两部分，但根据开发语言和环境的不同，入参个数可能有所不同

· event入参

event 参数类型为 dict，event 中包含了触发函数执行的基本信息，可以是平台定义的格式，也可以自定义格式。函数被触发开始执行后，可以在代码内部对 event 进行处理。

有两种方法可以触发云函数 SCF 执行：

1\. 通过调用 [云 API](https://cloud.tencent.com/document/product/583/17243) 触发函数执行。

2\. 通过绑定 [触发器](https://cloud.tencent.com/document/product/583/9705) 触发函数执行。

· context入参

context 为 SCF 平台提供的入参，将 context 入参传递给执行方法，代码可通过解析 context 入参对象，获取到运行环境及当前请求的相关信息。

{% embed url="<https://cloud.tencent.com/document/product/583/9210>" %}

**函数返回**

SCF 平台会获取到云函数执行完成后的返回值，并根据下表中不同的触发方式进行处理。

同步触发

Ø 通过 API 网关、云 API 同步 invoke 触发函数的方式为同步触发。

Ø 使用同步方式触发的函数在执行期间，SCF 平台不会返回触发结果。

Ø 在函数执行完成后，SCF 平台会将函数返回值封装为 JSON 格式并返回给调用方。

Ø 异步触发

Ø 使用异步方式触发的云函数，SCF 平台接收触发事件后，会返回触发请求 ID 。

Ø 在函数执行完成后，函数的返回值会封装为 JSON 格式并存储在日志中。

Ø 用户可在函数执行完成后，通过返回的请求 ID 查询日志获取该异步触发函数的返回值。

#### 触发器和触发源 <a href="#toc951682570" id="toc951682570"></a>

* &#x20;任何可以产生事件，触发云函数执行的均可以被称为触发器或触发源。触发器在本身产生事件后，通过将事件传递给云函数来触发函数运行。
* &#x20;触发器在触发函数时，可以根据自身特点，使用同步或异步方式触发函数。同步方式触发函数时，触发器将等待函数执行完成并获取到函数执行结果；异步方式触发函数时，触发器将仅触发函数而忽略函数执行结果。
* &#x20;腾讯云云函数在和腾讯云的某些产品或服务对接时，也有自身实现的一些特殊方式，例如推（PUSH）模式和拉（PULL）模式。
  * &#x20;推模式：触发器主动将事件推送至云函数平台并触发函数运行。
  * &#x20;拉模式：云函数平台通过拉取模块，从触发器中拉取到事件并触发云函数运行。

#### 触发事件 <a href="#toc470751134" id="toc470751134"></a>

触发器在触发函数时会将事件传递给云函数。事件在传递时以一个特定的数据结构体现，数据结构格式在传递时均为 JSON 格式，并以函数 event 入参的方式传递给云函数。

触发事件的 JSON 数据内容，在不同的语言环境下将会转换为各自语言的数据结构或对象，无需在代码中自行进行从 JSON 结构到数据结构的转换。\
例如，在 Python 环境中，JSON 数据内容会转变为一个复杂 dict 对象，即函数的入参 event 就是一个 Python 的复杂 dict 对象。而在 Golang 或 Java 中，入参是一个需要和 event 数据结构可以匹配的对象。

#### Serverless 扫描技术 <a href="#toc584553590" id="toc584553590"></a>

**云函数端口扫描**

{% embed url="<https://console.cloud.tencent.com/scf/list?rid=4&ns=default>" %}

<figure><img src="/files/F5Gloh0T0XstytpoKqgb" alt=""><figcaption></figcaption></figure>

```bash
# -*- coding: utf8 -*-
from socket import *
 
def main_handler(event, context):
IP=event["queryString"]["ip"]
port=event["queryString"]["port"]
try:
conn=socket(AF_INET,SOCK_STREAM)
res=conn.connect_ex((str(IP),int(port)))
conn.send('Hello,World!'.encode("utf8"))
results=conn.recv(25)
if res==0:
conn.close()
return port
except Exception as err:
print(err)
finally:
print("")
conn.close()
return None
```

函数管理 -> 触发管理

<figure><img src="/files/oscHM6wRcHqhIoME4uhk" alt=""><figcaption></figcaption></figure>

扫描器

```bash
#!/usr/bin/env python
# encoding: utf-8
import grequests
 
def main():
    serverless = ["https://service-xxx-xxx.sh.apigw.tencentcs.com/release/http_proxy"]
    resp, num = [], 0
    port_one = [22, 53, 80, 81, 82, 83, 111, 9096, 9291, 9080, 6379, 5900, 9090, 443]
    port_two = [8088, 8080, 4566, 6666, 10001, 2443, 3306, 3389, 7001, 9099, 135, 23]
    try:
        ip = input("\033[31;32mPlease Input IP Address:\033[0m")
        print("")
        for server in serverless:
            num += 1
            port_list = port_one if num == 1 else port_two
            for port in port_list:
                serverless_one = f"{server}?ip={ip}&port={port}"
                resp.append(grequests.get(
                    serverless_one,
                    timeout=5
                )
            )
            res_list = grequests.map(resp)
            for res in res_list:
                if res.text != "null" and res.text.find("errorCode") == -1:
                    print('[+]{}/tcp OPEN'.format(res.text))
    except Exception as err:
        print(err)
        pass
 
if __name__ == '__main__':
    main()
```

&#x20;

**云函数目录扫描**

<figure><img src="/files/lkkwn4w0VLwIvJH0gIW9" alt=""><figcaption></figcaption></figure>

选择Python3.6，3.7有问题。

```bash
# -*- coding: utf8 -*-
import requests
 
def main_handler(event, context):
    headers=event["headers"]
    url=event["queryString"]["url"]
    path = event["queryString"]["path"]
    crake_url=str(url+path)
    try:
        r = requests.get(crake_url,timeout=5,headers=headers,verify=False)
        status = r.status_code
    except Exception:
        status = None
        pass
 
    return status,crake_url
```

创建触发器为API

```bash
#!/usr/bin/env python
# encoding: utf-8
 
import random
import requests
 
def dict_read(dict_file, num):
    dict_list = []
    with open(dict_file, "r", encoding='utf-8') as ip_text:
        lines = ip_text.readlines()[:7] if num == 1 else ip_text.readlines()[7:]
        for line in lines:
            dict_list.append(line.strip("\n"))
    return dict_list
 
def main():
    from get_ua_header import UA
    number = 0
    severless = ["https://service-o1u1x736-1301587401.gz.apigw.tencentcs.com/release/dir_scan"]
    try:
        url = input("\033[31;32mplease input url:\033[0m")
        dict_file_path = input("\033[32;32mplease input crash dict path:\033[0m")
        print("")
        for server in severless:
            number += 1
            for path in dict_read(dict_file_path, number):
                headers = {
                    "User-Agent": random.choice(UA),
                }
                serverless_one = f"{server}?path={path}&url={url}"
                r = requests.get(serverless_one, headers=headers)
                print(r.text)
 
    except Exception as err:
        print(err)
 
if __name__ == '__main__':
    main()
```

&#x20;

**云函数连接WebShell**

```bash
# -*- coding: utf8 -*-
import requests
import json
def geturl(urlstr):
    jurlstr = json.dumps(urlstr)
    dict_url = json.loads(jurlstr)
    return dict_url['u']
def main_handler(event, context):
    url = geturl(event['queryString'])
    postdata = event['body']
    headers=event['headers']
    resp=requests.post(url,data=postdata,headers=headers,verify=False)
    response={
        "isBase64Encoded": False,
        "statusCode": 200,
        "headers": {'Content-Type': 'text/html;charset='+resp.apparent_encoding},
        "body": resp.text
    }
    return response
```

创建API触发器访问：

{% code overflow="wrap" %}

```bash
https://service-xxxx-xxxxx.gz.apigw.tencentcs.com/release/saulGoodman?u=http://111.111.111.111/shell.php
```

{% endcode %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lzcloudsecurity.gitbook.io/yun-an-quan-gong-fang-ru-men/di-si-zhang-gong-you-yun-gong-fang/yun-han-shu-gong-fang.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
