Workarounds for Sites page to update standard object?

You can code the controller as without sharing and copy the values into and out of an intermediate object.

The documentation for with sharing states:

The with sharing keyword allows you to specify that the sharing rules for the current user be taken into account for a class. You have to explicitly set this keyword for the class because Apex code runs in system context. In system context, Apex code has access to all objects and fields— object permissions, field-level security, sharing rules aren’t applied for the current user.

So, by specifying without sharing the class runs in system context and has access to the Opportunity. Note that doesn't apply to the Visualforce page, itself, so you couldn't access the Opportunity directly in it via an inputField.

Example:

public without sharing class OpportunityController {
    public UsableOpp usableOpp { get; set; }

    public OpportunityController() {
        usableOpp = new UsableOpp();
    }

    public class UsableOpp {
        public String name { get; set; }
        public Decimal amount { get; set; }
    }

    public PageReference doSubmit() {
        Opportunity opp = new Opportunity();
        opp.Name = usableOpp.name;
        opp.StageName = 'Brand New';
        opp.CloseDate = Date.today();
        opp.Amount = usableOpp.amount;

        insert opp;

        return null;
    }
}

In your Visualforce:

<apex:page controller="OpportunityController">
    <apex:form >
        Name: <apex:inputText value="{!usableOpp.Name}"/><br />
        Amount: <apex:inputText value="{!usableOpp.Amount}"/><br />
        <apex:commandButton value="Submit" action="{!doSubmit}"/>
    </apex:form>
</apex:page>

You lose all benefits of the security model in Salesforce. You’ll have to manually ensure that the Opportunities are only viewable/editable by the allowed users on the site.