我也遇到过这个错误。当文件中未配置AnalysisClassHierarchy.Untracked
Pyre 目录或配置错误时,会发生错误。typeshed
.pyre_configuration
例如,如果您已将 Pyre 安装到/home/max/.local/lib/pyre_check/
中,则typeshed
目录为/home/max/.local/lib/pyre_check/typeshed
.
为了立即重现此错误,我已将typeshed
配置文件中的目录更改为不正确的目录。因此,我收到以下错误:
Analysis__ClassHierarchy.Untracked("typing.NamedTuple")
更正路径后,Pyre 能够找到漏洞。见下文。我还将给出实际示例,说明它如何发现错误以及如何配置它,以及需要对源代码进行哪些更改。
如果您希望安装自定义存根(包含.pyi
文件的目录),请将它们添加到typeshed/third_party/2and3/
,或者,在我的情况下,它是/home/max/.local/lib/pyre_check/typeshed/third_party/2and3/
.
因此,您的.pyre_configuration
文件将如下所示:
{
"source_directories": ["/home/max/myproject"],
"taint_models_path": "/home/max/myproject/taint",
"typeshed": "/home/max/.local/lib/pyre_check/typeshed"
}
不要使用默认的 Pyre 污点目录。您已经指定了自己的污点目录,这是正确的。您已经在 中创建了它.
,但最好为它创建一个没有子目录的新目录。请创建一个新taint
目录/home/max/myproject/taint
,并将 Pyre 安装文件夹中的 taint.config 文件复制到其中。此外,将.pysa
文件从 Pyre 安装复制到此目录,但只复制您需要的文件,而不是所有文件。也把你的模型.pisa
文件放在那里。
让我给你举几个例子。
例如,使用https://github.com/fportantier/vulpy Pyre 发现以下错误:
{
"line": 20,
"column": 43,
"stop_line": 20,
"stop_column": 51,
"path": "mod_user.py",
"code": 5005,
"name": "SQL injection.",
"description":
"SQL injection. [5005]: Data from [UserControlled] source(s) may reach [SQL] sink(s)",
"inference": null,
"define": "mod_user.do_login"
},
{
"line": 20,
"column": 33,
"stop_line": 20,
"stop_column": 41,
"path": "mod_user.py",
"code": 5005,
"name": "SQL injection.",
"description":
"SQL injection. [5005]: Data from [UserControlled] source(s) may reach [SQL] sink(s)",
"inference": null,
"define": "mod_user.do_login"
},
{
"line": 52,
"column": 33,
"stop_line": 52,
"stop_column": 41,
"path": "mod_user.py",
"code": 5005,
"name": "SQL injection.",
"description":
"SQL injection. [5005]: Data from [UserControlled] source(s) may reach [SQL] sink(s)",
"inference": null,
"define": "mod_user.do_create"
},
{
"line": 52,
"column": 23,
"stop_line": 52,
"stop_column": 31,
"path": "mod_user.py",
"code": 5005,
"name": "SQL injection.",
"description":
"SQL injection. [5005]: Data from [UserControlled] source(s) may reach [SQL] sink(s)",
"inference": null,
"define": "mod_user.do_create"
},
{
"line": 80,
"column": 55,
"stop_line": 80,
"stop_column": 63,
"path": "mod_user.py",
"code": 5005,
"name": "SQL injection.",
"description":
"SQL injection. [5005]: Data from [UserControlled] source(s) may reach [SQL] sink(s)",
"inference": null,
"define": "mod_user.do_chpasswd"
},
{
"line": 39,
"column": 24,
"stop_line": 39,
"stop_column": 40,
"path": "mod_api.py",
"code": 6060,
"name": "User-controlled data flows into filesystem API (other)",
"description":
"User-controlled data flows into filesystem API (other) [6060]: Data from [UserControlled] source(s) may reach [FileSystem_Other] sink(s)",
"inference": null,
"define": "mod_api.do_key_create"
},
{
"line": 39,
"column": 24,
"stop_line": 39,
"stop_column": 40,
"path": "mod_api.py",
"code": 5011,
"name": "User data to filesystem operation (read/write)",
"description":
"User data to filesystem operation (read/write) [5011]: Data from [UserControlled] source(s) may reach [FileSystem_ReadWrite] sink(s)",
"inference": null,
"define": "mod_api.do_key_create"
}
]
而对于https://github.com/lchsk/django-insecure Pyre 发现以下错误:
{
"line": 16,
"column": 29,
"stop_line": 16,
"stop_column": 80,
"path": "security/views.py",
"code": 5005,
"name": "SQL injection.",
"description":
"SQL injection. [5005]: Data from [UserControlled] source(s) may reach [StringMayBeSQL] sink(s)",
"inference": null,
"define": "security.views.unsafe_users"
},
{
"line": 32,
"column": 14,
"stop_line": 32,
"stop_column": 22,
"path": "security/views.py",
"code": 5011,
"name": "User data to filesystem operation (read/write)",
"description":
"User data to filesystem operation (read/write) [5011]: Data from [UserControlled] source(s) may reach [FileSystem_ReadWrite] sink(s)",
"inference": null,
"define": "security.views.read_file"
},
{
"line": 41,
"column": 14,
"stop_line": 41,
"stop_column": 17,
"path": "security/views.py",
"code": 5001,
"name": "Possible shell injection",
"description":
"Possible shell injection [5001]: Data from [UserControlled] source(s) may reach [RemoteCodeExecution] sink(s)",
"inference": null,
"define": "security.views.copy_file"
},
{
"line": 72,
"column": 24,
"stop_line": 72,
"stop_column": 29,
"path": "security/views.py",
"code": 6066,
"name": "Unsafe deserialization may result in RCE",
"description":
"Unsafe deserialization may result in RCE [6066]: Data from [UserControlled] source(s) may reach [ExecDeserializationSink] sink(s)",
"inference": null,
"define": "security.views.admin_index"
}
]
在我的例子中, https://github.com/lchsk/django-insecure项目的存根目录包含以下文件:
collection_propagation.pysa
django_sources_sinks.pysa
filesystem_other_sinks.pysa
filesystem_sinks.pysa
flask_sources_sinks.pysa
format_string_sinks.pysa
general.pysa
github-django-insecure-views.pysa
http_server.pysa
logging_sinks.pysa
protocols.pysa
rce_sinks.pysa
requests_api_sinks.pysa
sanitizers.pysa
skipped_overrides.pysa
sqlite3_sinks.pysa
taint.config
wsgi_ref.pysa
xss_sinks.pysa
github-django-insecure-views.pysa 文件的内容如下。需要定义视图函数的字符串参数也是污染源:
def security.views.unsafe_users(request, user_id: TaintSource[UserControlled]): ...
def security.views.safe_users(request, user_id: TaintSource[UserControlled]): ...
def security.views.read_file(request, filename: TaintSource[UserControlled]): ...
def security.views.copy_file(request, filename: TaintSource[UserControlled]): ...
def security.views.admin_index(request): ...
def security.views.search(request): ...
def security.views.log(request): ...
我还编辑了 views.py 文件以指定请求参数的类型,如下所示:
def unsafe_users(request: HttpRequest, user_id):
你不能只创建.pyi
文件views.py
来定义请求参数的类型,因为如果 Pyre 找到一个.pyi
文件,它会跳过扫描这个文件,所以你必须确保在代码中明确指定了类型。否则,Pyre 将无法跟踪从 taint source 到 taint sink 的执行流程。