Avlyssnande proxy — hur en proxy ser din trafik
Observera konceptet
En proxy är en mellanhand. I stället för att din klient pratar direkt med servern, går trafiken via proxyn, som vidarebefordrar den. Servern ser proxyns adress som avsändare, inte din.
Klient Proxyserver Målserver
10.10.1.4 ───────▶ 192.168.4.2 ───────▶ exempel.se
(ser och kan
ändra allt
som passerar)
Vad koden gör — förklaring rad för rad
Inte kod, utan en ritning. Den visar var en proxy sitter: all trafik mellan dig och målservern passerar genom den, vilket är varför den kan läsa och ändra allt som går förbi.
- Klient
- Din dator, med sin adress i nätet.
- Proxyserver
- Mellanhanden. Målservern ser proxyns adress som avsändare, inte din.
- ───▶
- Pilarna visar trafikens riktning. Observera att det inte finns någon pil direkt från klient till målserver.
Detta är inte i sig något skadligt — proxyservrar används dagligen för caching, filtrering, lastbalansering och företagsbrandväggar. Men samma egenskap som gör en proxy användbar, nämligen att allt passerar genom den, gör den också till en position där trafik kan läsas och ändras.
Vid auktoriserad webbapplikationstestning används en avlyssnande proxy (Burp Suite eller OWASP ZAP) medvetet: testaren placerar den mellan sin egen webbläsare och applikationen för att kunna se exakt vad applikationen skickar och tar emot. Det är så man upptäcker att en applikation litar på data som egentligen kommer från klienten och därmed kan manipuleras.
Praktiskt moment
Konfigurera OWASP ZAP eller Burp Suite Community i din labbmiljö och ställ in webbläsaren att gå via proxyn. Installera proxyns CA-certifikat i webbläsaren så att även HTTPS-trafik kan visas.
Surfa till din labbapplikation och studera i proxyns historik:
- Vilka fält skickas som webbläsaren inte visar? (dolda formulärfält, kakor, headers)
- Vilka värden skickas som applikationen rimligen borde bestämma själv på serversidan? (priser, roller, användar-ID:n, rabatter)
Det sista är kärnan: allt som kommer från klienten är data som användaren kontrollerar, oavsett om gränssnittet ser låst ut.
Bygg försvaret
Två olika försvarsfrågor hör hemma här.
1. Mot proxyavlyssning i transporten: TLS (Lab 1) gör att en passiv mellanhand inte kan läsa innehållet. För att en proxy ska kunna läsa HTTPS måste dess certifikat vara betrott av klienten — vilket är precis varför du var tvungen att installera ZAP:s certifikat manuellt. Certificate pinning i mobilappar tar detta ett steg längre: appen accepterar bara ett specifikt, förväntat certifikat och vägrar ansluta även om operativsystemet litar på ett annat.
2. Mot manipulerad klientdata — det viktigare försvaret: Applikationen får aldrig lita på värden som kommer från klienten. Mönstret ser ut så här:
# Sårbart: priset kommer från klienten
def checkout(request):
pris = request.POST["pris"] # användaren kan sätta vad som helst
debitera(request.user, pris)
# Säkert: klienten anger VAD, servern avgör HUR MYCKET
def checkout(request):
produkt_id = request.POST["produkt_id"]
produkt = Produkt.objects.get(id=produkt_id)
debitera(request.user, produkt.pris) # priset hämtas på serversidan
Vad koden gör — förklaring rad för rad
Två versioner av samma funktion i Python — först den sårbara, sedan den säkra. Skillnaden är var priset kommer ifrån. Det är kursens viktigaste princip i sex rader kod.
- def checkout(request):
- def betyder "definiera en funktion". En funktion är ett namngivet recept som kan köras när som helst. Här heter receptet checkout och tar emot ett anrop från en besökare, kallat request.
- request.POST["pris"]
- Hämtar fältet som hette pris ur det besökaren skickade in. Problemet: besökaren bestämmer helt vad som står där.
- # Sårbart / # Säkert
- Kommentarer. Raden med # körs inte, den förklarar bara.
- Produkt.objects.get(id=produkt_id)
- Slår upp produkten i databasen utifrån dess id-nummer. Nu är det databasen som talar om vad produkten är.
- debitera(request.user, produkt.pris)
- Drar beloppet — men nu från produkt.pris, hämtat ur databasen, i stället för från det belopp besökaren skickade.
Samma princip gäller roller (is_admin får aldrig komma från ett formulärfält), rabatter, lagersaldon och behörigheter.
Verifiera och dokumentera
Gå igenom din egen eller en exempelapplikations anrop och gör en lista över varje fält som skickas från klienten. För varje fält: bestämmer servern detta värde själv, eller litar den på klienten? Fält i den andra kategorin är kandidater för granskning.
Reflektionsfrågor: Varför kan en avlyssnande proxy visa HTTPS-trafik i ditt labb, men inte mot en godtycklig sajt på internet? Vad säger det om vem man måste lita på i en certifikatkedja?
Kunskapskontroll
Välj ett svar per fråga. Du får återkoppling direkt, och avsnittet markeras som klart när alla frågor är besvarade.
1Varför måste du installera proxyns CA-certifikat i webbläsaren för att kunna se HTTPS-trafik?
2Vad är det viktigaste försvaret mot att en användare manipulerar data som skickas från klienten?
3Ett dolt formulärfält i HTML är ur säkerhetssynpunkt:
The intercepting proxy — how a proxy sees your traffic
Observe the concept
A proxy is an intermediary. Instead of your client talking directly to the server, traffic goes via the proxy, which forwards it. The server sees the proxy's address as the sender, not yours.
Client Proxy server Target server
10.10.1.4 ───────▶ 192.168.4.2 ───────▶ example.com
(sees and can
modify everything
passing through)
What this code does — line by line
Not code, but a drawing. It shows where a proxy sits: all traffic between you and the target server passes through it, which is why it can read and alter everything going by.
- Client
- Your machine, with its address on the network.
- Proxy server
- The intermediary. The target server sees the proxy's address as the sender, not yours.
- ───▶
- The arrows show the direction of traffic. Note there is no arrow directly from client to target server.
This is not inherently malicious — proxies are used daily for caching, filtering, load balancing and corporate firewalls. But the same property that makes a proxy useful, namely that everything passes through it, also makes it a position from which traffic can be read and altered.
In authorized web application testing an intercepting proxy (Burp Suite or OWASP ZAP) is used deliberately: the tester places it between their own browser and the application to see exactly what the application sends and receives. This is how you discover that an application trusts data that actually originates from the client and can therefore be manipulated.
Hands-on
Configure OWASP ZAP or Burp Suite Community in your lab and point your browser at the proxy. Install the proxy's CA certificate in the browser so HTTPS traffic is visible too.
Browse your lab application and study the proxy history:
- Which fields are sent that the browser never displays? (hidden form fields, cookies, headers)
- Which values are sent that the application should reasonably determine server-side? (prices, roles, user IDs, discounts)
That last point is the core lesson: anything coming from the client is data the user controls, no matter how locked down the interface looks.
Build the defense
Two distinct defensive questions belong here.
1. Against interception in transit: TLS (Lab 1) means a passive intermediary cannot read the content. For a proxy to read HTTPS, its certificate must be trusted by the client — which is exactly why you had to install ZAP's certificate manually. Certificate pinning in mobile apps takes this further: the app accepts only a specific expected certificate and refuses to connect even if the operating system trusts another.
2. Against manipulated client data — the more important defense: The application must never trust values arriving from the client. The pattern looks like this:
# Vulnerable: the price comes from the client
def checkout(request):
price = request.POST["price"] # user can set anything
charge(request.user, price)
# Safe: the client says WHAT, the server decides HOW MUCH
def checkout(request):
product_id = request.POST["product_id"]
product = Product.objects.get(id=product_id)
charge(request.user, product.price) # price resolved server-side
What this code does — line by line
Two versions of the same Python function — the vulnerable one first, then the safe one. The difference is where the price comes from. It is the course's most important principle in six lines of code.
- def checkout(request):
- def means "define a function". A function is a named recipe that can be run whenever needed. Here the recipe is called checkout and receives a visitor's request, called request.
- request.POST["price"]
- Fetches the field named price out of what the visitor submitted. The problem: the visitor decides entirely what it says.
- # Vulnerable / # Safe
- Comments. A line starting with # does not run, it only explains.
- Product.objects.get(id=product_id)
- Looks the product up in the database by its id number. Now the database is what says what the product is.
- charge(request.user, product.price)
- Charges the amount — but now from product.price, taken from the database, instead of the amount the visitor sent.
The same principle applies to roles (is_admin must never come from a form field), discounts, stock levels and permissions.
Verify and document
Walk through your own or a sample application's requests and list every field sent from the client. For each one ask: does the server determine this value itself, or does it trust the client? Fields in the second category are candidates for review.
Reflection: Why can an intercepting proxy display HTTPS traffic in your lab, but not against an arbitrary site on the internet? What does that tell you about who you must trust in a certificate chain?
Knowledge check
Pick one answer per question. You get feedback immediately, and the unit is marked complete once every question is answered.
1Why must you install the proxy's CA certificate in the browser to see HTTPS traffic?
2What is the most important defense against a user manipulating data sent from the client?
3From a security standpoint, a hidden HTML form field is: