You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
voidRenderFrameImpl::FrameDetached() {
// We need to clean up subframes by removing them from the map and deleting // the RenderFrameImpl. In contrast, the main frame is owned by its // containing RenderViewHost (so that they have the same lifetime), so only // removal from the map is needed and no deletion. auto it = g_frame_map.Get().find(frame_);
CHECK(it != g_frame_map.Get().end());
CHECK_EQ(it->second, this);
g_frame_map.Get().erase(it);
// RenderAccessibilityManager keeps a reference to the RenderFrame that owns // it, so we need to clear the pointer to prevent invalid access after the // frame gets closed and deleted.
render_accessibility_manager_.reset();
// |frame_| may not be referenced after this, so clear the pointer since // the actual WebLocalFrame may not be deleted immediately and other methods // may try to access it.
frame_->Close();
frame_ = nullptr;
if (mhtml_body_loader_client_) {
mhtml_body_loader_client_->Detach();
mhtml_body_loader_client_.reset();
}
deletethis; // [0] // Object is invalid after this point.
}
voidReadAnythingUntrustedPageHandler::LogTextStyle() {
// 判断browser_是否为空,非空则调用其来获取profile// 由于browser_为裸指针,所以在Browser被析构函数析构后,browser_很有可能为非空// 跟上面的render_frame类似,需要在调用前,想办法将browser_析构,render_frame可以通过刷新页面来析构// browser_不确定if (!browser_ || !browser_->profile()->GetPrefs()) {
return;
}
// This is called when the side panel closes, so retrieving the values from// preferences won't happen very often.
PrefService* prefs = browser_->profile()->GetPrefs();
int maximum_font_scale_logging =
GetNormalizedFontScale(kReadAnythingMaximumFontScale);
double font_scale =
prefs->GetDouble(prefs::kAccessibilityReadAnythingFontScale);
[527978:527978:0315/151833.088083:ERROR:debug_logger.h(25)] WebUIBubbleDialogView destructor called
[527978:527978:0315/151835.971764:ERROR:debug_logger.h(25)] ChromeComposeDialogController destructor called
[527978:527978:0315/151839.479424:ERROR:debug_logger.h(25)] WebUIBubbleDialogView destructor called
[527978:527978:0315/151846.823749:ERROR:debug_logger.h(25)] ChromeComposeDialogController destructor called
// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.h;l=52;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090classOmniboxPopupUI : publicui::MojoWebUIController {
public:explicitOmniboxPopupUI(content::WebUI* web_ui);
// ...// Instantiates the implementor of color_change_listener::mojom::PageHandler// mojo interface passing the pending receiver that will be internally bound.voidBindInterface(
mojo::PendingReceiver<color_change_listener::mojom::PageHandler>
pending_receiver);
RealboxHandler* handler() { return handler_.get(); }
private:
std::unique_ptr<RealboxHandler> handler_; <----- [3]
// https://source.chromium.org/chromium/chromium/src/+/main:chrome/browser/ui/webui/realbox/realbox_handler.h;l=46;drc=f4a00cc248dd2dc8ec8759fb51620d47b5114090classRealboxHandler : publicomnibox::mojom::PageHandler,
public AutocompleteController::Observer,
public LocationBarModel {
public:// Note: `omnibox_controller` may be null for the Realbox, in which case// an internally owned controller is created and used.RealboxHandler(
mojo::PendingReceiver<omnibox::mojom::PageHandler> pending_page_handler,
Profile* profile,
content::WebContents* web_contents,
MetricsReporter* metrics_reporter,
OmniboxController* omnibox_controller);
// Handle observers to be notified of WebUI changes.voidAddObserver(OmniboxWebUIPopupChangeObserver* observer);
voidRemoveObserver(OmniboxWebUIPopupChangeObserver* observer);
boolHasObserver(const OmniboxWebUIPopupChangeObserver* observer) const;
private:
OmniboxEditModel* edit_model() const;
AutocompleteController* autocomplete_controller() const; <------ [4]
chromium issues分析(001-005)
update: 2024.03.21
001-issue-40073847
issue 40073847
模块:
UI>Accessibility
问题及分析
RenderFrameImpl::FrameDetached
会释放不再使用的render_frame
释放完了之后
ReadAnythingAppController::OnActiveAXTreeIDChanged
使用,导致UAF
,修复代码主要是添加了在调用render_frame
之前的判断复现步骤
tab
页中打开:chrome-untrusted://read-anything-side-panel.top-chrome/
修复方法:在代码中增加对
render_frame
指针的判断,为空则返回这类漏洞的寻找方法总结:
FrameDetached
处设置栈回溯日志content::RenderFrame* render_frame
这样的代码,render_frame
作为其参数或者类成员render_frame
处添加日志输出,查看触发条件Detached
释放对应的render_frame
render_frame
触发UAF002-issue-40936128
issue-4093612
模块:
UI>Accessibility>ReadingMode
问题及分析
在
40073847
修复的基础上发现的漏洞,在RenderFrameImpl::FrameDetached
释放指针之后,并没有直接删除变量render_frame
,所以在做render_frame
指针判空的时候,其并不为空,该类问题为raw_ptr
问题,当判断为非空再次访问UAF
复现步骤
修复方法:不再使用
render_frame
指针,而是使用render_frame_id
来找到对应的render_frame
,如果不是则返回该漏洞为典型问题,应该很多这种类型的漏洞
该问题类似于该代码
以上两个问题主因都是因为
ReadAnythingAppController
存放了render_frame
的裸指针,在对裸指针使用不当时导致内存问题,触发的条件都是需要在使用render_frame之前释放其所占用内存
40073847:直接后退,释放
render_frame
40936128:在打开的
chrome-untrusted://read-anything-side-panel.top-chrome/
页面,直接访问另一个url,触发释放render_frame003-issue-40936633
issue 40936633
模块:
UI>Browser>TopChrome>SidePanel
问题及分析
这个漏洞依然存在于阅读模式,在类
ReadAnythingUntrustedPageHandler
中定义了成员变量raw_ptr<Browser> browser_
复现步骤
./Chromium --user-data-dir=./tmp http://127.0.0.1:8605/poc.html about:blank
SidePanel
, chooseReadAnything
, then drag and merge the poc.html, close theSidePanel
这个需要调试,不能确定
browser_
什么时候会被析构,这个可能需要详细调试一下,因为browser_
以后还会在别的组件上发生问题,需要理清其中的内容修复方法:将
browser_
的指针类型由raw_ptr
改为WeakPtr
004-issue-40076226
issue-40076226
模块:
UI>Browser>ContentSuggestions
根据其中的复现叙述,总是没办法复现,但是可以通过以下方式复现
./out/Release/chrome --enable-features=Compose,ComposeNudge --user-dir=/tmp/data http://127.0.0.1:8000/poc.html about:blank
Ctrl+W
,之后关闭chrome
,成功复现这个问题没有办法直观看出,所以先复现,编译
120.0.6090.0
的代码栈回溯
根据栈分析崩溃原因
[2]
初始化ChromeComposeDialogController
的成员变量bubble_wrapper_
[3]
会将bubble_wrapper_
传给WebUIBubbleDialogView
的成员变量contents_wrapper_
,其类型raw_ptr<BubbleContentsWrapper>
正常的处理逻辑日志信息
WebUIBubbleDialogView destructor
先被调用,然后ChromeComposeDialogController destructor
被调用如果
ChromeComposeDialogController
的析构函数在WebUIBubbleDialogView::ClearContentsWrapper
之前被调用,就会造成UAF
成功触发的日志信息
想办法来造成这种情况,得看一下
ChromeComposeDialogController
的析构函数会在什么时候被调用通过上述的箭头所指信息可以发现,想要触发
ChromeComposeDialogController::~ChromeComposeDialogController()
,需要当前网页的WebContents
析构,可以发现,上述复现过程应该是通过
Ctrl+W
直接关闭tab
页面从而触发当前网页的WebContents
析构,其实通过刷新网页同样可以触发WebContents
析构,但是不能通过点击刷新来刷新,因为点击的话会先触发
WebUIBubbleDialogView
析构,可以通过Ctrl+Shift+R
来实现整体的
UAF
逻辑类似于005-issue-40071901
issue-40071901
模块:
UI>Browser>Omnibox
漏洞代码
上述代码中用到了设计模式中的观察者模式,观察者模式是一种设计模式,
允许一个对象(称为“观察者
Observer
”)自动接收到另一个对象(称为“主题Subject
”或“被观察者”)状态变化的通知。实现这个模式通常涉及创建一个观察者接口,它定义了接收更新的方法。被观察者维护一个观察者列表,
当其状态发生变化时,会遍历这个列表并调用每个观察者的更新方法。
其中通过
[1]
可以看出OmniboxController
作为Observer
,AutocompleteController
作为Subject
其中
OmniboxPopupUI
有成员变量std::unique_ptr<RealboxHandler> handler_;
,通过分析代码[3,4]
,可以发现handler_
可以视为Observer
,那么简单点考虑
OmniboxPopupUI
作为Observer
将上述的整体逻辑简化,可以更好的理解其中的观察者模式
通过简化的代码可以发现,如果
Subject
在Observer
之前释放,那么再释放Observer
时就会导致UAF
具体测试观察者模式先释放
Subject
后释放Observer
导致UAF
的效果,可以看我的测试代码The text was updated successfully, but these errors were encountered: